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 static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; 20 21 import static java.lang.Math.max; 22 23 import android.animation.AnimatorInflater; 24 import android.animation.StateListAnimator; 25 import android.annotation.CallSuper; 26 import android.annotation.ColorInt; 27 import android.annotation.DrawableRes; 28 import android.annotation.FloatRange; 29 import android.annotation.IdRes; 30 import android.annotation.IntDef; 31 import android.annotation.IntRange; 32 import android.annotation.LayoutRes; 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.annotation.Size; 36 import android.annotation.TestApi; 37 import android.annotation.UiThread; 38 import android.content.ClipData; 39 import android.content.Context; 40 import android.content.ContextWrapper; 41 import android.content.Intent; 42 import android.content.res.ColorStateList; 43 import android.content.res.Configuration; 44 import android.content.res.Resources; 45 import android.content.res.TypedArray; 46 import android.graphics.Bitmap; 47 import android.graphics.Canvas; 48 import android.graphics.Color; 49 import android.graphics.Insets; 50 import android.graphics.Interpolator; 51 import android.graphics.LinearGradient; 52 import android.graphics.Matrix; 53 import android.graphics.Outline; 54 import android.graphics.Paint; 55 import android.graphics.PixelFormat; 56 import android.graphics.Point; 57 import android.graphics.PorterDuff; 58 import android.graphics.PorterDuffXfermode; 59 import android.graphics.Rect; 60 import android.graphics.RectF; 61 import android.graphics.Region; 62 import android.graphics.Shader; 63 import android.graphics.drawable.ColorDrawable; 64 import android.graphics.drawable.Drawable; 65 import android.hardware.display.DisplayManagerGlobal; 66 import android.net.Uri; 67 import android.os.Build; 68 import android.os.Bundle; 69 import android.os.Handler; 70 import android.os.IBinder; 71 import android.os.Message; 72 import android.os.Parcel; 73 import android.os.Parcelable; 74 import android.os.RemoteException; 75 import android.os.SystemClock; 76 import android.os.SystemProperties; 77 import android.os.Trace; 78 import android.text.InputType; 79 import android.text.TextUtils; 80 import android.util.AttributeSet; 81 import android.util.FloatProperty; 82 import android.util.LayoutDirection; 83 import android.util.Log; 84 import android.util.LongSparseLongArray; 85 import android.util.Pools.SynchronizedPool; 86 import android.util.Property; 87 import android.util.SparseArray; 88 import android.util.StateSet; 89 import android.util.SuperNotCalledException; 90 import android.util.TypedValue; 91 import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 92 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 93 import android.view.AccessibilityIterators.TextSegmentIterator; 94 import android.view.AccessibilityIterators.WordTextSegmentIterator; 95 import android.view.ContextMenu.ContextMenuInfo; 96 import android.view.accessibility.AccessibilityEvent; 97 import android.view.accessibility.AccessibilityEventSource; 98 import android.view.accessibility.AccessibilityManager; 99 import android.view.accessibility.AccessibilityNodeInfo; 100 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 101 import android.view.accessibility.AccessibilityNodeProvider; 102 import android.view.accessibility.AccessibilityWindowInfo; 103 import android.view.animation.Animation; 104 import android.view.animation.AnimationUtils; 105 import android.view.animation.Transformation; 106 import android.view.autofill.AutofillId; 107 import android.view.autofill.AutofillManager; 108 import android.view.autofill.AutofillValue; 109 import android.view.inputmethod.EditorInfo; 110 import android.view.inputmethod.InputConnection; 111 import android.view.inputmethod.InputMethodManager; 112 import android.widget.Checkable; 113 import android.widget.FrameLayout; 114 import android.widget.ScrollBarDrawable; 115 116 import com.android.internal.R; 117 import com.android.internal.view.TooltipPopup; 118 import com.android.internal.view.menu.MenuBuilder; 119 import com.android.internal.widget.ScrollBarUtils; 120 121 import com.google.android.collect.Lists; 122 import com.google.android.collect.Maps; 123 124 import java.lang.annotation.Retention; 125 import java.lang.annotation.RetentionPolicy; 126 import java.lang.ref.WeakReference; 127 import java.lang.reflect.Field; 128 import java.lang.reflect.InvocationTargetException; 129 import java.lang.reflect.Method; 130 import java.lang.reflect.Modifier; 131 import java.util.ArrayList; 132 import java.util.Arrays; 133 import java.util.Calendar; 134 import java.util.Collection; 135 import java.util.Collections; 136 import java.util.HashMap; 137 import java.util.List; 138 import java.util.Locale; 139 import java.util.Map; 140 import java.util.concurrent.CopyOnWriteArrayList; 141 import java.util.concurrent.atomic.AtomicInteger; 142 import java.util.function.Predicate; 143 144 /** 145 * <p> 146 * This class represents the basic building block for user interface components. A View 147 * occupies a rectangular area on the screen and is responsible for drawing and 148 * event handling. View is the base class for <em>widgets</em>, which are 149 * used to create interactive UI components (buttons, text fields, etc.). The 150 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 151 * are invisible containers that hold other Views (or other ViewGroups) and define 152 * their layout properties. 153 * </p> 154 * 155 * <div class="special reference"> 156 * <h3>Developer Guides</h3> 157 * <p>For information about using this class to develop your application's user interface, 158 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 159 * </div> 160 * 161 * <a name="Using"></a> 162 * <h3>Using Views</h3> 163 * <p> 164 * All of the views in a window are arranged in a single tree. You can add views 165 * either from code or by specifying a tree of views in one or more XML layout 166 * files. There are many specialized subclasses of views that act as controls or 167 * are capable of displaying text, images, or other content. 168 * </p> 169 * <p> 170 * Once you have created a tree of views, there are typically a few types of 171 * common operations you may wish to perform: 172 * <ul> 173 * <li><strong>Set properties:</strong> for example setting the text of a 174 * {@link android.widget.TextView}. The available properties and the methods 175 * that set them will vary among the different subclasses of views. Note that 176 * properties that are known at build time can be set in the XML layout 177 * files.</li> 178 * <li><strong>Set focus:</strong> The framework will handle moving focus in 179 * response to user input. To force focus to a specific view, call 180 * {@link #requestFocus}.</li> 181 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 182 * that will be notified when something interesting happens to the view. For 183 * example, all views will let you set a listener to be notified when the view 184 * gains or loses focus. You can register such a listener using 185 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 186 * Other view subclasses offer more specialized listeners. For example, a Button 187 * exposes a listener to notify clients when the button is clicked.</li> 188 * <li><strong>Set visibility:</strong> You can hide or show views using 189 * {@link #setVisibility(int)}.</li> 190 * </ul> 191 * </p> 192 * <p><em> 193 * Note: The Android framework is responsible for measuring, laying out and 194 * drawing views. You should not call methods that perform these actions on 195 * views yourself unless you are actually implementing a 196 * {@link android.view.ViewGroup}. 197 * </em></p> 198 * 199 * <a name="Lifecycle"></a> 200 * <h3>Implementing a Custom View</h3> 201 * 202 * <p> 203 * To implement a custom view, you will usually begin by providing overrides for 204 * some of the standard methods that the framework calls on all views. You do 205 * not need to override all of these methods. In fact, you can start by just 206 * overriding {@link #onDraw(android.graphics.Canvas)}. 207 * <table border="2" width="85%" align="center" cellpadding="5"> 208 * <thead> 209 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 210 * </thead> 211 * 212 * <tbody> 213 * <tr> 214 * <td rowspan="2">Creation</td> 215 * <td>Constructors</td> 216 * <td>There is a form of the constructor that are called when the view 217 * is created from code and a form that is called when the view is 218 * inflated from a layout file. The second form should parse and apply 219 * any attributes defined in the layout file. 220 * </td> 221 * </tr> 222 * <tr> 223 * <td><code>{@link #onFinishInflate()}</code></td> 224 * <td>Called after a view and all of its children has been inflated 225 * from XML.</td> 226 * </tr> 227 * 228 * <tr> 229 * <td rowspan="3">Layout</td> 230 * <td><code>{@link #onMeasure(int, int)}</code></td> 231 * <td>Called to determine the size requirements for this view and all 232 * of its children. 233 * </td> 234 * </tr> 235 * <tr> 236 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 237 * <td>Called when this view should assign a size and position to all 238 * of its children. 239 * </td> 240 * </tr> 241 * <tr> 242 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 243 * <td>Called when the size of this view has changed. 244 * </td> 245 * </tr> 246 * 247 * <tr> 248 * <td>Drawing</td> 249 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 250 * <td>Called when the view should render its content. 251 * </td> 252 * </tr> 253 * 254 * <tr> 255 * <td rowspan="4">Event processing</td> 256 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 257 * <td>Called when a new hardware key event occurs. 258 * </td> 259 * </tr> 260 * <tr> 261 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 262 * <td>Called when a hardware key up event occurs. 263 * </td> 264 * </tr> 265 * <tr> 266 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 267 * <td>Called when a trackball motion event occurs. 268 * </td> 269 * </tr> 270 * <tr> 271 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 272 * <td>Called when a touch screen motion event occurs. 273 * </td> 274 * </tr> 275 * 276 * <tr> 277 * <td rowspan="2">Focus</td> 278 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 279 * <td>Called when the view gains or loses focus. 280 * </td> 281 * </tr> 282 * 283 * <tr> 284 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 285 * <td>Called when the window containing the view gains or loses focus. 286 * </td> 287 * </tr> 288 * 289 * <tr> 290 * <td rowspan="3">Attaching</td> 291 * <td><code>{@link #onAttachedToWindow()}</code></td> 292 * <td>Called when the view is attached to a window. 293 * </td> 294 * </tr> 295 * 296 * <tr> 297 * <td><code>{@link #onDetachedFromWindow}</code></td> 298 * <td>Called when the view is detached from its window. 299 * </td> 300 * </tr> 301 * 302 * <tr> 303 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 304 * <td>Called when the visibility of the window containing the view 305 * has changed. 306 * </td> 307 * </tr> 308 * </tbody> 309 * 310 * </table> 311 * </p> 312 * 313 * <a name="IDs"></a> 314 * <h3>IDs</h3> 315 * Views may have an integer id associated with them. These ids are typically 316 * assigned in the layout XML files, and are used to find specific views within 317 * the view tree. A common pattern is to: 318 * <ul> 319 * <li>Define a Button in the layout file and assign it a unique ID. 320 * <pre> 321 * <Button 322 * android:id="@+id/my_button" 323 * android:layout_width="wrap_content" 324 * android:layout_height="wrap_content" 325 * android:text="@string/my_button_text"/> 326 * </pre></li> 327 * <li>From the onCreate method of an Activity, find the Button 328 * <pre class="prettyprint"> 329 * Button myButton = findViewById(R.id.my_button); 330 * </pre></li> 331 * </ul> 332 * <p> 333 * View IDs need not be unique throughout the tree, but it is good practice to 334 * ensure that they are at least unique within the part of the tree you are 335 * searching. 336 * </p> 337 * 338 * <a name="Position"></a> 339 * <h3>Position</h3> 340 * <p> 341 * The geometry of a view is that of a rectangle. A view has a location, 342 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 343 * two dimensions, expressed as a width and a height. The unit for location 344 * and dimensions is the pixel. 345 * </p> 346 * 347 * <p> 348 * It is possible to retrieve the location of a view by invoking the methods 349 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 350 * coordinate of the rectangle representing the view. The latter returns the 351 * top, or Y, coordinate of the rectangle representing the view. These methods 352 * both return the location of the view relative to its parent. For instance, 353 * when getLeft() returns 20, that means the view is located 20 pixels to the 354 * right of the left edge of its direct parent. 355 * </p> 356 * 357 * <p> 358 * In addition, several convenience methods are offered to avoid unnecessary 359 * computations, namely {@link #getRight()} and {@link #getBottom()}. 360 * These methods return the coordinates of the right and bottom edges of the 361 * rectangle representing the view. For instance, calling {@link #getRight()} 362 * is similar to the following computation: <code>getLeft() + getWidth()</code> 363 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 364 * </p> 365 * 366 * <a name="SizePaddingMargins"></a> 367 * <h3>Size, padding and margins</h3> 368 * <p> 369 * The size of a view is expressed with a width and a height. A view actually 370 * possess two pairs of width and height values. 371 * </p> 372 * 373 * <p> 374 * The first pair is known as <em>measured width</em> and 375 * <em>measured height</em>. These dimensions define how big a view wants to be 376 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 377 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 378 * and {@link #getMeasuredHeight()}. 379 * </p> 380 * 381 * <p> 382 * The second pair is simply known as <em>width</em> and <em>height</em>, or 383 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 384 * dimensions define the actual size of the view on screen, at drawing time and 385 * after layout. These values may, but do not have to, be different from the 386 * measured width and height. The width and height can be obtained by calling 387 * {@link #getWidth()} and {@link #getHeight()}. 388 * </p> 389 * 390 * <p> 391 * To measure its dimensions, a view takes into account its padding. The padding 392 * is expressed in pixels for the left, top, right and bottom parts of the view. 393 * Padding can be used to offset the content of the view by a specific amount of 394 * pixels. For instance, a left padding of 2 will push the view's content by 395 * 2 pixels to the right of the left edge. Padding can be set using the 396 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 397 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 398 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 399 * {@link #getPaddingEnd()}. 400 * </p> 401 * 402 * <p> 403 * Even though a view can define a padding, it does not provide any support for 404 * margins. However, view groups provide such a support. Refer to 405 * {@link android.view.ViewGroup} and 406 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 407 * </p> 408 * 409 * <a name="Layout"></a> 410 * <h3>Layout</h3> 411 * <p> 412 * Layout is a two pass process: a measure pass and a layout pass. The measuring 413 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 414 * of the view tree. Each view pushes dimension specifications down the tree 415 * during the recursion. At the end of the measure pass, every view has stored 416 * its measurements. The second pass happens in 417 * {@link #layout(int,int,int,int)} and is also top-down. During 418 * this pass each parent is responsible for positioning all of its children 419 * using the sizes computed in the measure pass. 420 * </p> 421 * 422 * <p> 423 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 424 * {@link #getMeasuredHeight()} values must be set, along with those for all of 425 * that view's descendants. A view's measured width and measured height values 426 * must respect the constraints imposed by the view's parents. This guarantees 427 * that at the end of the measure pass, all parents accept all of their 428 * children's measurements. A parent view may call measure() more than once on 429 * its children. For example, the parent may measure each child once with 430 * unspecified dimensions to find out how big they want to be, then call 431 * measure() on them again with actual numbers if the sum of all the children's 432 * unconstrained sizes is too big or too small. 433 * </p> 434 * 435 * <p> 436 * The measure pass uses two classes to communicate dimensions. The 437 * {@link MeasureSpec} class is used by views to tell their parents how they 438 * want to be measured and positioned. The base LayoutParams class just 439 * describes how big the view wants to be for both width and height. For each 440 * dimension, it can specify one of: 441 * <ul> 442 * <li> an exact number 443 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 444 * (minus padding) 445 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 446 * enclose its content (plus padding). 447 * </ul> 448 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 449 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 450 * an X and Y value. 451 * </p> 452 * 453 * <p> 454 * MeasureSpecs are used to push requirements down the tree from parent to 455 * child. A MeasureSpec can be in one of three modes: 456 * <ul> 457 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 458 * of a child view. For example, a LinearLayout may call measure() on its child 459 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 460 * tall the child view wants to be given a width of 240 pixels. 461 * <li>EXACTLY: This is used by the parent to impose an exact size on the 462 * child. The child must use this size, and guarantee that all of its 463 * descendants will fit within this size. 464 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 465 * child. The child must guarantee that it and all of its descendants will fit 466 * within this size. 467 * </ul> 468 * </p> 469 * 470 * <p> 471 * To initiate a layout, call {@link #requestLayout}. This method is typically 472 * called by a view on itself when it believes that is can no longer fit within 473 * its current bounds. 474 * </p> 475 * 476 * <a name="Drawing"></a> 477 * <h3>Drawing</h3> 478 * <p> 479 * Drawing is handled by walking the tree and recording the drawing commands of 480 * any View that needs to update. After this, the drawing commands of the 481 * entire tree are issued to screen, clipped to the newly damaged area. 482 * </p> 483 * 484 * <p> 485 * The tree is largely recorded and drawn in order, with parents drawn before 486 * (i.e., behind) their children, with siblings drawn in the order they appear 487 * in the tree. If you set a background drawable for a View, then the View will 488 * draw it before calling back to its <code>onDraw()</code> method. The child 489 * drawing order can be overridden with 490 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order} 491 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views. 492 * </p> 493 * 494 * <p> 495 * To force a view to draw, call {@link #invalidate()}. 496 * </p> 497 * 498 * <a name="EventHandlingThreading"></a> 499 * <h3>Event Handling and Threading</h3> 500 * <p> 501 * The basic cycle of a view is as follows: 502 * <ol> 503 * <li>An event comes in and is dispatched to the appropriate view. The view 504 * handles the event and notifies any listeners.</li> 505 * <li>If in the course of processing the event, the view's bounds may need 506 * to be changed, the view will call {@link #requestLayout()}.</li> 507 * <li>Similarly, if in the course of processing the event the view's appearance 508 * may need to be changed, the view will call {@link #invalidate()}.</li> 509 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 510 * the framework will take care of measuring, laying out, and drawing the tree 511 * as appropriate.</li> 512 * </ol> 513 * </p> 514 * 515 * <p><em>Note: The entire view tree is single threaded. You must always be on 516 * the UI thread when calling any method on any view.</em> 517 * If you are doing work on other threads and want to update the state of a view 518 * from that thread, you should use a {@link Handler}. 519 * </p> 520 * 521 * <a name="FocusHandling"></a> 522 * <h3>Focus Handling</h3> 523 * <p> 524 * The framework will handle routine focus movement in response to user input. 525 * This includes changing the focus as views are removed or hidden, or as new 526 * views become available. Views indicate their willingness to take focus 527 * through the {@link #isFocusable} method. To change whether a view can take 528 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 529 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 530 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 531 * </p> 532 * <p> 533 * Focus movement is based on an algorithm which finds the nearest neighbor in a 534 * given direction. In rare cases, the default algorithm may not match the 535 * intended behavior of the developer. In these situations, you can provide 536 * explicit overrides by using these XML attributes in the layout file: 537 * <pre> 538 * nextFocusDown 539 * nextFocusLeft 540 * nextFocusRight 541 * nextFocusUp 542 * </pre> 543 * </p> 544 * 545 * 546 * <p> 547 * To get a particular view to take focus, call {@link #requestFocus()}. 548 * </p> 549 * 550 * <a name="TouchMode"></a> 551 * <h3>Touch Mode</h3> 552 * <p> 553 * When a user is navigating a user interface via directional keys such as a D-pad, it is 554 * necessary to give focus to actionable items such as buttons so the user can see 555 * what will take input. If the device has touch capabilities, however, and the user 556 * begins interacting with the interface by touching it, it is no longer necessary to 557 * always highlight, or give focus to, a particular view. This motivates a mode 558 * for interaction named 'touch mode'. 559 * </p> 560 * <p> 561 * For a touch capable device, once the user touches the screen, the device 562 * will enter touch mode. From this point onward, only views for which 563 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 564 * Other views that are touchable, like buttons, will not take focus when touched; they will 565 * only fire the on click listeners. 566 * </p> 567 * <p> 568 * Any time a user hits a directional key, such as a D-pad direction, the view device will 569 * exit touch mode, and find a view to take focus, so that the user may resume interacting 570 * with the user interface without touching the screen again. 571 * </p> 572 * <p> 573 * The touch mode state is maintained across {@link android.app.Activity}s. Call 574 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 575 * </p> 576 * 577 * <a name="Scrolling"></a> 578 * <h3>Scrolling</h3> 579 * <p> 580 * The framework provides basic support for views that wish to internally 581 * scroll their content. This includes keeping track of the X and Y scroll 582 * offset as well as mechanisms for drawing scrollbars. See 583 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 584 * {@link #awakenScrollBars()} for more details. 585 * </p> 586 * 587 * <a name="Tags"></a> 588 * <h3>Tags</h3> 589 * <p> 590 * Unlike IDs, tags are not used to identify views. Tags are essentially an 591 * extra piece of information that can be associated with a view. They are most 592 * often used as a convenience to store data related to views in the views 593 * themselves rather than by putting them in a separate structure. 594 * </p> 595 * <p> 596 * Tags may be specified with character sequence values in layout XML as either 597 * a single tag using the {@link android.R.styleable#View_tag android:tag} 598 * attribute or multiple tags using the {@code <tag>} child element: 599 * <pre> 600 * <View ... 601 * android:tag="@string/mytag_value" /> 602 * <View ...> 603 * <tag android:id="@+id/mytag" 604 * android:value="@string/mytag_value" /> 605 * </View> 606 * </pre> 607 * </p> 608 * <p> 609 * Tags may also be specified with arbitrary objects from code using 610 * {@link #setTag(Object)} or {@link #setTag(int, Object)}. 611 * </p> 612 * 613 * <a name="Themes"></a> 614 * <h3>Themes</h3> 615 * <p> 616 * By default, Views are created using the theme of the Context object supplied 617 * to their constructor; however, a different theme may be specified by using 618 * the {@link android.R.styleable#View_theme android:theme} attribute in layout 619 * XML or by passing a {@link ContextThemeWrapper} to the constructor from 620 * code. 621 * </p> 622 * <p> 623 * When the {@link android.R.styleable#View_theme android:theme} attribute is 624 * used in XML, the specified theme is applied on top of the inflation 625 * context's theme (see {@link LayoutInflater}) and used for the view itself as 626 * well as any child elements. 627 * </p> 628 * <p> 629 * In the following example, both views will be created using the Material dark 630 * color scheme; however, because an overlay theme is used which only defines a 631 * subset of attributes, the value of 632 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on 633 * the inflation context's theme (e.g. the Activity theme) will be preserved. 634 * <pre> 635 * <LinearLayout 636 * ... 637 * android:theme="@android:theme/ThemeOverlay.Material.Dark"> 638 * <View ...> 639 * </LinearLayout> 640 * </pre> 641 * </p> 642 * 643 * <a name="Properties"></a> 644 * <h3>Properties</h3> 645 * <p> 646 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 647 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 648 * available both in the {@link Property} form as well as in similarly-named setter/getter 649 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 650 * be used to set persistent state associated with these rendering-related properties on the view. 651 * The properties and methods can also be used in conjunction with 652 * {@link android.animation.Animator Animator}-based animations, described more in the 653 * <a href="#Animation">Animation</a> section. 654 * </p> 655 * 656 * <a name="Animation"></a> 657 * <h3>Animation</h3> 658 * <p> 659 * Starting with Android 3.0, the preferred way of animating views is to use the 660 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 661 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 662 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 663 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 664 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 665 * makes animating these View properties particularly easy and efficient. 666 * </p> 667 * <p> 668 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 669 * You can attach an {@link Animation} object to a view using 670 * {@link #setAnimation(Animation)} or 671 * {@link #startAnimation(Animation)}. The animation can alter the scale, 672 * rotation, translation and alpha of a view over time. If the animation is 673 * attached to a view that has children, the animation will affect the entire 674 * subtree rooted by that node. When an animation is started, the framework will 675 * take care of redrawing the appropriate views until the animation completes. 676 * </p> 677 * 678 * <a name="Security"></a> 679 * <h3>Security</h3> 680 * <p> 681 * Sometimes it is essential that an application be able to verify that an action 682 * is being performed with the full knowledge and consent of the user, such as 683 * granting a permission request, making a purchase or clicking on an advertisement. 684 * Unfortunately, a malicious application could try to spoof the user into 685 * performing these actions, unaware, by concealing the intended purpose of the view. 686 * As a remedy, the framework offers a touch filtering mechanism that can be used to 687 * improve the security of views that provide access to sensitive functionality. 688 * </p><p> 689 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 690 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 691 * will discard touches that are received whenever the view's window is obscured by 692 * another visible window. As a result, the view will not receive touches whenever a 693 * toast, dialog or other window appears above the view's window. 694 * </p><p> 695 * For more fine-grained control over security, consider overriding the 696 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 697 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 698 * </p> 699 * 700 * @attr ref android.R.styleable#View_accessibilityHeading 701 * @attr ref android.R.styleable#View_alpha 702 * @attr ref android.R.styleable#View_background 703 * @attr ref android.R.styleable#View_clickable 704 * @attr ref android.R.styleable#View_contentDescription 705 * @attr ref android.R.styleable#View_drawingCacheQuality 706 * @attr ref android.R.styleable#View_duplicateParentState 707 * @attr ref android.R.styleable#View_id 708 * @attr ref android.R.styleable#View_requiresFadingEdge 709 * @attr ref android.R.styleable#View_fadeScrollbars 710 * @attr ref android.R.styleable#View_fadingEdgeLength 711 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 712 * @attr ref android.R.styleable#View_fitsSystemWindows 713 * @attr ref android.R.styleable#View_isScrollContainer 714 * @attr ref android.R.styleable#View_focusable 715 * @attr ref android.R.styleable#View_focusableInTouchMode 716 * @attr ref android.R.styleable#View_focusedByDefault 717 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 718 * @attr ref android.R.styleable#View_keepScreenOn 719 * @attr ref android.R.styleable#View_keyboardNavigationCluster 720 * @attr ref android.R.styleable#View_layerType 721 * @attr ref android.R.styleable#View_layoutDirection 722 * @attr ref android.R.styleable#View_longClickable 723 * @attr ref android.R.styleable#View_minHeight 724 * @attr ref android.R.styleable#View_minWidth 725 * @attr ref android.R.styleable#View_nextClusterForward 726 * @attr ref android.R.styleable#View_nextFocusDown 727 * @attr ref android.R.styleable#View_nextFocusLeft 728 * @attr ref android.R.styleable#View_nextFocusRight 729 * @attr ref android.R.styleable#View_nextFocusUp 730 * @attr ref android.R.styleable#View_onClick 731 * @attr ref android.R.styleable#View_outlineSpotShadowColor 732 * @attr ref android.R.styleable#View_outlineAmbientShadowColor 733 * @attr ref android.R.styleable#View_padding 734 * @attr ref android.R.styleable#View_paddingHorizontal 735 * @attr ref android.R.styleable#View_paddingVertical 736 * @attr ref android.R.styleable#View_paddingBottom 737 * @attr ref android.R.styleable#View_paddingLeft 738 * @attr ref android.R.styleable#View_paddingRight 739 * @attr ref android.R.styleable#View_paddingTop 740 * @attr ref android.R.styleable#View_paddingStart 741 * @attr ref android.R.styleable#View_paddingEnd 742 * @attr ref android.R.styleable#View_saveEnabled 743 * @attr ref android.R.styleable#View_rotation 744 * @attr ref android.R.styleable#View_rotationX 745 * @attr ref android.R.styleable#View_rotationY 746 * @attr ref android.R.styleable#View_scaleX 747 * @attr ref android.R.styleable#View_scaleY 748 * @attr ref android.R.styleable#View_scrollX 749 * @attr ref android.R.styleable#View_scrollY 750 * @attr ref android.R.styleable#View_scrollbarSize 751 * @attr ref android.R.styleable#View_scrollbarStyle 752 * @attr ref android.R.styleable#View_scrollbars 753 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 754 * @attr ref android.R.styleable#View_scrollbarFadeDuration 755 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 756 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 757 * @attr ref android.R.styleable#View_scrollbarThumbVertical 758 * @attr ref android.R.styleable#View_scrollbarTrackVertical 759 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 760 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 761 * @attr ref android.R.styleable#View_stateListAnimator 762 * @attr ref android.R.styleable#View_transitionName 763 * @attr ref android.R.styleable#View_soundEffectsEnabled 764 * @attr ref android.R.styleable#View_tag 765 * @attr ref android.R.styleable#View_textAlignment 766 * @attr ref android.R.styleable#View_textDirection 767 * @attr ref android.R.styleable#View_transformPivotX 768 * @attr ref android.R.styleable#View_transformPivotY 769 * @attr ref android.R.styleable#View_translationX 770 * @attr ref android.R.styleable#View_translationY 771 * @attr ref android.R.styleable#View_translationZ 772 * @attr ref android.R.styleable#View_visibility 773 * @attr ref android.R.styleable#View_theme 774 * 775 * @see android.view.ViewGroup 776 */ 777 @UiThread 778 public class View implements Drawable.Callback, KeyEvent.Callback, 779 AccessibilityEventSource { 780 private static final boolean DBG = false; 781 782 /** @hide */ 783 public static boolean DEBUG_DRAW = false; 784 785 /** 786 * The logging tag used by this class with android.util.Log. 787 */ 788 protected static final String VIEW_LOG_TAG = "View"; 789 790 /** 791 * When set to true, apps will draw debugging information about their layouts. 792 * 793 * @hide 794 */ 795 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 796 797 /** 798 * When set to true, this view will save its attribute data. 799 * 800 * @hide 801 */ 802 public static boolean mDebugViewAttributes = false; 803 804 /** 805 * Used to mark a View that has no ID. 806 */ 807 public static final int NO_ID = -1; 808 809 /** 810 * Last ID that is given to Views that are no part of activities. 811 * 812 * {@hide} 813 */ 814 public static final int LAST_APP_AUTOFILL_ID = Integer.MAX_VALUE / 2; 815 816 /** 817 * Attribute to find the autofilled highlight 818 * 819 * @see #getAutofilledDrawable() 820 */ 821 private static final int[] AUTOFILL_HIGHLIGHT_ATTR = 822 new int[]{android.R.attr.autofilledHighlight}; 823 824 /** 825 * Signals that compatibility booleans have been initialized according to 826 * target SDK versions. 827 */ 828 private static boolean sCompatibilityDone = false; 829 830 /** 831 * Use the old (broken) way of building MeasureSpecs. 832 */ 833 private static boolean sUseBrokenMakeMeasureSpec = false; 834 835 /** 836 * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED 837 */ 838 static boolean sUseZeroUnspecifiedMeasureSpec = false; 839 840 /** 841 * Ignore any optimizations using the measure cache. 842 */ 843 private static boolean sIgnoreMeasureCache = false; 844 845 /** 846 * Ignore an optimization that skips unnecessary EXACTLY layout passes. 847 */ 848 private static boolean sAlwaysRemeasureExactly = false; 849 850 /** 851 * Relax constraints around whether setLayoutParams() must be called after 852 * modifying the layout params. 853 */ 854 private static boolean sLayoutParamsAlwaysChanged = false; 855 856 /** 857 * Allow setForeground/setBackground to be called (and ignored) on a textureview, 858 * without throwing 859 */ 860 static boolean sTextureViewIgnoresDrawableSetters = false; 861 862 /** 863 * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend 864 * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to 865 * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API 866 * check is implemented for backwards compatibility. 867 * 868 * {@hide} 869 */ 870 protected static boolean sPreserveMarginParamsInLayoutParamConversion; 871 872 /** 873 * Prior to N, when drag enters into child of a view that has already received an 874 * ACTION_DRAG_ENTERED event, the parent doesn't get a ACTION_DRAG_EXITED event. 875 * ACTION_DRAG_LOCATION and ACTION_DROP were delivered to the parent of a view that returned 876 * false from its event handler for these events. 877 * Starting from N, the parent will get ACTION_DRAG_EXITED event before the child gets its 878 * ACTION_DRAG_ENTERED. ACTION_DRAG_LOCATION and ACTION_DROP are never propagated to the parent. 879 * sCascadedDragDrop is true for pre-N apps for backwards compatibility implementation. 880 */ 881 static boolean sCascadedDragDrop; 882 883 /** 884 * Prior to O, auto-focusable didn't exist and widgets such as ListView use hasFocusable 885 * to determine things like whether or not to permit item click events. We can't break 886 * apps that do this just because more things (clickable things) are now auto-focusable 887 * and they would get different results, so give old behavior to old apps. 888 */ 889 static boolean sHasFocusableExcludeAutoFocusable; 890 891 /** 892 * Prior to O, auto-focusable didn't exist and views marked as clickable weren't implicitly 893 * made focusable by default. As a result, apps could (incorrectly) change the clickable 894 * setting of views off the UI thread. Now that clickable can effect the focusable state, 895 * changing the clickable attribute off the UI thread will cause an exception (since changing 896 * the focusable state checks). In order to prevent apps from crashing, we will handle this 897 * specific case and just not notify parents on new focusables resulting from marking views 898 * clickable from outside the UI thread. 899 */ 900 private static boolean sAutoFocusableOffUIThreadWontNotifyParents; 901 902 /** 903 * Prior to P things like setScaleX() allowed passing float values that were bogus such as 904 * Float.NaN. If the app is targetting P or later then passing these values will result in an 905 * exception being thrown. If the app is targetting an earlier SDK version, then we will 906 * silently clamp these values to avoid crashes elsewhere when the rendering code hits 907 * these bogus values. 908 */ 909 private static boolean sThrowOnInvalidFloatProperties; 910 911 /** 912 * Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow. 913 * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface 914 * instead. 915 */ 916 private static boolean sAcceptZeroSizeDragShadow; 917 918 /** @hide */ 919 @IntDef({NOT_FOCUSABLE, FOCUSABLE, FOCUSABLE_AUTO}) 920 @Retention(RetentionPolicy.SOURCE) 921 public @interface Focusable {} 922 923 /** 924 * This view does not want keystrokes. 925 * <p> 926 * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code 927 * android:focusable}. 928 */ 929 public static final int NOT_FOCUSABLE = 0x00000000; 930 931 /** 932 * This view wants keystrokes. 933 * <p> 934 * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code 935 * android:focusable}. 936 */ 937 public static final int FOCUSABLE = 0x00000001; 938 939 /** 940 * This view determines focusability automatically. This is the default. 941 * <p> 942 * Use with {@link #setFocusable(int)} and <a href="#attr_android:focusable">{@code 943 * android:focusable}. 944 */ 945 public static final int FOCUSABLE_AUTO = 0x00000010; 946 947 /** 948 * Mask for use with setFlags indicating bits used for focus. 949 */ 950 private static final int FOCUSABLE_MASK = 0x00000011; 951 952 /** 953 * This view will adjust its padding to fit sytem windows (e.g. status bar) 954 */ 955 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 956 957 /** @hide */ 958 @IntDef({VISIBLE, INVISIBLE, GONE}) 959 @Retention(RetentionPolicy.SOURCE) 960 public @interface Visibility {} 961 962 /** 963 * This view is visible. 964 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 965 * android:visibility}. 966 */ 967 public static final int VISIBLE = 0x00000000; 968 969 /** 970 * This view is invisible, but it still takes up space for layout purposes. 971 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 972 * android:visibility}. 973 */ 974 public static final int INVISIBLE = 0x00000004; 975 976 /** 977 * This view is invisible, and it doesn't take any space for layout 978 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 979 * android:visibility}. 980 */ 981 public static final int GONE = 0x00000008; 982 983 /** 984 * Mask for use with setFlags indicating bits used for visibility. 985 * {@hide} 986 */ 987 static final int VISIBILITY_MASK = 0x0000000C; 988 989 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 990 991 /** 992 * Hint indicating that this view can be autofilled with an email address. 993 * 994 * <p>Can be used with either {@link #setAutofillHints(String[])} or 995 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 996 * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>). 997 * 998 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 999 */ 1000 public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress"; 1001 1002 /** 1003 * Hint indicating that this view can be autofilled with a user's real name. 1004 * 1005 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1006 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1007 * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>). 1008 * 1009 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1010 */ 1011 public static final String AUTOFILL_HINT_NAME = "name"; 1012 1013 /** 1014 * Hint indicating that this view can be autofilled with a username. 1015 * 1016 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1017 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1018 * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>). 1019 * 1020 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1021 */ 1022 public static final String AUTOFILL_HINT_USERNAME = "username"; 1023 1024 /** 1025 * Hint indicating that this view can be autofilled with a password. 1026 * 1027 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1028 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1029 * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>). 1030 * 1031 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1032 */ 1033 public static final String AUTOFILL_HINT_PASSWORD = "password"; 1034 1035 /** 1036 * Hint indicating that this view can be autofilled with a phone number. 1037 * 1038 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1039 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1040 * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>). 1041 * 1042 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1043 */ 1044 public static final String AUTOFILL_HINT_PHONE = "phone"; 1045 1046 /** 1047 * Hint indicating that this view can be autofilled with a postal address. 1048 * 1049 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1050 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1051 * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>). 1052 * 1053 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1054 */ 1055 public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress"; 1056 1057 /** 1058 * Hint indicating that this view can be autofilled with a postal code. 1059 * 1060 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1061 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1062 * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>). 1063 * 1064 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1065 */ 1066 public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode"; 1067 1068 /** 1069 * Hint indicating that this view can be autofilled with a credit card number. 1070 * 1071 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1072 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1073 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>). 1074 * 1075 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1076 */ 1077 public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber"; 1078 1079 /** 1080 * Hint indicating that this view can be autofilled with a credit card security code. 1081 * 1082 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1083 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1084 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>). 1085 * 1086 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1087 */ 1088 public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode"; 1089 1090 /** 1091 * Hint indicating that this view can be autofilled with a credit card expiration date. 1092 * 1093 * <p>It should be used when the credit card expiration date is represented by just one view; 1094 * if it is represented by more than one (for example, one view for the month and another view 1095 * for the year), then each of these views should use the hint specific for the unit 1096 * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}, 1097 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}, 1098 * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}). 1099 * 1100 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1101 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1102 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>). 1103 * 1104 * <p>When annotating a view with this hint, it's recommended to use a date autofill value to 1105 * avoid ambiguity when the autofill service provides a value for it. To understand why a 1106 * value can be ambiguous, consider "April of 2020", which could be represented as either of 1107 * the following options: 1108 * 1109 * <ul> 1110 * <li>{@code "04/2020"} 1111 * <li>{@code "4/2020"} 1112 * <li>{@code "2020/04"} 1113 * <li>{@code "2020/4"} 1114 * <li>{@code "April/2020"} 1115 * <li>{@code "Apr/2020"} 1116 * </ul> 1117 * 1118 * <p>You define a date autofill value for the view by overriding the following methods: 1119 * 1120 * <ol> 1121 * <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}. 1122 * <li>{@link #getAutofillValue()} to return a 1123 * {@link AutofillValue#forDate(long) date autofillvalue}. 1124 * <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue. 1125 * </ol> 1126 * 1127 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1128 */ 1129 public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE = 1130 "creditCardExpirationDate"; 1131 1132 /** 1133 * Hint indicating that this view can be autofilled with a credit card expiration month. 1134 * 1135 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1136 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1137 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>). 1138 * 1139 * <p>When annotating a view with this hint, it's recommended to use a text autofill value 1140 * whose value is the numerical representation of the month, starting on {@code 1} to avoid 1141 * ambiguity when the autofill service provides a value for it. To understand why a 1142 * value can be ambiguous, consider "January", which could be represented as either of 1143 * 1144 * <ul> 1145 * <li>{@code "1"}: recommended way. 1146 * <li>{@code "0"}: if following the {@link Calendar#MONTH} convention. 1147 * <li>{@code "January"}: full name, in English. 1148 * <li>{@code "jan"}: abbreviated name, in English. 1149 * <li>{@code "Janeiro"}: full name, in another language. 1150 * </ul> 1151 * 1152 * <p>Another recommended approach is to use a date autofill value - see 1153 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details. 1154 * 1155 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1156 */ 1157 public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH = 1158 "creditCardExpirationMonth"; 1159 1160 /** 1161 * Hint indicating that this view can be autofilled with a credit card expiration year. 1162 * 1163 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1164 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1165 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>). 1166 * 1167 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1168 */ 1169 public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR = 1170 "creditCardExpirationYear"; 1171 1172 /** 1173 * Hint indicating that this view can be autofilled with a credit card expiration day. 1174 * 1175 * <p>Can be used with either {@link #setAutofillHints(String[])} or 1176 * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the 1177 * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>). 1178 * 1179 * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints. 1180 */ 1181 public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay"; 1182 1183 /** 1184 * Hints for the autofill services that describes the content of the view. 1185 */ 1186 private @Nullable String[] mAutofillHints; 1187 1188 /** 1189 * Autofill id, lazily created on calls to {@link #getAutofillId()}. 1190 */ 1191 private AutofillId mAutofillId; 1192 1193 /** @hide */ 1194 @IntDef(prefix = { "AUTOFILL_TYPE_" }, value = { 1195 AUTOFILL_TYPE_NONE, 1196 AUTOFILL_TYPE_TEXT, 1197 AUTOFILL_TYPE_TOGGLE, 1198 AUTOFILL_TYPE_LIST, 1199 AUTOFILL_TYPE_DATE 1200 }) 1201 @Retention(RetentionPolicy.SOURCE) 1202 public @interface AutofillType {} 1203 1204 /** 1205 * Autofill type for views that cannot be autofilled. 1206 * 1207 * <p>Typically used when the view is read-only; for example, a text label. 1208 * 1209 * @see #getAutofillType() 1210 */ 1211 public static final int AUTOFILL_TYPE_NONE = 0; 1212 1213 /** 1214 * Autofill type for a text field, which is filled by a {@link CharSequence}. 1215 * 1216 * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through 1217 * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a 1218 * {@link View} can be fetched through {@link AutofillValue#getTextValue()}. 1219 * 1220 * @see #getAutofillType() 1221 */ 1222 public static final int AUTOFILL_TYPE_TEXT = 1; 1223 1224 /** 1225 * Autofill type for a togglable field, which is filled by a {@code boolean}. 1226 * 1227 * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through 1228 * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a 1229 * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}. 1230 * 1231 * @see #getAutofillType() 1232 */ 1233 public static final int AUTOFILL_TYPE_TOGGLE = 2; 1234 1235 /** 1236 * Autofill type for a selection list field, which is filled by an {@code int} 1237 * representing the element index inside the list (starting at {@code 0}). 1238 * 1239 * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through 1240 * {@link AutofillValue#forList(int)}, and the value passed to autofill a 1241 * {@link View} can be fetched through {@link AutofillValue#getListValue()}. 1242 * 1243 * <p>The available options in the selection list are typically provided by 1244 * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}. 1245 * 1246 * @see #getAutofillType() 1247 */ 1248 public static final int AUTOFILL_TYPE_LIST = 3; 1249 1250 1251 /** 1252 * Autofill type for a field that contains a date, which is represented by a long representing 1253 * the number of milliseconds since the standard base time known as "the epoch", namely 1254 * January 1, 1970, 00:00:00 GMT (see {@link java.util.Date#getTime()}. 1255 * 1256 * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through 1257 * {@link AutofillValue#forDate(long)}, and the values passed to 1258 * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}. 1259 * 1260 * @see #getAutofillType() 1261 */ 1262 public static final int AUTOFILL_TYPE_DATE = 4; 1263 1264 /** @hide */ 1265 @IntDef(prefix = { "IMPORTANT_FOR_AUTOFILL_" }, value = { 1266 IMPORTANT_FOR_AUTOFILL_AUTO, 1267 IMPORTANT_FOR_AUTOFILL_YES, 1268 IMPORTANT_FOR_AUTOFILL_NO, 1269 IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS, 1270 IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS 1271 }) 1272 @Retention(RetentionPolicy.SOURCE) 1273 public @interface AutofillImportance {} 1274 1275 /** 1276 * Automatically determine whether a view is important for autofill. 1277 * 1278 * @see #isImportantForAutofill() 1279 * @see #setImportantForAutofill(int) 1280 */ 1281 public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0; 1282 1283 /** 1284 * The view is important for autofill, and its children (if any) will be traversed. 1285 * 1286 * @see #isImportantForAutofill() 1287 * @see #setImportantForAutofill(int) 1288 */ 1289 public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1; 1290 1291 /** 1292 * The view is not important for autofill, but its children (if any) will be traversed. 1293 * 1294 * @see #isImportantForAutofill() 1295 * @see #setImportantForAutofill(int) 1296 */ 1297 public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2; 1298 1299 /** 1300 * The view is important for autofill, but its children (if any) will not be traversed. 1301 * 1302 * @see #isImportantForAutofill() 1303 * @see #setImportantForAutofill(int) 1304 */ 1305 public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4; 1306 1307 /** 1308 * The view is not important for autofill, and its children (if any) will not be traversed. 1309 * 1310 * @see #isImportantForAutofill() 1311 * @see #setImportantForAutofill(int) 1312 */ 1313 public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8; 1314 1315 /** @hide */ 1316 @IntDef(flag = true, prefix = { "AUTOFILL_FLAG_" }, value = { 1317 AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 1318 }) 1319 @Retention(RetentionPolicy.SOURCE) 1320 public @interface AutofillFlags {} 1321 1322 /** 1323 * Flag requesting you to add views that are marked as not important for autofill 1324 * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}. 1325 */ 1326 public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1; 1327 1328 /** 1329 * This view is enabled. Interpretation varies by subclass. 1330 * Use with ENABLED_MASK when calling setFlags. 1331 * {@hide} 1332 */ 1333 static final int ENABLED = 0x00000000; 1334 1335 /** 1336 * This view is disabled. Interpretation varies by subclass. 1337 * Use with ENABLED_MASK when calling setFlags. 1338 * {@hide} 1339 */ 1340 static final int DISABLED = 0x00000020; 1341 1342 /** 1343 * Mask for use with setFlags indicating bits used for indicating whether 1344 * this view is enabled 1345 * {@hide} 1346 */ 1347 static final int ENABLED_MASK = 0x00000020; 1348 1349 /** 1350 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 1351 * called and further optimizations will be performed. It is okay to have 1352 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 1353 * {@hide} 1354 */ 1355 static final int WILL_NOT_DRAW = 0x00000080; 1356 1357 /** 1358 * Mask for use with setFlags indicating bits used for indicating whether 1359 * this view is will draw 1360 * {@hide} 1361 */ 1362 static final int DRAW_MASK = 0x00000080; 1363 1364 /** 1365 * <p>This view doesn't show scrollbars.</p> 1366 * {@hide} 1367 */ 1368 static final int SCROLLBARS_NONE = 0x00000000; 1369 1370 /** 1371 * <p>This view shows horizontal scrollbars.</p> 1372 * {@hide} 1373 */ 1374 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 1375 1376 /** 1377 * <p>This view shows vertical scrollbars.</p> 1378 * {@hide} 1379 */ 1380 static final int SCROLLBARS_VERTICAL = 0x00000200; 1381 1382 /** 1383 * <p>Mask for use with setFlags indicating bits used for indicating which 1384 * scrollbars are enabled.</p> 1385 * {@hide} 1386 */ 1387 static final int SCROLLBARS_MASK = 0x00000300; 1388 1389 /** 1390 * Indicates that the view should filter touches when its window is obscured. 1391 * Refer to the class comments for more information about this security feature. 1392 * {@hide} 1393 */ 1394 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 1395 1396 /** 1397 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 1398 * that they are optional and should be skipped if the window has 1399 * requested system UI flags that ignore those insets for layout. 1400 */ 1401 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 1402 1403 /** 1404 * <p>This view doesn't show fading edges.</p> 1405 * {@hide} 1406 */ 1407 static final int FADING_EDGE_NONE = 0x00000000; 1408 1409 /** 1410 * <p>This view shows horizontal fading edges.</p> 1411 * {@hide} 1412 */ 1413 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 1414 1415 /** 1416 * <p>This view shows vertical fading edges.</p> 1417 * {@hide} 1418 */ 1419 static final int FADING_EDGE_VERTICAL = 0x00002000; 1420 1421 /** 1422 * <p>Mask for use with setFlags indicating bits used for indicating which 1423 * fading edges are enabled.</p> 1424 * {@hide} 1425 */ 1426 static final int FADING_EDGE_MASK = 0x00003000; 1427 1428 /** 1429 * <p>Indicates this view can be clicked. When clickable, a View reacts 1430 * to clicks by notifying the OnClickListener.<p> 1431 * {@hide} 1432 */ 1433 static final int CLICKABLE = 0x00004000; 1434 1435 /** 1436 * <p>Indicates this view is caching its drawing into a bitmap.</p> 1437 * {@hide} 1438 */ 1439 static final int DRAWING_CACHE_ENABLED = 0x00008000; 1440 1441 /** 1442 * <p>Indicates that no icicle should be saved for this view.<p> 1443 * {@hide} 1444 */ 1445 static final int SAVE_DISABLED = 0x000010000; 1446 1447 /** 1448 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 1449 * property.</p> 1450 * {@hide} 1451 */ 1452 static final int SAVE_DISABLED_MASK = 0x000010000; 1453 1454 /** 1455 * <p>Indicates that no drawing cache should ever be created for this view.<p> 1456 * {@hide} 1457 */ 1458 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 1459 1460 /** 1461 * <p>Indicates this view can take / keep focus when int touch mode.</p> 1462 * {@hide} 1463 */ 1464 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 1465 1466 /** @hide */ 1467 @Retention(RetentionPolicy.SOURCE) 1468 @IntDef(prefix = { "DRAWING_CACHE_QUALITY_" }, value = { 1469 DRAWING_CACHE_QUALITY_LOW, 1470 DRAWING_CACHE_QUALITY_HIGH, 1471 DRAWING_CACHE_QUALITY_AUTO 1472 }) 1473 public @interface DrawingCacheQuality {} 1474 1475 /** 1476 * <p>Enables low quality mode for the drawing cache.</p> 1477 * 1478 * @deprecated The view drawing cache was largely made obsolete with the introduction of 1479 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 1480 * layers are largely unnecessary and can easily result in a net loss in performance due to the 1481 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 1482 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 1483 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 1484 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 1485 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 1486 * software-rendered usages are discouraged and have compatibility issues with hardware-only 1487 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 1488 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 1489 * reports or unit testing the {@link PixelCopy} API is recommended. 1490 */ 1491 @Deprecated 1492 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 1493 1494 /** 1495 * <p>Enables high quality mode for the drawing cache.</p> 1496 * 1497 * @deprecated The view drawing cache was largely made obsolete with the introduction of 1498 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 1499 * layers are largely unnecessary and can easily result in a net loss in performance due to the 1500 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 1501 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 1502 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 1503 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 1504 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 1505 * software-rendered usages are discouraged and have compatibility issues with hardware-only 1506 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 1507 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 1508 * reports or unit testing the {@link PixelCopy} API is recommended. 1509 */ 1510 @Deprecated 1511 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 1512 1513 /** 1514 * <p>Enables automatic quality mode for the drawing cache.</p> 1515 * 1516 * @deprecated The view drawing cache was largely made obsolete with the introduction of 1517 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 1518 * layers are largely unnecessary and can easily result in a net loss in performance due to the 1519 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 1520 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 1521 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 1522 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 1523 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 1524 * software-rendered usages are discouraged and have compatibility issues with hardware-only 1525 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 1526 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 1527 * reports or unit testing the {@link PixelCopy} API is recommended. 1528 */ 1529 @Deprecated 1530 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 1531 1532 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 1533 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 1534 }; 1535 1536 /** 1537 * <p>Mask for use with setFlags indicating bits used for the cache 1538 * quality property.</p> 1539 * {@hide} 1540 */ 1541 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 1542 1543 /** 1544 * <p> 1545 * Indicates this view can be long clicked. When long clickable, a View 1546 * reacts to long clicks by notifying the OnLongClickListener or showing a 1547 * context menu. 1548 * </p> 1549 * {@hide} 1550 */ 1551 static final int LONG_CLICKABLE = 0x00200000; 1552 1553 /** 1554 * <p>Indicates that this view gets its drawable states from its direct parent 1555 * and ignores its original internal states.</p> 1556 * 1557 * @hide 1558 */ 1559 static final int DUPLICATE_PARENT_STATE = 0x00400000; 1560 1561 /** 1562 * <p> 1563 * Indicates this view can be context clicked. When context clickable, a View reacts to a 1564 * context click (e.g. a primary stylus button press or right mouse click) by notifying the 1565 * OnContextClickListener. 1566 * </p> 1567 * {@hide} 1568 */ 1569 static final int CONTEXT_CLICKABLE = 0x00800000; 1570 1571 /** @hide */ 1572 @IntDef(prefix = { "SCROLLBARS_" }, value = { 1573 SCROLLBARS_INSIDE_OVERLAY, 1574 SCROLLBARS_INSIDE_INSET, 1575 SCROLLBARS_OUTSIDE_OVERLAY, 1576 SCROLLBARS_OUTSIDE_INSET 1577 }) 1578 @Retention(RetentionPolicy.SOURCE) 1579 public @interface ScrollBarStyle {} 1580 1581 /** 1582 * The scrollbar style to display the scrollbars inside the content area, 1583 * without increasing the padding. The scrollbars will be overlaid with 1584 * translucency on the view's content. 1585 */ 1586 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 1587 1588 /** 1589 * The scrollbar style to display the scrollbars inside the padded area, 1590 * increasing the padding of the view. The scrollbars will not overlap the 1591 * content area of the view. 1592 */ 1593 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 1594 1595 /** 1596 * The scrollbar style to display the scrollbars at the edge of the view, 1597 * without increasing the padding. The scrollbars will be overlaid with 1598 * translucency. 1599 */ 1600 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 1601 1602 /** 1603 * The scrollbar style to display the scrollbars at the edge of the view, 1604 * increasing the padding of the view. The scrollbars will only overlap the 1605 * background, if any. 1606 */ 1607 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 1608 1609 /** 1610 * Mask to check if the scrollbar style is overlay or inset. 1611 * {@hide} 1612 */ 1613 static final int SCROLLBARS_INSET_MASK = 0x01000000; 1614 1615 /** 1616 * Mask to check if the scrollbar style is inside or outside. 1617 * {@hide} 1618 */ 1619 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 1620 1621 /** 1622 * Mask for scrollbar style. 1623 * {@hide} 1624 */ 1625 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 1626 1627 /** 1628 * View flag indicating that the screen should remain on while the 1629 * window containing this view is visible to the user. This effectively 1630 * takes care of automatically setting the WindowManager's 1631 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 1632 */ 1633 public static final int KEEP_SCREEN_ON = 0x04000000; 1634 1635 /** 1636 * View flag indicating whether this view should have sound effects enabled 1637 * for events such as clicking and touching. 1638 */ 1639 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1640 1641 /** 1642 * View flag indicating whether this view should have haptic feedback 1643 * enabled for events such as long presses. 1644 */ 1645 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1646 1647 /** 1648 * <p>Indicates that the view hierarchy should stop saving state when 1649 * it reaches this view. If state saving is initiated immediately at 1650 * the view, it will be allowed. 1651 * {@hide} 1652 */ 1653 static final int PARENT_SAVE_DISABLED = 0x20000000; 1654 1655 /** 1656 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1657 * {@hide} 1658 */ 1659 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1660 1661 private static Paint sDebugPaint; 1662 1663 /** 1664 * <p>Indicates this view can display a tooltip on hover or long press.</p> 1665 * {@hide} 1666 */ 1667 static final int TOOLTIP = 0x40000000; 1668 1669 /** @hide */ 1670 @IntDef(flag = true, prefix = { "FOCUSABLES_" }, value = { 1671 FOCUSABLES_ALL, 1672 FOCUSABLES_TOUCH_MODE 1673 }) 1674 @Retention(RetentionPolicy.SOURCE) 1675 public @interface FocusableMode {} 1676 1677 /** 1678 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1679 * should add all focusable Views regardless if they are focusable in touch mode. 1680 */ 1681 public static final int FOCUSABLES_ALL = 0x00000000; 1682 1683 /** 1684 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1685 * should add only Views focusable in touch mode. 1686 */ 1687 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1688 1689 /** @hide */ 1690 @IntDef(prefix = { "FOCUS_" }, value = { 1691 FOCUS_BACKWARD, 1692 FOCUS_FORWARD, 1693 FOCUS_LEFT, 1694 FOCUS_UP, 1695 FOCUS_RIGHT, 1696 FOCUS_DOWN 1697 }) 1698 @Retention(RetentionPolicy.SOURCE) 1699 public @interface FocusDirection {} 1700 1701 /** @hide */ 1702 @IntDef(prefix = { "FOCUS_" }, value = { 1703 FOCUS_LEFT, 1704 FOCUS_UP, 1705 FOCUS_RIGHT, 1706 FOCUS_DOWN 1707 }) 1708 @Retention(RetentionPolicy.SOURCE) 1709 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward 1710 1711 /** 1712 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1713 * item. 1714 */ 1715 public static final int FOCUS_BACKWARD = 0x00000001; 1716 1717 /** 1718 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1719 * item. 1720 */ 1721 public static final int FOCUS_FORWARD = 0x00000002; 1722 1723 /** 1724 * Use with {@link #focusSearch(int)}. Move focus to the left. 1725 */ 1726 public static final int FOCUS_LEFT = 0x00000011; 1727 1728 /** 1729 * Use with {@link #focusSearch(int)}. Move focus up. 1730 */ 1731 public static final int FOCUS_UP = 0x00000021; 1732 1733 /** 1734 * Use with {@link #focusSearch(int)}. Move focus to the right. 1735 */ 1736 public static final int FOCUS_RIGHT = 0x00000042; 1737 1738 /** 1739 * Use with {@link #focusSearch(int)}. Move focus down. 1740 */ 1741 public static final int FOCUS_DOWN = 0x00000082; 1742 1743 /** 1744 * Bits of {@link #getMeasuredWidthAndState()} and 1745 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1746 */ 1747 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1748 1749 /** 1750 * Bits of {@link #getMeasuredWidthAndState()} and 1751 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1752 */ 1753 public static final int MEASURED_STATE_MASK = 0xff000000; 1754 1755 /** 1756 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1757 * for functions that combine both width and height into a single int, 1758 * such as {@link #getMeasuredState()} and the childState argument of 1759 * {@link #resolveSizeAndState(int, int, int)}. 1760 */ 1761 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1762 1763 /** 1764 * Bit of {@link #getMeasuredWidthAndState()} and 1765 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1766 * is smaller that the space the view would like to have. 1767 */ 1768 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1769 1770 /** 1771 * Base View state sets 1772 */ 1773 // Singles 1774 /** 1775 * Indicates the view has no states set. States are used with 1776 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1777 * view depending on its state. 1778 * 1779 * @see android.graphics.drawable.Drawable 1780 * @see #getDrawableState() 1781 */ 1782 protected static final int[] EMPTY_STATE_SET; 1783 /** 1784 * Indicates the view is enabled. States are used with 1785 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1786 * view depending on its state. 1787 * 1788 * @see android.graphics.drawable.Drawable 1789 * @see #getDrawableState() 1790 */ 1791 protected static final int[] ENABLED_STATE_SET; 1792 /** 1793 * Indicates the view is focused. States are used with 1794 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1795 * view depending on its state. 1796 * 1797 * @see android.graphics.drawable.Drawable 1798 * @see #getDrawableState() 1799 */ 1800 protected static final int[] FOCUSED_STATE_SET; 1801 /** 1802 * Indicates the view is selected. States are used with 1803 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1804 * view depending on its state. 1805 * 1806 * @see android.graphics.drawable.Drawable 1807 * @see #getDrawableState() 1808 */ 1809 protected static final int[] SELECTED_STATE_SET; 1810 /** 1811 * Indicates the view is pressed. States are used with 1812 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1813 * view depending on its state. 1814 * 1815 * @see android.graphics.drawable.Drawable 1816 * @see #getDrawableState() 1817 */ 1818 protected static final int[] PRESSED_STATE_SET; 1819 /** 1820 * Indicates the view's window has focus. States are used with 1821 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1822 * view depending on its state. 1823 * 1824 * @see android.graphics.drawable.Drawable 1825 * @see #getDrawableState() 1826 */ 1827 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1828 // Doubles 1829 /** 1830 * Indicates the view is enabled and has the focus. 1831 * 1832 * @see #ENABLED_STATE_SET 1833 * @see #FOCUSED_STATE_SET 1834 */ 1835 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1836 /** 1837 * Indicates the view is enabled and selected. 1838 * 1839 * @see #ENABLED_STATE_SET 1840 * @see #SELECTED_STATE_SET 1841 */ 1842 protected static final int[] ENABLED_SELECTED_STATE_SET; 1843 /** 1844 * Indicates the view is enabled and that its window has focus. 1845 * 1846 * @see #ENABLED_STATE_SET 1847 * @see #WINDOW_FOCUSED_STATE_SET 1848 */ 1849 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1850 /** 1851 * Indicates the view is focused and selected. 1852 * 1853 * @see #FOCUSED_STATE_SET 1854 * @see #SELECTED_STATE_SET 1855 */ 1856 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1857 /** 1858 * Indicates the view has the focus and that its window has the focus. 1859 * 1860 * @see #FOCUSED_STATE_SET 1861 * @see #WINDOW_FOCUSED_STATE_SET 1862 */ 1863 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1864 /** 1865 * Indicates the view is selected and that its window has the focus. 1866 * 1867 * @see #SELECTED_STATE_SET 1868 * @see #WINDOW_FOCUSED_STATE_SET 1869 */ 1870 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1871 // Triples 1872 /** 1873 * Indicates the view is enabled, focused and selected. 1874 * 1875 * @see #ENABLED_STATE_SET 1876 * @see #FOCUSED_STATE_SET 1877 * @see #SELECTED_STATE_SET 1878 */ 1879 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1880 /** 1881 * Indicates the view is enabled, focused and its window has the focus. 1882 * 1883 * @see #ENABLED_STATE_SET 1884 * @see #FOCUSED_STATE_SET 1885 * @see #WINDOW_FOCUSED_STATE_SET 1886 */ 1887 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1888 /** 1889 * Indicates the view is enabled, selected and its window has the focus. 1890 * 1891 * @see #ENABLED_STATE_SET 1892 * @see #SELECTED_STATE_SET 1893 * @see #WINDOW_FOCUSED_STATE_SET 1894 */ 1895 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1896 /** 1897 * Indicates the view is focused, selected and its window has the focus. 1898 * 1899 * @see #FOCUSED_STATE_SET 1900 * @see #SELECTED_STATE_SET 1901 * @see #WINDOW_FOCUSED_STATE_SET 1902 */ 1903 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1904 /** 1905 * Indicates the view is enabled, focused, selected and its window 1906 * has the focus. 1907 * 1908 * @see #ENABLED_STATE_SET 1909 * @see #FOCUSED_STATE_SET 1910 * @see #SELECTED_STATE_SET 1911 * @see #WINDOW_FOCUSED_STATE_SET 1912 */ 1913 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1914 /** 1915 * Indicates the view is pressed and its window has the focus. 1916 * 1917 * @see #PRESSED_STATE_SET 1918 * @see #WINDOW_FOCUSED_STATE_SET 1919 */ 1920 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1921 /** 1922 * Indicates the view is pressed and selected. 1923 * 1924 * @see #PRESSED_STATE_SET 1925 * @see #SELECTED_STATE_SET 1926 */ 1927 protected static final int[] PRESSED_SELECTED_STATE_SET; 1928 /** 1929 * Indicates the view is pressed, selected and its window has the focus. 1930 * 1931 * @see #PRESSED_STATE_SET 1932 * @see #SELECTED_STATE_SET 1933 * @see #WINDOW_FOCUSED_STATE_SET 1934 */ 1935 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1936 /** 1937 * Indicates the view is pressed and focused. 1938 * 1939 * @see #PRESSED_STATE_SET 1940 * @see #FOCUSED_STATE_SET 1941 */ 1942 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1943 /** 1944 * Indicates the view is pressed, focused and its window has the focus. 1945 * 1946 * @see #PRESSED_STATE_SET 1947 * @see #FOCUSED_STATE_SET 1948 * @see #WINDOW_FOCUSED_STATE_SET 1949 */ 1950 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1951 /** 1952 * Indicates the view is pressed, focused and selected. 1953 * 1954 * @see #PRESSED_STATE_SET 1955 * @see #SELECTED_STATE_SET 1956 * @see #FOCUSED_STATE_SET 1957 */ 1958 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1959 /** 1960 * Indicates the view is pressed, focused, selected and its window has the focus. 1961 * 1962 * @see #PRESSED_STATE_SET 1963 * @see #FOCUSED_STATE_SET 1964 * @see #SELECTED_STATE_SET 1965 * @see #WINDOW_FOCUSED_STATE_SET 1966 */ 1967 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1968 /** 1969 * Indicates the view is pressed and enabled. 1970 * 1971 * @see #PRESSED_STATE_SET 1972 * @see #ENABLED_STATE_SET 1973 */ 1974 protected static final int[] PRESSED_ENABLED_STATE_SET; 1975 /** 1976 * Indicates the view is pressed, enabled and its window has the focus. 1977 * 1978 * @see #PRESSED_STATE_SET 1979 * @see #ENABLED_STATE_SET 1980 * @see #WINDOW_FOCUSED_STATE_SET 1981 */ 1982 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1983 /** 1984 * Indicates the view is pressed, enabled and selected. 1985 * 1986 * @see #PRESSED_STATE_SET 1987 * @see #ENABLED_STATE_SET 1988 * @see #SELECTED_STATE_SET 1989 */ 1990 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1991 /** 1992 * Indicates the view is pressed, enabled, selected and its window has the 1993 * focus. 1994 * 1995 * @see #PRESSED_STATE_SET 1996 * @see #ENABLED_STATE_SET 1997 * @see #SELECTED_STATE_SET 1998 * @see #WINDOW_FOCUSED_STATE_SET 1999 */ 2000 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 2001 /** 2002 * Indicates the view is pressed, enabled and focused. 2003 * 2004 * @see #PRESSED_STATE_SET 2005 * @see #ENABLED_STATE_SET 2006 * @see #FOCUSED_STATE_SET 2007 */ 2008 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 2009 /** 2010 * Indicates the view is pressed, enabled, focused and its window has the 2011 * focus. 2012 * 2013 * @see #PRESSED_STATE_SET 2014 * @see #ENABLED_STATE_SET 2015 * @see #FOCUSED_STATE_SET 2016 * @see #WINDOW_FOCUSED_STATE_SET 2017 */ 2018 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 2019 /** 2020 * Indicates the view is pressed, enabled, focused and selected. 2021 * 2022 * @see #PRESSED_STATE_SET 2023 * @see #ENABLED_STATE_SET 2024 * @see #SELECTED_STATE_SET 2025 * @see #FOCUSED_STATE_SET 2026 */ 2027 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 2028 /** 2029 * Indicates the view is pressed, enabled, focused, selected and its window 2030 * has the focus. 2031 * 2032 * @see #PRESSED_STATE_SET 2033 * @see #ENABLED_STATE_SET 2034 * @see #SELECTED_STATE_SET 2035 * @see #FOCUSED_STATE_SET 2036 * @see #WINDOW_FOCUSED_STATE_SET 2037 */ 2038 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 2039 2040 static { 2041 EMPTY_STATE_SET = StateSet.get(0); 2042 2043 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED); 2044 2045 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED); 2046 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2047 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED); 2048 2049 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED); 2050 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2051 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED); 2052 FOCUSED_SELECTED_STATE_SET = StateSet.get( 2053 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED); 2054 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2055 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2056 | StateSet.VIEW_STATE_FOCUSED); 2057 2058 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED); 2059 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2060 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED); 2061 ENABLED_SELECTED_STATE_SET = StateSet.get( 2062 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED); 2063 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2064 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2065 | StateSet.VIEW_STATE_ENABLED); 2066 ENABLED_FOCUSED_STATE_SET = StateSet.get( 2067 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED); 2068 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2069 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 2070 | StateSet.VIEW_STATE_ENABLED); 2071 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 2072 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 2073 | StateSet.VIEW_STATE_ENABLED); 2074 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2075 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2076 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED); 2077 2078 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED); 2079 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2080 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED); 2081 PRESSED_SELECTED_STATE_SET = StateSet.get( 2082 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED); 2083 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2084 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2085 | StateSet.VIEW_STATE_PRESSED); 2086 PRESSED_FOCUSED_STATE_SET = StateSet.get( 2087 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 2088 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2089 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 2090 | StateSet.VIEW_STATE_PRESSED); 2091 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 2092 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 2093 | StateSet.VIEW_STATE_PRESSED); 2094 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2095 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2096 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 2097 PRESSED_ENABLED_STATE_SET = StateSet.get( 2098 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 2099 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2100 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED 2101 | StateSet.VIEW_STATE_PRESSED); 2102 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get( 2103 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED 2104 | StateSet.VIEW_STATE_PRESSED); 2105 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2106 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2107 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 2108 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get( 2109 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED 2110 | StateSet.VIEW_STATE_PRESSED); 2111 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2112 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 2113 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 2114 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 2115 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 2116 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 2117 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 2118 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 2119 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED 2120 | StateSet.VIEW_STATE_PRESSED); 2121 } 2122 2123 /** 2124 * Accessibility event types that are dispatched for text population. 2125 */ 2126 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 2127 AccessibilityEvent.TYPE_VIEW_CLICKED 2128 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 2129 | AccessibilityEvent.TYPE_VIEW_SELECTED 2130 | AccessibilityEvent.TYPE_VIEW_FOCUSED 2131 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 2132 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 2133 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 2134 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 2135 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 2136 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 2137 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 2138 2139 static final int DEBUG_CORNERS_COLOR = Color.rgb(63, 127, 255); 2140 2141 static final int DEBUG_CORNERS_SIZE_DIP = 8; 2142 2143 /** 2144 * Temporary Rect currently for use in setBackground(). This will probably 2145 * be extended in the future to hold our own class with more than just 2146 * a Rect. :) 2147 */ 2148 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 2149 2150 /** 2151 * Map used to store views' tags. 2152 */ 2153 private SparseArray<Object> mKeyedTags; 2154 2155 /** 2156 * The next available accessibility id. 2157 */ 2158 private static int sNextAccessibilityViewId; 2159 2160 /** 2161 * The animation currently associated with this view. 2162 * @hide 2163 */ 2164 protected Animation mCurrentAnimation = null; 2165 2166 /** 2167 * Width as measured during measure pass. 2168 * {@hide} 2169 */ 2170 @ViewDebug.ExportedProperty(category = "measurement") 2171 int mMeasuredWidth; 2172 2173 /** 2174 * Height as measured during measure pass. 2175 * {@hide} 2176 */ 2177 @ViewDebug.ExportedProperty(category = "measurement") 2178 int mMeasuredHeight; 2179 2180 /** 2181 * Flag to indicate that this view was marked INVALIDATED, or had its display list 2182 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 2183 * its display list. This flag, used only when hw accelerated, allows us to clear the 2184 * flag while retaining this information until it's needed (at getDisplayList() time and 2185 * in drawChild(), when we decide to draw a view's children's display lists into our own). 2186 * 2187 * {@hide} 2188 */ 2189 boolean mRecreateDisplayList = false; 2190 2191 /** 2192 * The view's identifier. 2193 * {@hide} 2194 * 2195 * @see #setId(int) 2196 * @see #getId() 2197 */ 2198 @IdRes 2199 @ViewDebug.ExportedProperty(resolveId = true) 2200 int mID = NO_ID; 2201 2202 /** The ID of this view for autofill purposes. 2203 * <ul> 2204 * <li>== {@link #NO_ID}: ID has not been assigned yet 2205 * <li>≤ {@link #LAST_APP_AUTOFILL_ID}: View is not part of a activity. The ID is 2206 * unique in the process. This might change 2207 * over activity lifecycle events. 2208 * <li>> {@link #LAST_APP_AUTOFILL_ID}: View is part of a activity. The ID is 2209 * unique in the activity. This stays the same 2210 * over activity lifecycle events. 2211 */ 2212 private int mAutofillViewId = NO_ID; 2213 2214 // ID for accessibility purposes. This ID must be unique for every window 2215 private int mAccessibilityViewId = NO_ID; 2216 2217 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 2218 2219 /** 2220 * The view's tag. 2221 * {@hide} 2222 * 2223 * @see #setTag(Object) 2224 * @see #getTag() 2225 */ 2226 protected Object mTag = null; 2227 2228 // for mPrivateFlags: 2229 /** {@hide} */ 2230 static final int PFLAG_WANTS_FOCUS = 0x00000001; 2231 /** {@hide} */ 2232 static final int PFLAG_FOCUSED = 0x00000002; 2233 /** {@hide} */ 2234 static final int PFLAG_SELECTED = 0x00000004; 2235 /** {@hide} */ 2236 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 2237 /** {@hide} */ 2238 static final int PFLAG_HAS_BOUNDS = 0x00000010; 2239 /** {@hide} */ 2240 static final int PFLAG_DRAWN = 0x00000020; 2241 /** 2242 * When this flag is set, this view is running an animation on behalf of its 2243 * children and should therefore not cancel invalidate requests, even if they 2244 * lie outside of this view's bounds. 2245 * 2246 * {@hide} 2247 */ 2248 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 2249 /** {@hide} */ 2250 static final int PFLAG_SKIP_DRAW = 0x00000080; 2251 /** {@hide} */ 2252 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 2253 /** {@hide} */ 2254 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 2255 /** {@hide} */ 2256 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 2257 /** {@hide} */ 2258 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 2259 /** {@hide} */ 2260 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 2261 2262 private static final int PFLAG_PRESSED = 0x00004000; 2263 2264 /** {@hide} */ 2265 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 2266 /** 2267 * Flag used to indicate that this view should be drawn once more (and only once 2268 * more) after its animation has completed. 2269 * {@hide} 2270 */ 2271 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 2272 2273 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 2274 2275 /** 2276 * Indicates that the View returned true when onSetAlpha() was called and that 2277 * the alpha must be restored. 2278 * {@hide} 2279 */ 2280 static final int PFLAG_ALPHA_SET = 0x00040000; 2281 2282 /** 2283 * Set by {@link #setScrollContainer(boolean)}. 2284 */ 2285 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 2286 2287 /** 2288 * Set by {@link #setScrollContainer(boolean)}. 2289 */ 2290 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 2291 2292 /** 2293 * View flag indicating whether this view was invalidated (fully or partially.) 2294 * 2295 * @hide 2296 */ 2297 static final int PFLAG_DIRTY = 0x00200000; 2298 2299 /** 2300 * View flag indicating whether this view was invalidated by an opaque 2301 * invalidate request. 2302 * 2303 * @hide 2304 */ 2305 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 2306 2307 /** 2308 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 2309 * 2310 * @hide 2311 */ 2312 static final int PFLAG_DIRTY_MASK = 0x00600000; 2313 2314 /** 2315 * Indicates whether the background is opaque. 2316 * 2317 * @hide 2318 */ 2319 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 2320 2321 /** 2322 * Indicates whether the scrollbars are opaque. 2323 * 2324 * @hide 2325 */ 2326 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 2327 2328 /** 2329 * Indicates whether the view is opaque. 2330 * 2331 * @hide 2332 */ 2333 static final int PFLAG_OPAQUE_MASK = 0x01800000; 2334 2335 /** 2336 * Indicates a prepressed state; 2337 * the short time between ACTION_DOWN and recognizing 2338 * a 'real' press. Prepressed is used to recognize quick taps 2339 * even when they are shorter than ViewConfiguration.getTapTimeout(). 2340 * 2341 * @hide 2342 */ 2343 private static final int PFLAG_PREPRESSED = 0x02000000; 2344 2345 /** 2346 * Indicates whether the view is temporarily detached. 2347 * 2348 * @hide 2349 */ 2350 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 2351 2352 /** 2353 * Indicates that we should awaken scroll bars once attached 2354 * 2355 * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged 2356 * during window attachment and it is no longer needed. Feel free to repurpose it. 2357 * 2358 * @hide 2359 */ 2360 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 2361 2362 /** 2363 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 2364 * @hide 2365 */ 2366 private static final int PFLAG_HOVERED = 0x10000000; 2367 2368 /** 2369 * Flag set by {@link AutofillManager} if it needs to be notified when this view is clicked. 2370 */ 2371 private static final int PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK = 0x20000000; 2372 2373 /** {@hide} */ 2374 static final int PFLAG_ACTIVATED = 0x40000000; 2375 2376 /** 2377 * Indicates that this view was specifically invalidated, not just dirtied because some 2378 * child view was invalidated. The flag is used to determine when we need to recreate 2379 * a view's display list (as opposed to just returning a reference to its existing 2380 * display list). 2381 * 2382 * @hide 2383 */ 2384 static final int PFLAG_INVALIDATED = 0x80000000; 2385 2386 /** 2387 * Masks for mPrivateFlags2, as generated by dumpFlags(): 2388 * 2389 * |-------|-------|-------|-------| 2390 * 1 PFLAG2_DRAG_CAN_ACCEPT 2391 * 1 PFLAG2_DRAG_HOVERED 2392 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 2393 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 2394 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 2395 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 2396 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 2397 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 2398 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 2399 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 2400 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 2401 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6] 2402 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7] 2403 * 111 PFLAG2_TEXT_DIRECTION_MASK 2404 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 2405 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 2406 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 2407 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 2408 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 2409 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 2410 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 2411 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 2412 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 2413 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 2414 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 2415 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 2416 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 2417 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 2418 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 2419 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 2420 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 2421 * 1 PFLAG2_VIEW_QUICK_REJECTED 2422 * 1 PFLAG2_PADDING_RESOLVED 2423 * 1 PFLAG2_DRAWABLE_RESOLVED 2424 * 1 PFLAG2_HAS_TRANSIENT_STATE 2425 * |-------|-------|-------|-------| 2426 */ 2427 2428 /** 2429 * Indicates that this view has reported that it can accept the current drag's content. 2430 * Cleared when the drag operation concludes. 2431 * @hide 2432 */ 2433 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 2434 2435 /** 2436 * Indicates that this view is currently directly under the drag location in a 2437 * drag-and-drop operation involving content that it can accept. Cleared when 2438 * the drag exits the view, or when the drag operation concludes. 2439 * @hide 2440 */ 2441 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 2442 2443 /** @hide */ 2444 @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = { 2445 LAYOUT_DIRECTION_LTR, 2446 LAYOUT_DIRECTION_RTL, 2447 LAYOUT_DIRECTION_INHERIT, 2448 LAYOUT_DIRECTION_LOCALE 2449 }) 2450 @Retention(RetentionPolicy.SOURCE) 2451 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection 2452 public @interface LayoutDir {} 2453 2454 /** @hide */ 2455 @IntDef(prefix = { "LAYOUT_DIRECTION_" }, value = { 2456 LAYOUT_DIRECTION_LTR, 2457 LAYOUT_DIRECTION_RTL 2458 }) 2459 @Retention(RetentionPolicy.SOURCE) 2460 public @interface ResolvedLayoutDir {} 2461 2462 /** 2463 * A flag to indicate that the layout direction of this view has not been defined yet. 2464 * @hide 2465 */ 2466 public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED; 2467 2468 /** 2469 * Horizontal layout direction of this view is from Left to Right. 2470 * Use with {@link #setLayoutDirection}. 2471 */ 2472 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 2473 2474 /** 2475 * Horizontal layout direction of this view is from Right to Left. 2476 * Use with {@link #setLayoutDirection}. 2477 */ 2478 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 2479 2480 /** 2481 * Horizontal layout direction of this view is inherited from its parent. 2482 * Use with {@link #setLayoutDirection}. 2483 */ 2484 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 2485 2486 /** 2487 * Horizontal layout direction of this view is from deduced from the default language 2488 * script for the locale. Use with {@link #setLayoutDirection}. 2489 */ 2490 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 2491 2492 /** 2493 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2494 * @hide 2495 */ 2496 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 2497 2498 /** 2499 * Mask for use with private flags indicating bits used for horizontal layout direction. 2500 * @hide 2501 */ 2502 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2503 2504 /** 2505 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 2506 * right-to-left direction. 2507 * @hide 2508 */ 2509 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2510 2511 /** 2512 * Indicates whether the view horizontal layout direction has been resolved. 2513 * @hide 2514 */ 2515 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2516 2517 /** 2518 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 2519 * @hide 2520 */ 2521 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 2522 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2523 2524 /* 2525 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 2526 * flag value. 2527 * @hide 2528 */ 2529 private static final int[] LAYOUT_DIRECTION_FLAGS = { 2530 LAYOUT_DIRECTION_LTR, 2531 LAYOUT_DIRECTION_RTL, 2532 LAYOUT_DIRECTION_INHERIT, 2533 LAYOUT_DIRECTION_LOCALE 2534 }; 2535 2536 /** 2537 * Default horizontal layout direction. 2538 */ 2539 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 2540 2541 /** 2542 * Default horizontal layout direction. 2543 * @hide 2544 */ 2545 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 2546 2547 /** 2548 * Text direction is inherited through {@link ViewGroup} 2549 */ 2550 public static final int TEXT_DIRECTION_INHERIT = 0; 2551 2552 /** 2553 * Text direction is using "first strong algorithm". The first strong directional character 2554 * determines the paragraph direction. If there is no strong directional character, the 2555 * paragraph direction is the view's resolved layout direction. 2556 */ 2557 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 2558 2559 /** 2560 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 2561 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 2562 * If there are neither, the paragraph direction is the view's resolved layout direction. 2563 */ 2564 public static final int TEXT_DIRECTION_ANY_RTL = 2; 2565 2566 /** 2567 * Text direction is forced to LTR. 2568 */ 2569 public static final int TEXT_DIRECTION_LTR = 3; 2570 2571 /** 2572 * Text direction is forced to RTL. 2573 */ 2574 public static final int TEXT_DIRECTION_RTL = 4; 2575 2576 /** 2577 * Text direction is coming from the system Locale. 2578 */ 2579 public static final int TEXT_DIRECTION_LOCALE = 5; 2580 2581 /** 2582 * Text direction is using "first strong algorithm". The first strong directional character 2583 * determines the paragraph direction. If there is no strong directional character, the 2584 * paragraph direction is LTR. 2585 */ 2586 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6; 2587 2588 /** 2589 * Text direction is using "first strong algorithm". The first strong directional character 2590 * determines the paragraph direction. If there is no strong directional character, the 2591 * paragraph direction is RTL. 2592 */ 2593 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7; 2594 2595 /** 2596 * Default text direction is inherited 2597 */ 2598 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 2599 2600 /** 2601 * Default resolved text direction 2602 * @hide 2603 */ 2604 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 2605 2606 /** 2607 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 2608 * @hide 2609 */ 2610 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 2611 2612 /** 2613 * Mask for use with private flags indicating bits used for text direction. 2614 * @hide 2615 */ 2616 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 2617 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2618 2619 /** 2620 * Array of text direction flags for mapping attribute "textDirection" to correct 2621 * flag value. 2622 * @hide 2623 */ 2624 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 2625 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2626 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2627 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2628 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2629 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2630 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2631 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2632 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 2633 }; 2634 2635 /** 2636 * Indicates whether the view text direction has been resolved. 2637 * @hide 2638 */ 2639 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 2640 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2641 2642 /** 2643 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2644 * @hide 2645 */ 2646 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 2647 2648 /** 2649 * Mask for use with private flags indicating bits used for resolved text direction. 2650 * @hide 2651 */ 2652 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 2653 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2654 2655 /** 2656 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 2657 * @hide 2658 */ 2659 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 2660 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2661 2662 /** @hide */ 2663 @IntDef(prefix = { "TEXT_ALIGNMENT_" }, value = { 2664 TEXT_ALIGNMENT_INHERIT, 2665 TEXT_ALIGNMENT_GRAVITY, 2666 TEXT_ALIGNMENT_CENTER, 2667 TEXT_ALIGNMENT_TEXT_START, 2668 TEXT_ALIGNMENT_TEXT_END, 2669 TEXT_ALIGNMENT_VIEW_START, 2670 TEXT_ALIGNMENT_VIEW_END 2671 }) 2672 @Retention(RetentionPolicy.SOURCE) 2673 public @interface TextAlignment {} 2674 2675 /** 2676 * Default text alignment. The text alignment of this View is inherited from its parent. 2677 * Use with {@link #setTextAlignment(int)} 2678 */ 2679 public static final int TEXT_ALIGNMENT_INHERIT = 0; 2680 2681 /** 2682 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 2683 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 2684 * 2685 * Use with {@link #setTextAlignment(int)} 2686 */ 2687 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 2688 2689 /** 2690 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2691 * 2692 * Use with {@link #setTextAlignment(int)} 2693 */ 2694 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2695 2696 /** 2697 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2698 * 2699 * Use with {@link #setTextAlignment(int)} 2700 */ 2701 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2702 2703 /** 2704 * Center the paragraph, e.g. ALIGN_CENTER. 2705 * 2706 * Use with {@link #setTextAlignment(int)} 2707 */ 2708 public static final int TEXT_ALIGNMENT_CENTER = 4; 2709 2710 /** 2711 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved 2712 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2713 * 2714 * Use with {@link #setTextAlignment(int)} 2715 */ 2716 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2717 2718 /** 2719 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved 2720 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2721 * 2722 * Use with {@link #setTextAlignment(int)} 2723 */ 2724 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2725 2726 /** 2727 * Default text alignment is inherited 2728 */ 2729 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2730 2731 /** 2732 * Default resolved text alignment 2733 * @hide 2734 */ 2735 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2736 2737 /** 2738 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2739 * @hide 2740 */ 2741 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2742 2743 /** 2744 * Mask for use with private flags indicating bits used for text alignment. 2745 * @hide 2746 */ 2747 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2748 2749 /** 2750 * Array of text direction flags for mapping attribute "textAlignment" to correct 2751 * flag value. 2752 * @hide 2753 */ 2754 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2755 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2756 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2757 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2758 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2759 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2760 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2761 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2762 }; 2763 2764 /** 2765 * Indicates whether the view text alignment has been resolved. 2766 * @hide 2767 */ 2768 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2769 2770 /** 2771 * Bit shift to get the resolved text alignment. 2772 * @hide 2773 */ 2774 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2775 2776 /** 2777 * Mask for use with private flags indicating bits used for text alignment. 2778 * @hide 2779 */ 2780 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2781 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2782 2783 /** 2784 * Indicates whether if the view text alignment has been resolved to gravity 2785 */ 2786 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2787 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2788 2789 // Accessiblity constants for mPrivateFlags2 2790 2791 /** 2792 * Shift for the bits in {@link #mPrivateFlags2} related to the 2793 * "importantForAccessibility" attribute. 2794 */ 2795 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2796 2797 /** 2798 * Automatically determine whether a view is important for accessibility. 2799 */ 2800 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2801 2802 /** 2803 * The view is important for accessibility. 2804 */ 2805 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2806 2807 /** 2808 * The view is not important for accessibility. 2809 */ 2810 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2811 2812 /** 2813 * The view is not important for accessibility, nor are any of its 2814 * descendant views. 2815 */ 2816 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2817 2818 /** 2819 * The default whether the view is important for accessibility. 2820 */ 2821 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2822 2823 /** 2824 * Mask for obtaining the bits which specify how to determine 2825 * whether a view is important for accessibility. 2826 */ 2827 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2828 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2829 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2830 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2831 2832 /** 2833 * Shift for the bits in {@link #mPrivateFlags2} related to the 2834 * "accessibilityLiveRegion" attribute. 2835 */ 2836 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2837 2838 /** 2839 * Live region mode specifying that accessibility services should not 2840 * automatically announce changes to this view. This is the default live 2841 * region mode for most views. 2842 * <p> 2843 * Use with {@link #setAccessibilityLiveRegion(int)}. 2844 */ 2845 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2846 2847 /** 2848 * Live region mode specifying that accessibility services should announce 2849 * changes to this view. 2850 * <p> 2851 * Use with {@link #setAccessibilityLiveRegion(int)}. 2852 */ 2853 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2854 2855 /** 2856 * Live region mode specifying that accessibility services should interrupt 2857 * ongoing speech to immediately announce changes to this view. 2858 * <p> 2859 * Use with {@link #setAccessibilityLiveRegion(int)}. 2860 */ 2861 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2862 2863 /** 2864 * The default whether the view is important for accessibility. 2865 */ 2866 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2867 2868 /** 2869 * Mask for obtaining the bits which specify a view's accessibility live 2870 * region mode. 2871 */ 2872 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2873 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2874 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2875 2876 /** 2877 * Flag indicating whether a view has accessibility focus. 2878 */ 2879 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2880 2881 /** 2882 * Flag whether the accessibility state of the subtree rooted at this view changed. 2883 */ 2884 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2885 2886 /** 2887 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2888 * is used to check whether later changes to the view's transform should invalidate the 2889 * view to force the quickReject test to run again. 2890 */ 2891 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2892 2893 /** 2894 * Flag indicating that start/end padding has been resolved into left/right padding 2895 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2896 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2897 * during measurement. In some special cases this is required such as when an adapter-based 2898 * view measures prospective children without attaching them to a window. 2899 */ 2900 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2901 2902 /** 2903 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2904 */ 2905 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2906 2907 /** 2908 * Indicates that the view is tracking some sort of transient state 2909 * that the app should not need to be aware of, but that the framework 2910 * should take special care to preserve. 2911 */ 2912 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2913 2914 /** 2915 * Group of bits indicating that RTL properties resolution is done. 2916 */ 2917 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2918 PFLAG2_TEXT_DIRECTION_RESOLVED | 2919 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2920 PFLAG2_PADDING_RESOLVED | 2921 PFLAG2_DRAWABLE_RESOLVED; 2922 2923 // There are a couple of flags left in mPrivateFlags2 2924 2925 /* End of masks for mPrivateFlags2 */ 2926 2927 /** 2928 * Masks for mPrivateFlags3, as generated by dumpFlags(): 2929 * 2930 * |-------|-------|-------|-------| 2931 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM 2932 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA 2933 * 1 PFLAG3_IS_LAID_OUT 2934 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT 2935 * 1 PFLAG3_CALLED_SUPER 2936 * 1 PFLAG3_APPLYING_INSETS 2937 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS 2938 * 1 PFLAG3_NESTED_SCROLLING_ENABLED 2939 * 1 PFLAG3_SCROLL_INDICATOR_TOP 2940 * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM 2941 * 1 PFLAG3_SCROLL_INDICATOR_LEFT 2942 * 1 PFLAG3_SCROLL_INDICATOR_RIGHT 2943 * 1 PFLAG3_SCROLL_INDICATOR_START 2944 * 1 PFLAG3_SCROLL_INDICATOR_END 2945 * 1 PFLAG3_ASSIST_BLOCKED 2946 * 1 PFLAG3_CLUSTER 2947 * 1 PFLAG3_IS_AUTOFILLED 2948 * 1 PFLAG3_FINGER_DOWN 2949 * 1 PFLAG3_FOCUSED_BY_DEFAULT 2950 * 1111 PFLAG3_IMPORTANT_FOR_AUTOFILL 2951 * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE 2952 * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED 2953 * 1 PFLAG3_TEMPORARY_DETACH 2954 * 1 PFLAG3_NO_REVEAL_ON_FOCUS 2955 * 1 PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT 2956 * 1 PFLAG3_SCREEN_READER_FOCUSABLE 2957 * 1 PFLAG3_AGGREGATED_VISIBLE 2958 * 1 PFLAG3_AUTOFILLID_EXPLICITLY_SET 2959 * 1 PFLAG3_ACCESSIBILITY_HEADING 2960 * |-------|-------|-------|-------| 2961 */ 2962 2963 /** 2964 * Flag indicating that view has a transform animation set on it. This is used to track whether 2965 * an animation is cleared between successive frames, in order to tell the associated 2966 * DisplayList to clear its animation matrix. 2967 */ 2968 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2969 2970 /** 2971 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2972 * animation is cleared between successive frames, in order to tell the associated 2973 * DisplayList to restore its alpha value. 2974 */ 2975 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2976 2977 /** 2978 * Flag indicating that the view has been through at least one layout since it 2979 * was last attached to a window. 2980 */ 2981 static final int PFLAG3_IS_LAID_OUT = 0x4; 2982 2983 /** 2984 * Flag indicating that a call to measure() was skipped and should be done 2985 * instead when layout() is invoked. 2986 */ 2987 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2988 2989 /** 2990 * Flag indicating that an overridden method correctly called down to 2991 * the superclass implementation as required by the API spec. 2992 */ 2993 static final int PFLAG3_CALLED_SUPER = 0x10; 2994 2995 /** 2996 * Flag indicating that we're in the process of applying window insets. 2997 */ 2998 static final int PFLAG3_APPLYING_INSETS = 0x20; 2999 3000 /** 3001 * Flag indicating that we're in the process of fitting system windows using the old method. 3002 */ 3003 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40; 3004 3005 /** 3006 * Flag indicating that nested scrolling is enabled for this view. 3007 * The view will optionally cooperate with views up its parent chain to allow for 3008 * integrated nested scrolling along the same axis. 3009 */ 3010 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; 3011 3012 /** 3013 * Flag indicating that the bottom scroll indicator should be displayed 3014 * when this view can scroll up. 3015 */ 3016 static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; 3017 3018 /** 3019 * Flag indicating that the bottom scroll indicator should be displayed 3020 * when this view can scroll down. 3021 */ 3022 static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; 3023 3024 /** 3025 * Flag indicating that the left scroll indicator should be displayed 3026 * when this view can scroll left. 3027 */ 3028 static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; 3029 3030 /** 3031 * Flag indicating that the right scroll indicator should be displayed 3032 * when this view can scroll right. 3033 */ 3034 static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; 3035 3036 /** 3037 * Flag indicating that the start scroll indicator should be displayed 3038 * when this view can scroll in the start direction. 3039 */ 3040 static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; 3041 3042 /** 3043 * Flag indicating that the end scroll indicator should be displayed 3044 * when this view can scroll in the end direction. 3045 */ 3046 static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; 3047 3048 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 3049 3050 static final int SCROLL_INDICATORS_NONE = 0x0000; 3051 3052 /** 3053 * Mask for use with setFlags indicating bits used for indicating which 3054 * scroll indicators are enabled. 3055 */ 3056 static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP 3057 | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT 3058 | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START 3059 | PFLAG3_SCROLL_INDICATOR_END; 3060 3061 /** 3062 * Left-shift required to translate between public scroll indicator flags 3063 * and internal PFLAGS3 flags. When used as a right-shift, translates 3064 * PFLAGS3 flags to public flags. 3065 */ 3066 static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; 3067 3068 /** @hide */ 3069 @Retention(RetentionPolicy.SOURCE) 3070 @IntDef(flag = true, prefix = { "SCROLL_INDICATOR_" }, value = { 3071 SCROLL_INDICATOR_TOP, 3072 SCROLL_INDICATOR_BOTTOM, 3073 SCROLL_INDICATOR_LEFT, 3074 SCROLL_INDICATOR_RIGHT, 3075 SCROLL_INDICATOR_START, 3076 SCROLL_INDICATOR_END, 3077 }) 3078 public @interface ScrollIndicators {} 3079 3080 /** 3081 * Scroll indicator direction for the top edge of the view. 3082 * 3083 * @see #setScrollIndicators(int) 3084 * @see #setScrollIndicators(int, int) 3085 * @see #getScrollIndicators() 3086 */ 3087 public static final int SCROLL_INDICATOR_TOP = 3088 PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3089 3090 /** 3091 * Scroll indicator direction for the bottom edge of the view. 3092 * 3093 * @see #setScrollIndicators(int) 3094 * @see #setScrollIndicators(int, int) 3095 * @see #getScrollIndicators() 3096 */ 3097 public static final int SCROLL_INDICATOR_BOTTOM = 3098 PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3099 3100 /** 3101 * Scroll indicator direction for the left edge of the view. 3102 * 3103 * @see #setScrollIndicators(int) 3104 * @see #setScrollIndicators(int, int) 3105 * @see #getScrollIndicators() 3106 */ 3107 public static final int SCROLL_INDICATOR_LEFT = 3108 PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3109 3110 /** 3111 * Scroll indicator direction for the right edge of the view. 3112 * 3113 * @see #setScrollIndicators(int) 3114 * @see #setScrollIndicators(int, int) 3115 * @see #getScrollIndicators() 3116 */ 3117 public static final int SCROLL_INDICATOR_RIGHT = 3118 PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3119 3120 /** 3121 * Scroll indicator direction for the starting edge of the view. 3122 * <p> 3123 * Resolved according to the view's layout direction, see 3124 * {@link #getLayoutDirection()} for more information. 3125 * 3126 * @see #setScrollIndicators(int) 3127 * @see #setScrollIndicators(int, int) 3128 * @see #getScrollIndicators() 3129 */ 3130 public static final int SCROLL_INDICATOR_START = 3131 PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3132 3133 /** 3134 * Scroll indicator direction for the ending edge of the view. 3135 * <p> 3136 * Resolved according to the view's layout direction, see 3137 * {@link #getLayoutDirection()} for more information. 3138 * 3139 * @see #setScrollIndicators(int) 3140 * @see #setScrollIndicators(int, int) 3141 * @see #getScrollIndicators() 3142 */ 3143 public static final int SCROLL_INDICATOR_END = 3144 PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 3145 3146 /** 3147 * <p>Indicates that we are allowing {@link ViewStructure} to traverse 3148 * into this view.<p> 3149 */ 3150 static final int PFLAG3_ASSIST_BLOCKED = 0x4000; 3151 3152 /** 3153 * Flag indicating that the view is a root of a keyboard navigation cluster. 3154 * 3155 * @see #isKeyboardNavigationCluster() 3156 * @see #setKeyboardNavigationCluster(boolean) 3157 */ 3158 private static final int PFLAG3_CLUSTER = 0x8000; 3159 3160 /** 3161 * Flag indicating that the view is autofilled 3162 * 3163 * @see #isAutofilled() 3164 * @see #setAutofilled(boolean) 3165 */ 3166 private static final int PFLAG3_IS_AUTOFILLED = 0x10000; 3167 3168 /** 3169 * Indicates that the user is currently touching the screen. 3170 * Currently used for the tooltip positioning only. 3171 */ 3172 private static final int PFLAG3_FINGER_DOWN = 0x20000; 3173 3174 /** 3175 * Flag indicating that this view is the default-focus view. 3176 * 3177 * @see #isFocusedByDefault() 3178 * @see #setFocusedByDefault(boolean) 3179 */ 3180 private static final int PFLAG3_FOCUSED_BY_DEFAULT = 0x40000; 3181 3182 /** 3183 * Shift for the bits in {@link #mPrivateFlags3} related to the 3184 * "importantForAutofill" attribute. 3185 */ 3186 static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT = 19; 3187 3188 /** 3189 * Mask for obtaining the bits which specify how to determine 3190 * whether a view is important for autofill. 3191 */ 3192 static final int PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK = (IMPORTANT_FOR_AUTOFILL_AUTO 3193 | IMPORTANT_FOR_AUTOFILL_YES | IMPORTANT_FOR_AUTOFILL_NO 3194 | IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS 3195 | IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS) 3196 << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT; 3197 3198 /** 3199 * Whether this view has rendered elements that overlap (see {@link 3200 * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and 3201 * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when 3202 * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is 3203 * determined by whatever {@link #hasOverlappingRendering()} returns. 3204 */ 3205 private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000; 3206 3207 /** 3208 * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value 3209 * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid. 3210 */ 3211 private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000; 3212 3213 /** 3214 * Flag indicating that the view is temporarily detached from the parent view. 3215 * 3216 * @see #onStartTemporaryDetach() 3217 * @see #onFinishTemporaryDetach() 3218 */ 3219 static final int PFLAG3_TEMPORARY_DETACH = 0x2000000; 3220 3221 /** 3222 * Flag indicating that the view does not wish to be revealed within its parent 3223 * hierarchy when it gains focus. Expressed in the negative since the historical 3224 * default behavior is to reveal on focus; this flag suppresses that behavior. 3225 * 3226 * @see #setRevealOnFocusHint(boolean) 3227 * @see #getRevealOnFocusHint() 3228 */ 3229 private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000; 3230 3231 /** 3232 * Flag indicating that when layout is completed we should notify 3233 * that the view was entered for autofill purposes. To minimize 3234 * showing autofill for views not visible to the user we evaluate 3235 * user visibility which cannot be done until the view is laid out. 3236 */ 3237 static final int PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT = 0x8000000; 3238 3239 /** 3240 * Works like focusable for screen readers, but without the side effects on input focus. 3241 * @see #setScreenReaderFocusable(boolean) 3242 */ 3243 private static final int PFLAG3_SCREEN_READER_FOCUSABLE = 0x10000000; 3244 3245 /** 3246 * The last aggregated visibility. Used to detect when it truly changes. 3247 */ 3248 private static final int PFLAG3_AGGREGATED_VISIBLE = 0x20000000; 3249 3250 /** 3251 * Used to indicate that {@link #mAutofillId} was explicitly set through 3252 * {@link #setAutofillId(AutofillId)}. 3253 */ 3254 private static final int PFLAG3_AUTOFILLID_EXPLICITLY_SET = 0x40000000; 3255 3256 /** 3257 * Indicates if the View is a heading for accessibility purposes 3258 */ 3259 private static final int PFLAG3_ACCESSIBILITY_HEADING = 0x80000000; 3260 3261 /* End of masks for mPrivateFlags3 */ 3262 3263 /** 3264 * Always allow a user to over-scroll this view, provided it is a 3265 * view that can scroll. 3266 * 3267 * @see #getOverScrollMode() 3268 * @see #setOverScrollMode(int) 3269 */ 3270 public static final int OVER_SCROLL_ALWAYS = 0; 3271 3272 /** 3273 * Allow a user to over-scroll this view only if the content is large 3274 * enough to meaningfully scroll, provided it is a view that can scroll. 3275 * 3276 * @see #getOverScrollMode() 3277 * @see #setOverScrollMode(int) 3278 */ 3279 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 3280 3281 /** 3282 * Never allow a user to over-scroll this view. 3283 * 3284 * @see #getOverScrollMode() 3285 * @see #setOverScrollMode(int) 3286 */ 3287 public static final int OVER_SCROLL_NEVER = 2; 3288 3289 /** 3290 * Special constant for {@link #setSystemUiVisibility(int)}: View has 3291 * requested the system UI (status bar) to be visible (the default). 3292 * 3293 * @see #setSystemUiVisibility(int) 3294 */ 3295 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 3296 3297 /** 3298 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 3299 * system UI to enter an unobtrusive "low profile" mode. 3300 * 3301 * <p>This is for use in games, book readers, video players, or any other 3302 * "immersive" application where the usual system chrome is deemed too distracting. 3303 * 3304 * <p>In low profile mode, the status bar and/or navigation icons may dim. 3305 * 3306 * @see #setSystemUiVisibility(int) 3307 */ 3308 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 3309 3310 /** 3311 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 3312 * system navigation be temporarily hidden. 3313 * 3314 * <p>This is an even less obtrusive state than that called for by 3315 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 3316 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 3317 * those to disappear. This is useful (in conjunction with the 3318 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 3319 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 3320 * window flags) for displaying content using every last pixel on the display. 3321 * 3322 * <p>There is a limitation: because navigation controls are so important, the least user 3323 * interaction will cause them to reappear immediately. When this happens, both 3324 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 3325 * so that both elements reappear at the same time. 3326 * 3327 * @see #setSystemUiVisibility(int) 3328 */ 3329 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 3330 3331 /** 3332 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 3333 * into the normal fullscreen mode so that its content can take over the screen 3334 * while still allowing the user to interact with the application. 3335 * 3336 * <p>This has the same visual effect as 3337 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 3338 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 3339 * meaning that non-critical screen decorations (such as the status bar) will be 3340 * hidden while the user is in the View's window, focusing the experience on 3341 * that content. Unlike the window flag, if you are using ActionBar in 3342 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 3343 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 3344 * hide the action bar. 3345 * 3346 * <p>This approach to going fullscreen is best used over the window flag when 3347 * it is a transient state -- that is, the application does this at certain 3348 * points in its user interaction where it wants to allow the user to focus 3349 * on content, but not as a continuous state. For situations where the application 3350 * would like to simply stay full screen the entire time (such as a game that 3351 * wants to take over the screen), the 3352 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 3353 * is usually a better approach. The state set here will be removed by the system 3354 * in various situations (such as the user moving to another application) like 3355 * the other system UI states. 3356 * 3357 * <p>When using this flag, the application should provide some easy facility 3358 * for the user to go out of it. A common example would be in an e-book 3359 * reader, where tapping on the screen brings back whatever screen and UI 3360 * decorations that had been hidden while the user was immersed in reading 3361 * the book. 3362 * 3363 * @see #setSystemUiVisibility(int) 3364 */ 3365 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 3366 3367 /** 3368 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 3369 * flags, we would like a stable view of the content insets given to 3370 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 3371 * will always represent the worst case that the application can expect 3372 * as a continuous state. In the stock Android UI this is the space for 3373 * the system bar, nav bar, and status bar, but not more transient elements 3374 * such as an input method. 3375 * 3376 * The stable layout your UI sees is based on the system UI modes you can 3377 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 3378 * then you will get a stable layout for changes of the 3379 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 3380 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 3381 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 3382 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 3383 * with a stable layout. (Note that you should avoid using 3384 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 3385 * 3386 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 3387 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 3388 * then a hidden status bar will be considered a "stable" state for purposes 3389 * here. This allows your UI to continually hide the status bar, while still 3390 * using the system UI flags to hide the action bar while still retaining 3391 * a stable layout. Note that changing the window fullscreen flag will never 3392 * provide a stable layout for a clean transition. 3393 * 3394 * <p>If you are using ActionBar in 3395 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 3396 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 3397 * insets it adds to those given to the application. 3398 */ 3399 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 3400 3401 /** 3402 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 3403 * to be laid out as if it has requested 3404 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 3405 * allows it to avoid artifacts when switching in and out of that mode, at 3406 * the expense that some of its user interface may be covered by screen 3407 * decorations when they are shown. You can perform layout of your inner 3408 * UI elements to account for the navigation system UI through the 3409 * {@link #fitSystemWindows(Rect)} method. 3410 */ 3411 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 3412 3413 /** 3414 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 3415 * to be laid out as if it has requested 3416 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 3417 * allows it to avoid artifacts when switching in and out of that mode, at 3418 * the expense that some of its user interface may be covered by screen 3419 * decorations when they are shown. You can perform layout of your inner 3420 * UI elements to account for non-fullscreen system UI through the 3421 * {@link #fitSystemWindows(Rect)} method. 3422 * 3423 * <p>Note: on displays that have a {@link DisplayCutout}, the window may still be placed 3424 * differently than if {@link #SYSTEM_UI_FLAG_FULLSCREEN} was set, if the 3425 * window's {@link WindowManager.LayoutParams#layoutInDisplayCutoutMode 3426 * layoutInDisplayCutoutMode} is 3427 * {@link WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 3428 * LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT}. To avoid this, use either of the other modes. 3429 * 3430 * @see WindowManager.LayoutParams#layoutInDisplayCutoutMode 3431 * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 3432 * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 3433 * @see WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER 3434 */ 3435 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 3436 3437 /** 3438 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 3439 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 3440 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 3441 * user interaction. 3442 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 3443 * has an effect when used in combination with that flag.</p> 3444 */ 3445 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 3446 3447 /** 3448 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 3449 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 3450 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 3451 * experience while also hiding the system bars. If this flag is not set, 3452 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 3453 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 3454 * if the user swipes from the top of the screen. 3455 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 3456 * system gestures, such as swiping from the top of the screen. These transient system bars 3457 * will overlay app’s content, may have some degree of transparency, and will automatically 3458 * hide after a short timeout. 3459 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 3460 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 3461 * with one or both of those flags.</p> 3462 */ 3463 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 3464 3465 /** 3466 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that 3467 * is compatible with light status bar backgrounds. 3468 * 3469 * <p>For this to take effect, the window must request 3470 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 3471 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not 3472 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS 3473 * FLAG_TRANSLUCENT_STATUS}. 3474 * 3475 * @see android.R.attr#windowLightStatusBar 3476 */ 3477 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; 3478 3479 /** 3480 * This flag was previously used for a private API. DO NOT reuse it for a public API as it might 3481 * trigger undefined behavior on older platforms with apps compiled against a new SDK. 3482 */ 3483 private static final int SYSTEM_UI_RESERVED_LEGACY1 = 0x00004000; 3484 3485 /** 3486 * This flag was previously used for a private API. DO NOT reuse it for a public API as it might 3487 * trigger undefined behavior on older platforms with apps compiled against a new SDK. 3488 */ 3489 private static final int SYSTEM_UI_RESERVED_LEGACY2 = 0x00010000; 3490 3491 /** 3492 * Flag for {@link #setSystemUiVisibility(int)}: Requests the navigation bar to draw in a mode 3493 * that is compatible with light navigation bar backgrounds. 3494 * 3495 * <p>For this to take effect, the window must request 3496 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 3497 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not 3498 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION 3499 * FLAG_TRANSLUCENT_NAVIGATION}. 3500 * 3501 * @see android.R.attr#windowLightNavigationBar 3502 */ 3503 public static final int SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR = 0x00000010; 3504 3505 /** 3506 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 3507 */ 3508 @Deprecated 3509 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 3510 3511 /** 3512 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 3513 */ 3514 @Deprecated 3515 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 3516 3517 /** 3518 * @hide 3519 * 3520 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3521 * out of the public fields to keep the undefined bits out of the developer's way. 3522 * 3523 * Flag to make the status bar not expandable. Unless you also 3524 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 3525 */ 3526 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 3527 3528 /** 3529 * @hide 3530 * 3531 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3532 * out of the public fields to keep the undefined bits out of the developer's way. 3533 * 3534 * Flag to hide notification icons and scrolling ticker text. 3535 */ 3536 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 3537 3538 /** 3539 * @hide 3540 * 3541 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3542 * out of the public fields to keep the undefined bits out of the developer's way. 3543 * 3544 * Flag to disable incoming notification alerts. This will not block 3545 * icons, but it will block sound, vibrating and other visual or aural notifications. 3546 */ 3547 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 3548 3549 /** 3550 * @hide 3551 * 3552 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3553 * out of the public fields to keep the undefined bits out of the developer's way. 3554 * 3555 * Flag to hide only the scrolling ticker. Note that 3556 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 3557 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 3558 */ 3559 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 3560 3561 /** 3562 * @hide 3563 * 3564 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3565 * out of the public fields to keep the undefined bits out of the developer's way. 3566 * 3567 * Flag to hide the center system info area. 3568 */ 3569 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 3570 3571 /** 3572 * @hide 3573 * 3574 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3575 * out of the public fields to keep the undefined bits out of the developer's way. 3576 * 3577 * Flag to hide only the home button. Don't use this 3578 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3579 */ 3580 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 3581 3582 /** 3583 * @hide 3584 * 3585 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3586 * out of the public fields to keep the undefined bits out of the developer's way. 3587 * 3588 * Flag to hide only the back button. Don't use this 3589 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3590 */ 3591 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 3592 3593 /** 3594 * @hide 3595 * 3596 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3597 * out of the public fields to keep the undefined bits out of the developer's way. 3598 * 3599 * Flag to hide only the clock. You might use this if your activity has 3600 * its own clock making the status bar's clock redundant. 3601 */ 3602 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 3603 3604 /** 3605 * @hide 3606 * 3607 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3608 * out of the public fields to keep the undefined bits out of the developer's way. 3609 * 3610 * Flag to hide only the recent apps button. Don't use this 3611 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3612 */ 3613 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 3614 3615 /** 3616 * @hide 3617 * 3618 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3619 * out of the public fields to keep the undefined bits out of the developer's way. 3620 * 3621 * Flag to disable the global search gesture. Don't use this 3622 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3623 */ 3624 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 3625 3626 /** 3627 * @hide 3628 * 3629 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3630 * out of the public fields to keep the undefined bits out of the developer's way. 3631 * 3632 * Flag to specify that the status bar is displayed in transient mode. 3633 */ 3634 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 3635 3636 /** 3637 * @hide 3638 * 3639 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3640 * out of the public fields to keep the undefined bits out of the developer's way. 3641 * 3642 * Flag to specify that the navigation bar is displayed in transient mode. 3643 */ 3644 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 3645 3646 /** 3647 * @hide 3648 * 3649 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3650 * out of the public fields to keep the undefined bits out of the developer's way. 3651 * 3652 * Flag to specify that the hidden status bar would like to be shown. 3653 */ 3654 public static final int STATUS_BAR_UNHIDE = 0x10000000; 3655 3656 /** 3657 * @hide 3658 * 3659 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3660 * out of the public fields to keep the undefined bits out of the developer's way. 3661 * 3662 * Flag to specify that the hidden navigation bar would like to be shown. 3663 */ 3664 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 3665 3666 /** 3667 * @hide 3668 * 3669 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3670 * out of the public fields to keep the undefined bits out of the developer's way. 3671 * 3672 * Flag to specify that the status bar is displayed in translucent mode. 3673 */ 3674 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 3675 3676 /** 3677 * @hide 3678 * 3679 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3680 * out of the public fields to keep the undefined bits out of the developer's way. 3681 * 3682 * Flag to specify that the navigation bar is displayed in translucent mode. 3683 */ 3684 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 3685 3686 /** 3687 * @hide 3688 * 3689 * Makes navigation bar transparent (but not the status bar). 3690 */ 3691 public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000; 3692 3693 /** 3694 * @hide 3695 * 3696 * Makes status bar transparent (but not the navigation bar). 3697 */ 3698 public static final int STATUS_BAR_TRANSPARENT = 0x00000008; 3699 3700 /** 3701 * @hide 3702 * 3703 * Makes both status bar and navigation bar transparent. 3704 */ 3705 public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT 3706 | STATUS_BAR_TRANSPARENT; 3707 3708 /** 3709 * @hide 3710 */ 3711 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7; 3712 3713 /** 3714 * These are the system UI flags that can be cleared by events outside 3715 * of an application. Currently this is just the ability to tap on the 3716 * screen while hiding the navigation bar to have it return. 3717 * @hide 3718 */ 3719 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 3720 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 3721 | SYSTEM_UI_FLAG_FULLSCREEN; 3722 3723 /** 3724 * Flags that can impact the layout in relation to system UI. 3725 */ 3726 public static final int SYSTEM_UI_LAYOUT_FLAGS = 3727 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 3728 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 3729 3730 /** @hide */ 3731 @IntDef(flag = true, prefix = { "FIND_VIEWS_" }, value = { 3732 FIND_VIEWS_WITH_TEXT, 3733 FIND_VIEWS_WITH_CONTENT_DESCRIPTION 3734 }) 3735 @Retention(RetentionPolicy.SOURCE) 3736 public @interface FindViewFlags {} 3737 3738 /** 3739 * Find views that render the specified text. 3740 * 3741 * @see #findViewsWithText(ArrayList, CharSequence, int) 3742 */ 3743 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 3744 3745 /** 3746 * Find find views that contain the specified content description. 3747 * 3748 * @see #findViewsWithText(ArrayList, CharSequence, int) 3749 */ 3750 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 3751 3752 /** 3753 * Find views that contain {@link AccessibilityNodeProvider}. Such 3754 * a View is a root of virtual view hierarchy and may contain the searched 3755 * text. If this flag is set Views with providers are automatically 3756 * added and it is a responsibility of the client to call the APIs of 3757 * the provider to determine whether the virtual tree rooted at this View 3758 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 3759 * representing the virtual views with this text. 3760 * 3761 * @see #findViewsWithText(ArrayList, CharSequence, int) 3762 * 3763 * @hide 3764 */ 3765 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 3766 3767 /** 3768 * The undefined cursor position. 3769 * 3770 * @hide 3771 */ 3772 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 3773 3774 /** 3775 * Indicates that the screen has changed state and is now off. 3776 * 3777 * @see #onScreenStateChanged(int) 3778 */ 3779 public static final int SCREEN_STATE_OFF = 0x0; 3780 3781 /** 3782 * Indicates that the screen has changed state and is now on. 3783 * 3784 * @see #onScreenStateChanged(int) 3785 */ 3786 public static final int SCREEN_STATE_ON = 0x1; 3787 3788 /** 3789 * Indicates no axis of view scrolling. 3790 */ 3791 public static final int SCROLL_AXIS_NONE = 0; 3792 3793 /** 3794 * Indicates scrolling along the horizontal axis. 3795 */ 3796 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0; 3797 3798 /** 3799 * Indicates scrolling along the vertical axis. 3800 */ 3801 public static final int SCROLL_AXIS_VERTICAL = 1 << 1; 3802 3803 /** 3804 * Controls the over-scroll mode for this view. 3805 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 3806 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 3807 * and {@link #OVER_SCROLL_NEVER}. 3808 */ 3809 private int mOverScrollMode; 3810 3811 /** 3812 * The parent this view is attached to. 3813 * {@hide} 3814 * 3815 * @see #getParent() 3816 */ 3817 protected ViewParent mParent; 3818 3819 /** 3820 * {@hide} 3821 */ 3822 AttachInfo mAttachInfo; 3823 3824 /** 3825 * {@hide} 3826 */ 3827 @ViewDebug.ExportedProperty(flagMapping = { 3828 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 3829 name = "FORCE_LAYOUT"), 3830 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 3831 name = "LAYOUT_REQUIRED"), 3832 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 3833 name = "DRAWING_CACHE_INVALID", outputIf = false), 3834 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 3835 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 3836 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 3837 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 3838 }, formatToHexString = true) 3839 3840 /* @hide */ 3841 public int mPrivateFlags; 3842 int mPrivateFlags2; 3843 int mPrivateFlags3; 3844 3845 /** 3846 * This view's request for the visibility of the status bar. 3847 * @hide 3848 */ 3849 @ViewDebug.ExportedProperty(flagMapping = { 3850 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 3851 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 3852 name = "LOW_PROFILE"), 3853 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3854 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3855 name = "HIDE_NAVIGATION"), 3856 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN, 3857 equals = SYSTEM_UI_FLAG_FULLSCREEN, 3858 name = "FULLSCREEN"), 3859 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE, 3860 equals = SYSTEM_UI_FLAG_LAYOUT_STABLE, 3861 name = "LAYOUT_STABLE"), 3862 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION, 3863 equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION, 3864 name = "LAYOUT_HIDE_NAVIGATION"), 3865 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, 3866 equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, 3867 name = "LAYOUT_FULLSCREEN"), 3868 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE, 3869 equals = SYSTEM_UI_FLAG_IMMERSIVE, 3870 name = "IMMERSIVE"), 3871 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY, 3872 equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY, 3873 name = "IMMERSIVE_STICKY"), 3874 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, 3875 equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, 3876 name = "LIGHT_STATUS_BAR"), 3877 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, 3878 equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, 3879 name = "LIGHT_NAVIGATION_BAR"), 3880 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND, 3881 equals = STATUS_BAR_DISABLE_EXPAND, 3882 name = "STATUS_BAR_DISABLE_EXPAND"), 3883 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS, 3884 equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS, 3885 name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"), 3886 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS, 3887 equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS, 3888 name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"), 3889 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER, 3890 equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER, 3891 name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"), 3892 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO, 3893 equals = STATUS_BAR_DISABLE_SYSTEM_INFO, 3894 name = "STATUS_BAR_DISABLE_SYSTEM_INFO"), 3895 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME, 3896 equals = STATUS_BAR_DISABLE_HOME, 3897 name = "STATUS_BAR_DISABLE_HOME"), 3898 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK, 3899 equals = STATUS_BAR_DISABLE_BACK, 3900 name = "STATUS_BAR_DISABLE_BACK"), 3901 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK, 3902 equals = STATUS_BAR_DISABLE_CLOCK, 3903 name = "STATUS_BAR_DISABLE_CLOCK"), 3904 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT, 3905 equals = STATUS_BAR_DISABLE_RECENT, 3906 name = "STATUS_BAR_DISABLE_RECENT"), 3907 @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH, 3908 equals = STATUS_BAR_DISABLE_SEARCH, 3909 name = "STATUS_BAR_DISABLE_SEARCH"), 3910 @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT, 3911 equals = STATUS_BAR_TRANSIENT, 3912 name = "STATUS_BAR_TRANSIENT"), 3913 @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT, 3914 equals = NAVIGATION_BAR_TRANSIENT, 3915 name = "NAVIGATION_BAR_TRANSIENT"), 3916 @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE, 3917 equals = STATUS_BAR_UNHIDE, 3918 name = "STATUS_BAR_UNHIDE"), 3919 @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE, 3920 equals = NAVIGATION_BAR_UNHIDE, 3921 name = "NAVIGATION_BAR_UNHIDE"), 3922 @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT, 3923 equals = STATUS_BAR_TRANSLUCENT, 3924 name = "STATUS_BAR_TRANSLUCENT"), 3925 @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT, 3926 equals = NAVIGATION_BAR_TRANSLUCENT, 3927 name = "NAVIGATION_BAR_TRANSLUCENT"), 3928 @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT, 3929 equals = NAVIGATION_BAR_TRANSPARENT, 3930 name = "NAVIGATION_BAR_TRANSPARENT"), 3931 @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT, 3932 equals = STATUS_BAR_TRANSPARENT, 3933 name = "STATUS_BAR_TRANSPARENT") 3934 }, formatToHexString = true) 3935 int mSystemUiVisibility; 3936 3937 /** 3938 * Reference count for transient state. 3939 * @see #setHasTransientState(boolean) 3940 */ 3941 int mTransientStateCount = 0; 3942 3943 /** 3944 * Count of how many windows this view has been attached to. 3945 */ 3946 int mWindowAttachCount; 3947 3948 /** 3949 * The layout parameters associated with this view and used by the parent 3950 * {@link android.view.ViewGroup} to determine how this view should be 3951 * laid out. 3952 * {@hide} 3953 */ 3954 protected ViewGroup.LayoutParams mLayoutParams; 3955 3956 /** 3957 * The view flags hold various views states. 3958 * {@hide} 3959 */ 3960 @ViewDebug.ExportedProperty(formatToHexString = true) 3961 int mViewFlags; 3962 3963 static class TransformationInfo { 3964 /** 3965 * The transform matrix for the View. This transform is calculated internally 3966 * based on the translation, rotation, and scale properties. 3967 * 3968 * Do *not* use this variable directly; instead call getMatrix(), which will 3969 * load the value from the View's RenderNode. 3970 */ 3971 private final Matrix mMatrix = new Matrix(); 3972 3973 /** 3974 * The inverse transform matrix for the View. This transform is calculated 3975 * internally based on the translation, rotation, and scale properties. 3976 * 3977 * Do *not* use this variable directly; instead call getInverseMatrix(), 3978 * which will load the value from the View's RenderNode. 3979 */ 3980 private Matrix mInverseMatrix; 3981 3982 /** 3983 * The opacity of the View. This is a value from 0 to 1, where 0 means 3984 * completely transparent and 1 means completely opaque. 3985 */ 3986 @ViewDebug.ExportedProperty 3987 float mAlpha = 1f; 3988 3989 /** 3990 * The opacity of the view as manipulated by the Fade transition. This is a hidden 3991 * property only used by transitions, which is composited with the other alpha 3992 * values to calculate the final visual alpha value. 3993 */ 3994 float mTransitionAlpha = 1f; 3995 } 3996 3997 /** @hide */ 3998 public TransformationInfo mTransformationInfo; 3999 4000 /** 4001 * Current clip bounds. to which all drawing of this view are constrained. 4002 */ 4003 @ViewDebug.ExportedProperty(category = "drawing") 4004 Rect mClipBounds = null; 4005 4006 private boolean mLastIsOpaque; 4007 4008 /** 4009 * The distance in pixels from the left edge of this view's parent 4010 * to the left edge of this view. 4011 * {@hide} 4012 */ 4013 @ViewDebug.ExportedProperty(category = "layout") 4014 protected int mLeft; 4015 /** 4016 * The distance in pixels from the left edge of this view's parent 4017 * to the right edge of this view. 4018 * {@hide} 4019 */ 4020 @ViewDebug.ExportedProperty(category = "layout") 4021 protected int mRight; 4022 /** 4023 * The distance in pixels from the top edge of this view's parent 4024 * to the top edge of this view. 4025 * {@hide} 4026 */ 4027 @ViewDebug.ExportedProperty(category = "layout") 4028 protected int mTop; 4029 /** 4030 * The distance in pixels from the top edge of this view's parent 4031 * to the bottom edge of this view. 4032 * {@hide} 4033 */ 4034 @ViewDebug.ExportedProperty(category = "layout") 4035 protected int mBottom; 4036 4037 /** 4038 * The offset, in pixels, by which the content of this view is scrolled 4039 * horizontally. 4040 * {@hide} 4041 */ 4042 @ViewDebug.ExportedProperty(category = "scrolling") 4043 protected int mScrollX; 4044 /** 4045 * The offset, in pixels, by which the content of this view is scrolled 4046 * vertically. 4047 * {@hide} 4048 */ 4049 @ViewDebug.ExportedProperty(category = "scrolling") 4050 protected int mScrollY; 4051 4052 /** 4053 * The left padding in pixels, that is the distance in pixels between the 4054 * left edge of this view and the left edge of its content. 4055 * {@hide} 4056 */ 4057 @ViewDebug.ExportedProperty(category = "padding") 4058 protected int mPaddingLeft = 0; 4059 /** 4060 * The right padding in pixels, that is the distance in pixels between the 4061 * right edge of this view and the right edge of its content. 4062 * {@hide} 4063 */ 4064 @ViewDebug.ExportedProperty(category = "padding") 4065 protected int mPaddingRight = 0; 4066 /** 4067 * The top padding in pixels, that is the distance in pixels between the 4068 * top edge of this view and the top edge of its content. 4069 * {@hide} 4070 */ 4071 @ViewDebug.ExportedProperty(category = "padding") 4072 protected int mPaddingTop; 4073 /** 4074 * The bottom padding in pixels, that is the distance in pixels between the 4075 * bottom edge of this view and the bottom edge of its content. 4076 * {@hide} 4077 */ 4078 @ViewDebug.ExportedProperty(category = "padding") 4079 protected int mPaddingBottom; 4080 4081 /** 4082 * The layout insets in pixels, that is the distance in pixels between the 4083 * visible edges of this view its bounds. 4084 */ 4085 private Insets mLayoutInsets; 4086 4087 /** 4088 * Briefly describes the view and is primarily used for accessibility support. 4089 */ 4090 private CharSequence mContentDescription; 4091 4092 /** 4093 * If this view represents a distinct part of the window, it can have a title that labels the 4094 * area. 4095 */ 4096 private CharSequence mAccessibilityPaneTitle; 4097 4098 /** 4099 * Specifies the id of a view for which this view serves as a label for 4100 * accessibility purposes. 4101 */ 4102 private int mLabelForId = View.NO_ID; 4103 4104 /** 4105 * Predicate for matching labeled view id with its label for 4106 * accessibility purposes. 4107 */ 4108 private MatchLabelForPredicate mMatchLabelForPredicate; 4109 4110 /** 4111 * Specifies a view before which this one is visited in accessibility traversal. 4112 */ 4113 private int mAccessibilityTraversalBeforeId = NO_ID; 4114 4115 /** 4116 * Specifies a view after which this one is visited in accessibility traversal. 4117 */ 4118 private int mAccessibilityTraversalAfterId = NO_ID; 4119 4120 /** 4121 * Predicate for matching a view by its id. 4122 */ 4123 private MatchIdPredicate mMatchIdPredicate; 4124 4125 /** 4126 * Cache the paddingRight set by the user to append to the scrollbar's size. 4127 * 4128 * @hide 4129 */ 4130 @ViewDebug.ExportedProperty(category = "padding") 4131 protected int mUserPaddingRight; 4132 4133 /** 4134 * Cache the paddingBottom set by the user to append to the scrollbar's size. 4135 * 4136 * @hide 4137 */ 4138 @ViewDebug.ExportedProperty(category = "padding") 4139 protected int mUserPaddingBottom; 4140 4141 /** 4142 * Cache the paddingLeft set by the user to append to the scrollbar's size. 4143 * 4144 * @hide 4145 */ 4146 @ViewDebug.ExportedProperty(category = "padding") 4147 protected int mUserPaddingLeft; 4148 4149 /** 4150 * Cache the paddingStart set by the user to append to the scrollbar's size. 4151 * 4152 */ 4153 @ViewDebug.ExportedProperty(category = "padding") 4154 int mUserPaddingStart; 4155 4156 /** 4157 * Cache the paddingEnd set by the user to append to the scrollbar's size. 4158 * 4159 */ 4160 @ViewDebug.ExportedProperty(category = "padding") 4161 int mUserPaddingEnd; 4162 4163 /** 4164 * Cache initial left padding. 4165 * 4166 * @hide 4167 */ 4168 int mUserPaddingLeftInitial; 4169 4170 /** 4171 * Cache initial right padding. 4172 * 4173 * @hide 4174 */ 4175 int mUserPaddingRightInitial; 4176 4177 /** 4178 * Default undefined padding 4179 */ 4180 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 4181 4182 /** 4183 * Cache if a left padding has been defined 4184 */ 4185 private boolean mLeftPaddingDefined = false; 4186 4187 /** 4188 * Cache if a right padding has been defined 4189 */ 4190 private boolean mRightPaddingDefined = false; 4191 4192 /** 4193 * @hide 4194 */ 4195 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 4196 /** 4197 * @hide 4198 */ 4199 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 4200 4201 private LongSparseLongArray mMeasureCache; 4202 4203 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 4204 private Drawable mBackground; 4205 private TintInfo mBackgroundTint; 4206 4207 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") 4208 private ForegroundInfo mForegroundInfo; 4209 4210 private Drawable mScrollIndicatorDrawable; 4211 4212 /** 4213 * RenderNode used for backgrounds. 4214 * <p> 4215 * When non-null and valid, this is expected to contain an up-to-date copy 4216 * of the background drawable. It is cleared on temporary detach, and reset 4217 * on cleanup. 4218 */ 4219 private RenderNode mBackgroundRenderNode; 4220 4221 private int mBackgroundResource; 4222 private boolean mBackgroundSizeChanged; 4223 4224 /** The default focus highlight. 4225 * @see #mDefaultFocusHighlightEnabled 4226 * @see Drawable#hasFocusStateSpecified() 4227 */ 4228 private Drawable mDefaultFocusHighlight; 4229 private Drawable mDefaultFocusHighlightCache; 4230 private boolean mDefaultFocusHighlightSizeChanged; 4231 /** 4232 * True if the default focus highlight is needed on the target device. 4233 */ 4234 private static boolean sUseDefaultFocusHighlight; 4235 4236 /** 4237 * True if zero-sized views can be focused. 4238 */ 4239 private static boolean sCanFocusZeroSized; 4240 4241 /** 4242 * Always assign focus if a focusable View is available. 4243 */ 4244 private static boolean sAlwaysAssignFocus; 4245 4246 private String mTransitionName; 4247 4248 static class TintInfo { 4249 ColorStateList mTintList; 4250 PorterDuff.Mode mTintMode; 4251 boolean mHasTintMode; 4252 boolean mHasTintList; 4253 } 4254 4255 private static class ForegroundInfo { 4256 private Drawable mDrawable; 4257 private TintInfo mTintInfo; 4258 private int mGravity = Gravity.FILL; 4259 private boolean mInsidePadding = true; 4260 private boolean mBoundsChanged = true; 4261 private final Rect mSelfBounds = new Rect(); 4262 private final Rect mOverlayBounds = new Rect(); 4263 } 4264 4265 static class ListenerInfo { 4266 /** 4267 * Listener used to dispatch focus change events. 4268 * This field should be made private, so it is hidden from the SDK. 4269 * {@hide} 4270 */ 4271 protected OnFocusChangeListener mOnFocusChangeListener; 4272 4273 /** 4274 * Listeners for layout change events. 4275 */ 4276 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 4277 4278 protected OnScrollChangeListener mOnScrollChangeListener; 4279 4280 /** 4281 * Listeners for attach events. 4282 */ 4283 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 4284 4285 /** 4286 * Listener used to dispatch click events. 4287 * This field should be made private, so it is hidden from the SDK. 4288 * {@hide} 4289 */ 4290 public OnClickListener mOnClickListener; 4291 4292 /** 4293 * Listener used to dispatch long click events. 4294 * This field should be made private, so it is hidden from the SDK. 4295 * {@hide} 4296 */ 4297 protected OnLongClickListener mOnLongClickListener; 4298 4299 /** 4300 * Listener used to dispatch context click events. This field should be made private, so it 4301 * is hidden from the SDK. 4302 * {@hide} 4303 */ 4304 protected OnContextClickListener mOnContextClickListener; 4305 4306 /** 4307 * Listener used to build the context menu. 4308 * This field should be made private, so it is hidden from the SDK. 4309 * {@hide} 4310 */ 4311 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 4312 4313 private OnKeyListener mOnKeyListener; 4314 4315 private OnTouchListener mOnTouchListener; 4316 4317 private OnHoverListener mOnHoverListener; 4318 4319 private OnGenericMotionListener mOnGenericMotionListener; 4320 4321 private OnDragListener mOnDragListener; 4322 4323 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 4324 4325 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener; 4326 4327 OnCapturedPointerListener mOnCapturedPointerListener; 4328 4329 private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners; 4330 } 4331 4332 ListenerInfo mListenerInfo; 4333 4334 private static class TooltipInfo { 4335 /** 4336 * Text to be displayed in a tooltip popup. 4337 */ 4338 @Nullable 4339 CharSequence mTooltipText; 4340 4341 /** 4342 * View-relative position of the tooltip anchor point. 4343 */ 4344 int mAnchorX; 4345 int mAnchorY; 4346 4347 /** 4348 * The tooltip popup. 4349 */ 4350 @Nullable 4351 TooltipPopup mTooltipPopup; 4352 4353 /** 4354 * Set to true if the tooltip was shown as a result of a long click. 4355 */ 4356 boolean mTooltipFromLongClick; 4357 4358 /** 4359 * Keep these Runnables so that they can be used to reschedule. 4360 */ 4361 Runnable mShowTooltipRunnable; 4362 Runnable mHideTooltipRunnable; 4363 4364 /** 4365 * Hover move is ignored if it is within this distance in pixels from the previous one. 4366 */ 4367 int mHoverSlop; 4368 4369 /** 4370 * Update the anchor position if it significantly (that is by at least mHoverSlop) 4371 * different from the previously stored position. Ignoring insignificant changes 4372 * filters out the jitter which is typical for such input sources as stylus. 4373 * 4374 * @return True if the position has been updated. 4375 */ updateAnchorPos(MotionEvent event)4376 private boolean updateAnchorPos(MotionEvent event) { 4377 final int newAnchorX = (int) event.getX(); 4378 final int newAnchorY = (int) event.getY(); 4379 if (Math.abs(newAnchorX - mAnchorX) <= mHoverSlop 4380 && Math.abs(newAnchorY - mAnchorY) <= mHoverSlop) { 4381 return false; 4382 } 4383 mAnchorX = newAnchorX; 4384 mAnchorY = newAnchorY; 4385 return true; 4386 } 4387 4388 /** 4389 * Clear the anchor position to ensure that the next change is considered significant. 4390 */ clearAnchorPos()4391 private void clearAnchorPos() { 4392 mAnchorX = Integer.MAX_VALUE; 4393 mAnchorY = Integer.MAX_VALUE; 4394 } 4395 } 4396 4397 TooltipInfo mTooltipInfo; 4398 4399 // Temporary values used to hold (x,y) coordinates when delegating from the 4400 // two-arg performLongClick() method to the legacy no-arg version. 4401 private float mLongClickX = Float.NaN; 4402 private float mLongClickY = Float.NaN; 4403 4404 /** 4405 * The application environment this view lives in. 4406 * This field should be made private, so it is hidden from the SDK. 4407 * {@hide} 4408 */ 4409 @ViewDebug.ExportedProperty(deepExport = true) 4410 protected Context mContext; 4411 4412 private final Resources mResources; 4413 4414 private ScrollabilityCache mScrollCache; 4415 4416 private int[] mDrawableState = null; 4417 4418 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND; 4419 4420 /** 4421 * Animator that automatically runs based on state changes. 4422 */ 4423 private StateListAnimator mStateListAnimator; 4424 4425 /** 4426 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 4427 * the user may specify which view to go to next. 4428 */ 4429 private int mNextFocusLeftId = View.NO_ID; 4430 4431 /** 4432 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 4433 * the user may specify which view to go to next. 4434 */ 4435 private int mNextFocusRightId = View.NO_ID; 4436 4437 /** 4438 * When this view has focus and the next focus is {@link #FOCUS_UP}, 4439 * the user may specify which view to go to next. 4440 */ 4441 private int mNextFocusUpId = View.NO_ID; 4442 4443 /** 4444 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 4445 * the user may specify which view to go to next. 4446 */ 4447 private int mNextFocusDownId = View.NO_ID; 4448 4449 /** 4450 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 4451 * the user may specify which view to go to next. 4452 */ 4453 int mNextFocusForwardId = View.NO_ID; 4454 4455 /** 4456 * User-specified next keyboard navigation cluster in the {@link #FOCUS_FORWARD} direction. 4457 * 4458 * @see #findUserSetNextKeyboardNavigationCluster(View, int) 4459 */ 4460 int mNextClusterForwardId = View.NO_ID; 4461 4462 /** 4463 * Whether this View should use a default focus highlight when it gets focused but doesn't 4464 * have {@link android.R.attr#state_focused} defined in its background. 4465 */ 4466 boolean mDefaultFocusHighlightEnabled = true; 4467 4468 private CheckForLongPress mPendingCheckForLongPress; 4469 private CheckForTap mPendingCheckForTap = null; 4470 private PerformClick mPerformClick; 4471 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 4472 4473 private UnsetPressedState mUnsetPressedState; 4474 4475 /** 4476 * Whether the long press's action has been invoked. The tap's action is invoked on the 4477 * up event while a long press is invoked as soon as the long press duration is reached, so 4478 * a long press could be performed before the tap is checked, in which case the tap's action 4479 * should not be invoked. 4480 */ 4481 private boolean mHasPerformedLongPress; 4482 4483 /** 4484 * Whether a context click button is currently pressed down. This is true when the stylus is 4485 * touching the screen and the primary button has been pressed, or if a mouse's right button is 4486 * pressed. This is false once the button is released or if the stylus has been lifted. 4487 */ 4488 private boolean mInContextButtonPress; 4489 4490 /** 4491 * Whether the next up event should be ignored for the purposes of gesture recognition. This is 4492 * true after a stylus button press has occured, when the next up event should not be recognized 4493 * as a tap. 4494 */ 4495 private boolean mIgnoreNextUpEvent; 4496 4497 /** 4498 * The minimum height of the view. We'll try our best to have the height 4499 * of this view to at least this amount. 4500 */ 4501 @ViewDebug.ExportedProperty(category = "measurement") 4502 private int mMinHeight; 4503 4504 /** 4505 * The minimum width of the view. We'll try our best to have the width 4506 * of this view to at least this amount. 4507 */ 4508 @ViewDebug.ExportedProperty(category = "measurement") 4509 private int mMinWidth; 4510 4511 /** 4512 * The delegate to handle touch events that are physically in this view 4513 * but should be handled by another view. 4514 */ 4515 private TouchDelegate mTouchDelegate = null; 4516 4517 /** 4518 * Solid color to use as a background when creating the drawing cache. Enables 4519 * the cache to use 16 bit bitmaps instead of 32 bit. 4520 */ 4521 private int mDrawingCacheBackgroundColor = 0; 4522 4523 /** 4524 * Special tree observer used when mAttachInfo is null. 4525 */ 4526 private ViewTreeObserver mFloatingTreeObserver; 4527 4528 /** 4529 * Cache the touch slop from the context that created the view. 4530 */ 4531 private int mTouchSlop; 4532 4533 /** 4534 * Object that handles automatic animation of view properties. 4535 */ 4536 private ViewPropertyAnimator mAnimator = null; 4537 4538 /** 4539 * List of registered FrameMetricsObservers. 4540 */ 4541 private ArrayList<FrameMetricsObserver> mFrameMetricsObservers; 4542 4543 /** 4544 * Flag indicating that a drag can cross window boundaries. When 4545 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 4546 * with this flag set, all visible applications with targetSdkVersion >= 4547 * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate 4548 * in the drag operation and receive the dragged content. 4549 * 4550 * <p>If this is the only flag set, then the drag recipient will only have access to text data 4551 * and intents contained in the {@link ClipData} object. Access to URIs contained in the 4552 * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p> 4553 */ 4554 public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256 4555 4556 /** 4557 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 4558 * request read access to the content URI(s) contained in the {@link ClipData} object. 4559 * @see android.content.Intent#FLAG_GRANT_READ_URI_PERMISSION 4560 */ 4561 public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION; 4562 4563 /** 4564 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 4565 * request write access to the content URI(s) contained in the {@link ClipData} object. 4566 * @see android.content.Intent#FLAG_GRANT_WRITE_URI_PERMISSION 4567 */ 4568 public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 4569 4570 /** 4571 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 4572 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device 4573 * reboots until explicitly revoked with 4574 * {@link android.content.Context#revokeUriPermission(Uri, int)} Context.revokeUriPermission}. 4575 * @see android.content.Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION 4576 */ 4577 public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 4578 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; 4579 4580 /** 4581 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 4582 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix 4583 * match against the original granted URI. 4584 * @see android.content.Intent#FLAG_GRANT_PREFIX_URI_PERMISSION 4585 */ 4586 public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 4587 Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; 4588 4589 /** 4590 * Flag indicating that the drag shadow will be opaque. When 4591 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 4592 * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent. 4593 */ 4594 public static final int DRAG_FLAG_OPAQUE = 1 << 9; 4595 4596 /** 4597 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 4598 */ 4599 private float mVerticalScrollFactor; 4600 4601 /** 4602 * Position of the vertical scroll bar. 4603 */ 4604 private int mVerticalScrollbarPosition; 4605 4606 /** 4607 * Position the scroll bar at the default position as determined by the system. 4608 */ 4609 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 4610 4611 /** 4612 * Position the scroll bar along the left edge. 4613 */ 4614 public static final int SCROLLBAR_POSITION_LEFT = 1; 4615 4616 /** 4617 * Position the scroll bar along the right edge. 4618 */ 4619 public static final int SCROLLBAR_POSITION_RIGHT = 2; 4620 4621 /** 4622 * Indicates that the view does not have a layer. 4623 * 4624 * @see #getLayerType() 4625 * @see #setLayerType(int, android.graphics.Paint) 4626 * @see #LAYER_TYPE_SOFTWARE 4627 * @see #LAYER_TYPE_HARDWARE 4628 */ 4629 public static final int LAYER_TYPE_NONE = 0; 4630 4631 /** 4632 * <p>Indicates that the view has a software layer. A software layer is backed 4633 * by a bitmap and causes the view to be rendered using Android's software 4634 * rendering pipeline, even if hardware acceleration is enabled.</p> 4635 * 4636 * <p>Software layers have various usages:</p> 4637 * <p>When the application is not using hardware acceleration, a software layer 4638 * is useful to apply a specific color filter and/or blending mode and/or 4639 * translucency to a view and all its children.</p> 4640 * <p>When the application is using hardware acceleration, a software layer 4641 * is useful to render drawing primitives not supported by the hardware 4642 * accelerated pipeline. It can also be used to cache a complex view tree 4643 * into a texture and reduce the complexity of drawing operations. For instance, 4644 * when animating a complex view tree with a translation, a software layer can 4645 * be used to render the view tree only once.</p> 4646 * <p>Software layers should be avoided when the affected view tree updates 4647 * often. Every update will require to re-render the software layer, which can 4648 * potentially be slow (particularly when hardware acceleration is turned on 4649 * since the layer will have to be uploaded into a hardware texture after every 4650 * update.)</p> 4651 * 4652 * @see #getLayerType() 4653 * @see #setLayerType(int, android.graphics.Paint) 4654 * @see #LAYER_TYPE_NONE 4655 * @see #LAYER_TYPE_HARDWARE 4656 */ 4657 public static final int LAYER_TYPE_SOFTWARE = 1; 4658 4659 /** 4660 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 4661 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 4662 * OpenGL hardware) and causes the view to be rendered using Android's hardware 4663 * rendering pipeline, but only if hardware acceleration is turned on for the 4664 * view hierarchy. When hardware acceleration is turned off, hardware layers 4665 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 4666 * 4667 * <p>A hardware layer is useful to apply a specific color filter and/or 4668 * blending mode and/or translucency to a view and all its children.</p> 4669 * <p>A hardware layer can be used to cache a complex view tree into a 4670 * texture and reduce the complexity of drawing operations. For instance, 4671 * when animating a complex view tree with a translation, a hardware layer can 4672 * be used to render the view tree only once.</p> 4673 * <p>A hardware layer can also be used to increase the rendering quality when 4674 * rotation transformations are applied on a view. It can also be used to 4675 * prevent potential clipping issues when applying 3D transforms on a view.</p> 4676 * 4677 * @see #getLayerType() 4678 * @see #setLayerType(int, android.graphics.Paint) 4679 * @see #LAYER_TYPE_NONE 4680 * @see #LAYER_TYPE_SOFTWARE 4681 */ 4682 public static final int LAYER_TYPE_HARDWARE = 2; 4683 4684 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 4685 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 4686 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 4687 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 4688 }) 4689 int mLayerType = LAYER_TYPE_NONE; 4690 Paint mLayerPaint; 4691 4692 /** 4693 * Set to true when drawing cache is enabled and cannot be created. 4694 * 4695 * @hide 4696 */ 4697 public boolean mCachingFailed; 4698 private Bitmap mDrawingCache; 4699 private Bitmap mUnscaledDrawingCache; 4700 4701 /** 4702 * RenderNode holding View properties, potentially holding a DisplayList of View content. 4703 * <p> 4704 * When non-null and valid, this is expected to contain an up-to-date copy 4705 * of the View content. Its DisplayList content is cleared on temporary detach and reset on 4706 * cleanup. 4707 */ 4708 final RenderNode mRenderNode; 4709 4710 /** 4711 * Set to true when the view is sending hover accessibility events because it 4712 * is the innermost hovered view. 4713 */ 4714 private boolean mSendingHoverAccessibilityEvents; 4715 4716 /** 4717 * Delegate for injecting accessibility functionality. 4718 */ 4719 AccessibilityDelegate mAccessibilityDelegate; 4720 4721 /** 4722 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 4723 * and add/remove objects to/from the overlay directly through the Overlay methods. 4724 */ 4725 ViewOverlay mOverlay; 4726 4727 /** 4728 * The currently active parent view for receiving delegated nested scrolling events. 4729 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared 4730 * by {@link #stopNestedScroll()} at the same point where we clear 4731 * requestDisallowInterceptTouchEvent. 4732 */ 4733 private ViewParent mNestedScrollingParent; 4734 4735 /** 4736 * Consistency verifier for debugging purposes. 4737 * @hide 4738 */ 4739 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 4740 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 4741 new InputEventConsistencyVerifier(this, 0) : null; 4742 4743 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 4744 4745 private int[] mTempNestedScrollConsumed; 4746 4747 /** 4748 * An overlay is going to draw this View instead of being drawn as part of this 4749 * View's parent. mGhostView is the View in the Overlay that must be invalidated 4750 * when this view is invalidated. 4751 */ 4752 GhostView mGhostView; 4753 4754 /** 4755 * Holds pairs of adjacent attribute data: attribute name followed by its value. 4756 * @hide 4757 */ 4758 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true) 4759 public String[] mAttributes; 4760 4761 /** 4762 * Maps a Resource id to its name. 4763 */ 4764 private static SparseArray<String> mAttributeMap; 4765 4766 /** 4767 * Queue of pending runnables. Used to postpone calls to post() until this 4768 * view is attached and has a handler. 4769 */ 4770 private HandlerActionQueue mRunQueue; 4771 4772 /** 4773 * The pointer icon when the mouse hovers on this view. The default is null. 4774 */ 4775 private PointerIcon mPointerIcon; 4776 4777 /** 4778 * @hide 4779 */ 4780 String mStartActivityRequestWho; 4781 4782 @Nullable 4783 private RoundScrollbarRenderer mRoundScrollbarRenderer; 4784 4785 /** Used to delay visibility updates sent to the autofill manager */ 4786 private Handler mVisibilityChangeForAutofillHandler; 4787 4788 /** 4789 * Simple constructor to use when creating a view from code. 4790 * 4791 * @param context The Context the view is running in, through which it can 4792 * access the current theme, resources, etc. 4793 */ View(Context context)4794 public View(Context context) { 4795 mContext = context; 4796 mResources = context != null ? context.getResources() : null; 4797 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO; 4798 // Set some flags defaults 4799 mPrivateFlags2 = 4800 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 4801 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 4802 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 4803 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 4804 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 4805 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 4806 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 4807 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 4808 mUserPaddingStart = UNDEFINED_PADDING; 4809 mUserPaddingEnd = UNDEFINED_PADDING; 4810 mRenderNode = RenderNode.create(getClass().getName(), this); 4811 4812 if (!sCompatibilityDone && context != null) { 4813 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4814 4815 // Older apps may need this compatibility hack for measurement. 4816 sUseBrokenMakeMeasureSpec = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1; 4817 4818 // Older apps expect onMeasure() to always be called on a layout pass, regardless 4819 // of whether a layout was requested on that View. 4820 sIgnoreMeasureCache = targetSdkVersion < Build.VERSION_CODES.KITKAT; 4821 4822 Canvas.sCompatibilityRestore = targetSdkVersion < Build.VERSION_CODES.M; 4823 Canvas.sCompatibilitySetBitmap = targetSdkVersion < Build.VERSION_CODES.O; 4824 Canvas.setCompatibilityVersion(targetSdkVersion); 4825 4826 // In M and newer, our widgets can pass a "hint" value in the size 4827 // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers 4828 // know what the expected parent size is going to be, so e.g. list items can size 4829 // themselves at 1/3 the size of their container. It breaks older apps though, 4830 // specifically apps that use some popular open source libraries. 4831 sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < Build.VERSION_CODES.M; 4832 4833 // Old versions of the platform would give different results from 4834 // LinearLayout measurement passes using EXACTLY and non-EXACTLY 4835 // modes, so we always need to run an additional EXACTLY pass. 4836 sAlwaysRemeasureExactly = targetSdkVersion <= Build.VERSION_CODES.M; 4837 4838 // Prior to N, layout params could change without requiring a 4839 // subsequent call to setLayoutParams() and they would usually 4840 // work. Partial layout breaks this assumption. 4841 sLayoutParamsAlwaysChanged = targetSdkVersion <= Build.VERSION_CODES.M; 4842 4843 // Prior to N, TextureView would silently ignore calls to setBackground/setForeground. 4844 // On N+, we throw, but that breaks compatibility with apps that use these methods. 4845 sTextureViewIgnoresDrawableSetters = targetSdkVersion <= Build.VERSION_CODES.M; 4846 4847 // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs 4848 // in apps so we target check it to avoid breaking existing apps. 4849 sPreserveMarginParamsInLayoutParamConversion = 4850 targetSdkVersion >= Build.VERSION_CODES.N; 4851 4852 sCascadedDragDrop = targetSdkVersion < Build.VERSION_CODES.N; 4853 4854 sHasFocusableExcludeAutoFocusable = targetSdkVersion < Build.VERSION_CODES.O; 4855 4856 sAutoFocusableOffUIThreadWontNotifyParents = targetSdkVersion < Build.VERSION_CODES.O; 4857 4858 sUseDefaultFocusHighlight = context.getResources().getBoolean( 4859 com.android.internal.R.bool.config_useDefaultFocusHighlight); 4860 4861 sThrowOnInvalidFloatProperties = targetSdkVersion >= Build.VERSION_CODES.P; 4862 4863 sCanFocusZeroSized = targetSdkVersion < Build.VERSION_CODES.P; 4864 4865 sAlwaysAssignFocus = targetSdkVersion < Build.VERSION_CODES.P; 4866 4867 sAcceptZeroSizeDragShadow = targetSdkVersion < Build.VERSION_CODES.P; 4868 4869 sCompatibilityDone = true; 4870 } 4871 } 4872 4873 /** 4874 * Constructor that is called when inflating a view from XML. This is called 4875 * when a view is being constructed from an XML file, supplying attributes 4876 * that were specified in the XML file. This version uses a default style of 4877 * 0, so the only attribute values applied are those in the Context's Theme 4878 * and the given AttributeSet. 4879 * 4880 * <p> 4881 * The method onFinishInflate() will be called after all children have been 4882 * added. 4883 * 4884 * @param context The Context the view is running in, through which it can 4885 * access the current theme, resources, etc. 4886 * @param attrs The attributes of the XML tag that is inflating the view. 4887 * @see #View(Context, AttributeSet, int) 4888 */ 4889 public View(Context context, @Nullable AttributeSet attrs) { 4890 this(context, attrs, 0); 4891 } 4892 4893 /** 4894 * Perform inflation from XML and apply a class-specific base style from a 4895 * theme attribute. This constructor of View allows subclasses to use their 4896 * own base style when they are inflating. For example, a Button class's 4897 * constructor would call this version of the super class constructor and 4898 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this 4899 * allows the theme's button style to modify all of the base view attributes 4900 * (in particular its background) as well as the Button class's attributes. 4901 * 4902 * @param context The Context the view is running in, through which it can 4903 * access the current theme, resources, etc. 4904 * @param attrs The attributes of the XML tag that is inflating the view. 4905 * @param defStyleAttr An attribute in the current theme that contains a 4906 * reference to a style resource that supplies default values for 4907 * the view. Can be 0 to not look for defaults. 4908 * @see #View(Context, AttributeSet) 4909 */ 4910 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 4911 this(context, attrs, defStyleAttr, 0); 4912 } 4913 4914 /** 4915 * Perform inflation from XML and apply a class-specific base style from a 4916 * theme attribute or style resource. This constructor of View allows 4917 * subclasses to use their own base style when they are inflating. 4918 * <p> 4919 * When determining the final value of a particular attribute, there are 4920 * four inputs that come into play: 4921 * <ol> 4922 * <li>Any attribute values in the given AttributeSet. 4923 * <li>The style resource specified in the AttributeSet (named "style"). 4924 * <li>The default style specified by <var>defStyleAttr</var>. 4925 * <li>The default style specified by <var>defStyleRes</var>. 4926 * <li>The base values in this theme. 4927 * </ol> 4928 * <p> 4929 * Each of these inputs is considered in-order, with the first listed taking 4930 * precedence over the following ones. In other words, if in the 4931 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code> 4932 * , then the button's text will <em>always</em> be black, regardless of 4933 * what is specified in any of the styles. 4934 * 4935 * @param context The Context the view is running in, through which it can 4936 * access the current theme, resources, etc. 4937 * @param attrs The attributes of the XML tag that is inflating the view. 4938 * @param defStyleAttr An attribute in the current theme that contains a 4939 * reference to a style resource that supplies default values for 4940 * the view. Can be 0 to not look for defaults. 4941 * @param defStyleRes A resource identifier of a style resource that 4942 * supplies default values for the view, used only if 4943 * defStyleAttr is 0 or can not be found in the theme. Can be 0 4944 * to not look for defaults. 4945 * @see #View(Context, AttributeSet, int) 4946 */ 4947 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 4948 this(context); 4949 4950 final TypedArray a = context.obtainStyledAttributes( 4951 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); 4952 4953 if (mDebugViewAttributes) { 4954 saveAttributeData(attrs, a); 4955 } 4956 4957 Drawable background = null; 4958 4959 int leftPadding = -1; 4960 int topPadding = -1; 4961 int rightPadding = -1; 4962 int bottomPadding = -1; 4963 int startPadding = UNDEFINED_PADDING; 4964 int endPadding = UNDEFINED_PADDING; 4965 4966 int padding = -1; 4967 int paddingHorizontal = -1; 4968 int paddingVertical = -1; 4969 4970 int viewFlagValues = 0; 4971 int viewFlagMasks = 0; 4972 4973 boolean setScrollContainer = false; 4974 4975 int x = 0; 4976 int y = 0; 4977 4978 float tx = 0; 4979 float ty = 0; 4980 float tz = 0; 4981 float elevation = 0; 4982 float rotation = 0; 4983 float rotationX = 0; 4984 float rotationY = 0; 4985 float sx = 1f; 4986 float sy = 1f; 4987 boolean transformSet = false; 4988 4989 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 4990 int overScrollMode = mOverScrollMode; 4991 boolean initializeScrollbars = false; 4992 boolean initializeScrollIndicators = false; 4993 4994 boolean startPaddingDefined = false; 4995 boolean endPaddingDefined = false; 4996 boolean leftPaddingDefined = false; 4997 boolean rightPaddingDefined = false; 4998 4999 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 5000 5001 // Set default values. 5002 viewFlagValues |= FOCUSABLE_AUTO; 5003 viewFlagMasks |= FOCUSABLE_AUTO; 5004 5005 final int N = a.getIndexCount(); 5006 for (int i = 0; i < N; i++) { 5007 int attr = a.getIndex(i); 5008 switch (attr) { 5009 case com.android.internal.R.styleable.View_background: 5010 background = a.getDrawable(attr); 5011 break; 5012 case com.android.internal.R.styleable.View_padding: 5013 padding = a.getDimensionPixelSize(attr, -1); 5014 mUserPaddingLeftInitial = padding; 5015 mUserPaddingRightInitial = padding; 5016 leftPaddingDefined = true; 5017 rightPaddingDefined = true; 5018 break; 5019 case com.android.internal.R.styleable.View_paddingHorizontal: 5020 paddingHorizontal = a.getDimensionPixelSize(attr, -1); 5021 mUserPaddingLeftInitial = paddingHorizontal; 5022 mUserPaddingRightInitial = paddingHorizontal; 5023 leftPaddingDefined = true; 5024 rightPaddingDefined = true; 5025 break; 5026 case com.android.internal.R.styleable.View_paddingVertical: 5027 paddingVertical = a.getDimensionPixelSize(attr, -1); 5028 break; 5029 case com.android.internal.R.styleable.View_paddingLeft: 5030 leftPadding = a.getDimensionPixelSize(attr, -1); 5031 mUserPaddingLeftInitial = leftPadding; 5032 leftPaddingDefined = true; 5033 break; 5034 case com.android.internal.R.styleable.View_paddingTop: 5035 topPadding = a.getDimensionPixelSize(attr, -1); 5036 break; 5037 case com.android.internal.R.styleable.View_paddingRight: 5038 rightPadding = a.getDimensionPixelSize(attr, -1); 5039 mUserPaddingRightInitial = rightPadding; 5040 rightPaddingDefined = true; 5041 break; 5042 case com.android.internal.R.styleable.View_paddingBottom: 5043 bottomPadding = a.getDimensionPixelSize(attr, -1); 5044 break; 5045 case com.android.internal.R.styleable.View_paddingStart: 5046 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 5047 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 5048 break; 5049 case com.android.internal.R.styleable.View_paddingEnd: 5050 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 5051 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 5052 break; 5053 case com.android.internal.R.styleable.View_scrollX: 5054 x = a.getDimensionPixelOffset(attr, 0); 5055 break; 5056 case com.android.internal.R.styleable.View_scrollY: 5057 y = a.getDimensionPixelOffset(attr, 0); 5058 break; 5059 case com.android.internal.R.styleable.View_alpha: 5060 setAlpha(a.getFloat(attr, 1f)); 5061 break; 5062 case com.android.internal.R.styleable.View_transformPivotX: 5063 setPivotX(a.getDimension(attr, 0)); 5064 break; 5065 case com.android.internal.R.styleable.View_transformPivotY: 5066 setPivotY(a.getDimension(attr, 0)); 5067 break; 5068 case com.android.internal.R.styleable.View_translationX: 5069 tx = a.getDimension(attr, 0); 5070 transformSet = true; 5071 break; 5072 case com.android.internal.R.styleable.View_translationY: 5073 ty = a.getDimension(attr, 0); 5074 transformSet = true; 5075 break; 5076 case com.android.internal.R.styleable.View_translationZ: 5077 tz = a.getDimension(attr, 0); 5078 transformSet = true; 5079 break; 5080 case com.android.internal.R.styleable.View_elevation: 5081 elevation = a.getDimension(attr, 0); 5082 transformSet = true; 5083 break; 5084 case com.android.internal.R.styleable.View_rotation: 5085 rotation = a.getFloat(attr, 0); 5086 transformSet = true; 5087 break; 5088 case com.android.internal.R.styleable.View_rotationX: 5089 rotationX = a.getFloat(attr, 0); 5090 transformSet = true; 5091 break; 5092 case com.android.internal.R.styleable.View_rotationY: 5093 rotationY = a.getFloat(attr, 0); 5094 transformSet = true; 5095 break; 5096 case com.android.internal.R.styleable.View_scaleX: 5097 sx = a.getFloat(attr, 1f); 5098 transformSet = true; 5099 break; 5100 case com.android.internal.R.styleable.View_scaleY: 5101 sy = a.getFloat(attr, 1f); 5102 transformSet = true; 5103 break; 5104 case com.android.internal.R.styleable.View_id: 5105 mID = a.getResourceId(attr, NO_ID); 5106 break; 5107 case com.android.internal.R.styleable.View_tag: 5108 mTag = a.getText(attr); 5109 break; 5110 case com.android.internal.R.styleable.View_fitsSystemWindows: 5111 if (a.getBoolean(attr, false)) { 5112 viewFlagValues |= FITS_SYSTEM_WINDOWS; 5113 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 5114 } 5115 break; 5116 case com.android.internal.R.styleable.View_focusable: 5117 viewFlagValues = (viewFlagValues & ~FOCUSABLE_MASK) | getFocusableAttribute(a); 5118 if ((viewFlagValues & FOCUSABLE_AUTO) == 0) { 5119 viewFlagMasks |= FOCUSABLE_MASK; 5120 } 5121 break; 5122 case com.android.internal.R.styleable.View_focusableInTouchMode: 5123 if (a.getBoolean(attr, false)) { 5124 // unset auto focus since focusableInTouchMode implies explicit focusable 5125 viewFlagValues &= ~FOCUSABLE_AUTO; 5126 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 5127 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 5128 } 5129 break; 5130 case com.android.internal.R.styleable.View_clickable: 5131 if (a.getBoolean(attr, false)) { 5132 viewFlagValues |= CLICKABLE; 5133 viewFlagMasks |= CLICKABLE; 5134 } 5135 break; 5136 case com.android.internal.R.styleable.View_longClickable: 5137 if (a.getBoolean(attr, false)) { 5138 viewFlagValues |= LONG_CLICKABLE; 5139 viewFlagMasks |= LONG_CLICKABLE; 5140 } 5141 break; 5142 case com.android.internal.R.styleable.View_contextClickable: 5143 if (a.getBoolean(attr, false)) { 5144 viewFlagValues |= CONTEXT_CLICKABLE; 5145 viewFlagMasks |= CONTEXT_CLICKABLE; 5146 } 5147 break; 5148 case com.android.internal.R.styleable.View_saveEnabled: 5149 if (!a.getBoolean(attr, true)) { 5150 viewFlagValues |= SAVE_DISABLED; 5151 viewFlagMasks |= SAVE_DISABLED_MASK; 5152 } 5153 break; 5154 case com.android.internal.R.styleable.View_duplicateParentState: 5155 if (a.getBoolean(attr, false)) { 5156 viewFlagValues |= DUPLICATE_PARENT_STATE; 5157 viewFlagMasks |= DUPLICATE_PARENT_STATE; 5158 } 5159 break; 5160 case com.android.internal.R.styleable.View_visibility: 5161 final int visibility = a.getInt(attr, 0); 5162 if (visibility != 0) { 5163 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 5164 viewFlagMasks |= VISIBILITY_MASK; 5165 } 5166 break; 5167 case com.android.internal.R.styleable.View_layoutDirection: 5168 // Clear any layout direction flags (included resolved bits) already set 5169 mPrivateFlags2 &= 5170 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 5171 // Set the layout direction flags depending on the value of the attribute 5172 final int layoutDirection = a.getInt(attr, -1); 5173 final int value = (layoutDirection != -1) ? 5174 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 5175 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 5176 break; 5177 case com.android.internal.R.styleable.View_drawingCacheQuality: 5178 final int cacheQuality = a.getInt(attr, 0); 5179 if (cacheQuality != 0) { 5180 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 5181 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 5182 } 5183 break; 5184 case com.android.internal.R.styleable.View_contentDescription: 5185 setContentDescription(a.getString(attr)); 5186 break; 5187 case com.android.internal.R.styleable.View_accessibilityTraversalBefore: 5188 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); 5189 break; 5190 case com.android.internal.R.styleable.View_accessibilityTraversalAfter: 5191 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); 5192 break; 5193 case com.android.internal.R.styleable.View_labelFor: 5194 setLabelFor(a.getResourceId(attr, NO_ID)); 5195 break; 5196 case com.android.internal.R.styleable.View_soundEffectsEnabled: 5197 if (!a.getBoolean(attr, true)) { 5198 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 5199 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 5200 } 5201 break; 5202 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 5203 if (!a.getBoolean(attr, true)) { 5204 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 5205 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 5206 } 5207 break; 5208 case R.styleable.View_scrollbars: 5209 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 5210 if (scrollbars != SCROLLBARS_NONE) { 5211 viewFlagValues |= scrollbars; 5212 viewFlagMasks |= SCROLLBARS_MASK; 5213 initializeScrollbars = true; 5214 } 5215 break; 5216 //noinspection deprecation 5217 case R.styleable.View_fadingEdge: 5218 if (targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 5219 // Ignore the attribute starting with ICS 5220 break; 5221 } 5222 // With builds < ICS, fall through and apply fading edges 5223 case R.styleable.View_requiresFadingEdge: 5224 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 5225 if (fadingEdge != FADING_EDGE_NONE) { 5226 viewFlagValues |= fadingEdge; 5227 viewFlagMasks |= FADING_EDGE_MASK; 5228 initializeFadingEdgeInternal(a); 5229 } 5230 break; 5231 case R.styleable.View_scrollbarStyle: 5232 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 5233 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 5234 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 5235 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 5236 } 5237 break; 5238 case R.styleable.View_isScrollContainer: 5239 setScrollContainer = true; 5240 if (a.getBoolean(attr, false)) { 5241 setScrollContainer(true); 5242 } 5243 break; 5244 case com.android.internal.R.styleable.View_keepScreenOn: 5245 if (a.getBoolean(attr, false)) { 5246 viewFlagValues |= KEEP_SCREEN_ON; 5247 viewFlagMasks |= KEEP_SCREEN_ON; 5248 } 5249 break; 5250 case R.styleable.View_filterTouchesWhenObscured: 5251 if (a.getBoolean(attr, false)) { 5252 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 5253 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 5254 } 5255 break; 5256 case R.styleable.View_nextFocusLeft: 5257 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 5258 break; 5259 case R.styleable.View_nextFocusRight: 5260 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 5261 break; 5262 case R.styleable.View_nextFocusUp: 5263 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 5264 break; 5265 case R.styleable.View_nextFocusDown: 5266 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 5267 break; 5268 case R.styleable.View_nextFocusForward: 5269 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 5270 break; 5271 case R.styleable.View_nextClusterForward: 5272 mNextClusterForwardId = a.getResourceId(attr, View.NO_ID); 5273 break; 5274 case R.styleable.View_minWidth: 5275 mMinWidth = a.getDimensionPixelSize(attr, 0); 5276 break; 5277 case R.styleable.View_minHeight: 5278 mMinHeight = a.getDimensionPixelSize(attr, 0); 5279 break; 5280 case R.styleable.View_onClick: 5281 if (context.isRestricted()) { 5282 throw new IllegalStateException("The android:onClick attribute cannot " 5283 + "be used within a restricted context"); 5284 } 5285 5286 final String handlerName = a.getString(attr); 5287 if (handlerName != null) { 5288 setOnClickListener(new DeclaredOnClickListener(this, handlerName)); 5289 } 5290 break; 5291 case R.styleable.View_overScrollMode: 5292 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 5293 break; 5294 case R.styleable.View_verticalScrollbarPosition: 5295 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 5296 break; 5297 case R.styleable.View_layerType: 5298 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 5299 break; 5300 case R.styleable.View_textDirection: 5301 // Clear any text direction flag already set 5302 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 5303 // Set the text direction flags depending on the value of the attribute 5304 final int textDirection = a.getInt(attr, -1); 5305 if (textDirection != -1) { 5306 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 5307 } 5308 break; 5309 case R.styleable.View_textAlignment: 5310 // Clear any text alignment flag already set 5311 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 5312 // Set the text alignment flag depending on the value of the attribute 5313 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 5314 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 5315 break; 5316 case R.styleable.View_importantForAccessibility: 5317 setImportantForAccessibility(a.getInt(attr, 5318 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 5319 break; 5320 case R.styleable.View_accessibilityLiveRegion: 5321 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 5322 break; 5323 case R.styleable.View_transitionName: 5324 setTransitionName(a.getString(attr)); 5325 break; 5326 case R.styleable.View_nestedScrollingEnabled: 5327 setNestedScrollingEnabled(a.getBoolean(attr, false)); 5328 break; 5329 case R.styleable.View_stateListAnimator: 5330 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, 5331 a.getResourceId(attr, 0))); 5332 break; 5333 case R.styleable.View_backgroundTint: 5334 // This will get applied later during setBackground(). 5335 if (mBackgroundTint == null) { 5336 mBackgroundTint = new TintInfo(); 5337 } 5338 mBackgroundTint.mTintList = a.getColorStateList( 5339 R.styleable.View_backgroundTint); 5340 mBackgroundTint.mHasTintList = true; 5341 break; 5342 case R.styleable.View_backgroundTintMode: 5343 // This will get applied later during setBackground(). 5344 if (mBackgroundTint == null) { 5345 mBackgroundTint = new TintInfo(); 5346 } 5347 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( 5348 R.styleable.View_backgroundTintMode, -1), null); 5349 mBackgroundTint.mHasTintMode = true; 5350 break; 5351 case R.styleable.View_outlineProvider: 5352 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider, 5353 PROVIDER_BACKGROUND)); 5354 break; 5355 case R.styleable.View_foreground: 5356 if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { 5357 setForeground(a.getDrawable(attr)); 5358 } 5359 break; 5360 case R.styleable.View_foregroundGravity: 5361 if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { 5362 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY)); 5363 } 5364 break; 5365 case R.styleable.View_foregroundTintMode: 5366 if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { 5367 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); 5368 } 5369 break; 5370 case R.styleable.View_foregroundTint: 5371 if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { 5372 setForegroundTintList(a.getColorStateList(attr)); 5373 } 5374 break; 5375 case R.styleable.View_foregroundInsidePadding: 5376 if (targetSdkVersion >= Build.VERSION_CODES.M || this instanceof FrameLayout) { 5377 if (mForegroundInfo == null) { 5378 mForegroundInfo = new ForegroundInfo(); 5379 } 5380 mForegroundInfo.mInsidePadding = a.getBoolean(attr, 5381 mForegroundInfo.mInsidePadding); 5382 } 5383 break; 5384 case R.styleable.View_scrollIndicators: 5385 final int scrollIndicators = 5386 (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT) 5387 & SCROLL_INDICATORS_PFLAG3_MASK; 5388 if (scrollIndicators != 0) { 5389 mPrivateFlags3 |= scrollIndicators; 5390 initializeScrollIndicators = true; 5391 } 5392 break; 5393 case R.styleable.View_pointerIcon: 5394 final int resourceId = a.getResourceId(attr, 0); 5395 if (resourceId != 0) { 5396 setPointerIcon(PointerIcon.load( 5397 context.getResources(), resourceId)); 5398 } else { 5399 final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED); 5400 if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) { 5401 setPointerIcon(PointerIcon.getSystemIcon(context, pointerType)); 5402 } 5403 } 5404 break; 5405 case R.styleable.View_forceHasOverlappingRendering: 5406 if (a.peekValue(attr) != null) { 5407 forceHasOverlappingRendering(a.getBoolean(attr, true)); 5408 } 5409 break; 5410 case R.styleable.View_tooltipText: 5411 setTooltipText(a.getText(attr)); 5412 break; 5413 case R.styleable.View_keyboardNavigationCluster: 5414 if (a.peekValue(attr) != null) { 5415 setKeyboardNavigationCluster(a.getBoolean(attr, true)); 5416 } 5417 break; 5418 case R.styleable.View_focusedByDefault: 5419 if (a.peekValue(attr) != null) { 5420 setFocusedByDefault(a.getBoolean(attr, true)); 5421 } 5422 break; 5423 case R.styleable.View_autofillHints: 5424 if (a.peekValue(attr) != null) { 5425 CharSequence[] rawHints = null; 5426 String rawString = null; 5427 5428 if (a.getType(attr) == TypedValue.TYPE_REFERENCE) { 5429 int resId = a.getResourceId(attr, 0); 5430 5431 try { 5432 rawHints = a.getTextArray(attr); 5433 } catch (Resources.NotFoundException e) { 5434 rawString = getResources().getString(resId); 5435 } 5436 } else { 5437 rawString = a.getString(attr); 5438 } 5439 5440 if (rawHints == null) { 5441 if (rawString == null) { 5442 throw new IllegalArgumentException( 5443 "Could not resolve autofillHints"); 5444 } else { 5445 rawHints = rawString.split(","); 5446 } 5447 } 5448 5449 String[] hints = new String[rawHints.length]; 5450 5451 int numHints = rawHints.length; 5452 for (int rawHintNum = 0; rawHintNum < numHints; rawHintNum++) { 5453 hints[rawHintNum] = rawHints[rawHintNum].toString().trim(); 5454 } 5455 setAutofillHints(hints); 5456 } 5457 break; 5458 case R.styleable.View_importantForAutofill: 5459 if (a.peekValue(attr) != null) { 5460 setImportantForAutofill(a.getInt(attr, IMPORTANT_FOR_AUTOFILL_AUTO)); 5461 } 5462 break; 5463 case R.styleable.View_defaultFocusHighlightEnabled: 5464 if (a.peekValue(attr) != null) { 5465 setDefaultFocusHighlightEnabled(a.getBoolean(attr, true)); 5466 } 5467 break; 5468 case R.styleable.View_screenReaderFocusable: 5469 if (a.peekValue(attr) != null) { 5470 setScreenReaderFocusable(a.getBoolean(attr, false)); 5471 } 5472 break; 5473 case R.styleable.View_accessibilityPaneTitle: 5474 if (a.peekValue(attr) != null) { 5475 setAccessibilityPaneTitle(a.getString(attr)); 5476 } 5477 break; 5478 case R.styleable.View_outlineSpotShadowColor: 5479 setOutlineSpotShadowColor(a.getColor(attr, Color.BLACK)); 5480 break; 5481 case R.styleable.View_outlineAmbientShadowColor: 5482 setOutlineAmbientShadowColor(a.getColor(attr, Color.BLACK)); 5483 break; 5484 case com.android.internal.R.styleable.View_accessibilityHeading: 5485 setAccessibilityHeading(a.getBoolean(attr, false)); 5486 } 5487 } 5488 5489 setOverScrollMode(overScrollMode); 5490 5491 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 5492 // the resolved layout direction). Those cached values will be used later during padding 5493 // resolution. 5494 mUserPaddingStart = startPadding; 5495 mUserPaddingEnd = endPadding; 5496 5497 if (background != null) { 5498 setBackground(background); 5499 } 5500 5501 // setBackground above will record that padding is currently provided by the background. 5502 // If we have padding specified via xml, record that here instead and use it. 5503 mLeftPaddingDefined = leftPaddingDefined; 5504 mRightPaddingDefined = rightPaddingDefined; 5505 5506 if (padding >= 0) { 5507 leftPadding = padding; 5508 topPadding = padding; 5509 rightPadding = padding; 5510 bottomPadding = padding; 5511 mUserPaddingLeftInitial = padding; 5512 mUserPaddingRightInitial = padding; 5513 } else { 5514 if (paddingHorizontal >= 0) { 5515 leftPadding = paddingHorizontal; 5516 rightPadding = paddingHorizontal; 5517 mUserPaddingLeftInitial = paddingHorizontal; 5518 mUserPaddingRightInitial = paddingHorizontal; 5519 } 5520 if (paddingVertical >= 0) { 5521 topPadding = paddingVertical; 5522 bottomPadding = paddingVertical; 5523 } 5524 } 5525 5526 if (isRtlCompatibilityMode()) { 5527 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 5528 // left / right padding are used if defined (meaning here nothing to do). If they are not 5529 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 5530 // start / end and resolve them as left / right (layout direction is not taken into account). 5531 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 5532 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 5533 // defined. 5534 if (!mLeftPaddingDefined && startPaddingDefined) { 5535 leftPadding = startPadding; 5536 } 5537 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 5538 if (!mRightPaddingDefined && endPaddingDefined) { 5539 rightPadding = endPadding; 5540 } 5541 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 5542 } else { 5543 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 5544 // values defined. Otherwise, left /right values are used. 5545 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 5546 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 5547 // defined. 5548 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 5549 5550 if (mLeftPaddingDefined && !hasRelativePadding) { 5551 mUserPaddingLeftInitial = leftPadding; 5552 } 5553 if (mRightPaddingDefined && !hasRelativePadding) { 5554 mUserPaddingRightInitial = rightPadding; 5555 } 5556 } 5557 5558 internalSetPadding( 5559 mUserPaddingLeftInitial, 5560 topPadding >= 0 ? topPadding : mPaddingTop, 5561 mUserPaddingRightInitial, 5562 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 5563 5564 if (viewFlagMasks != 0) { 5565 setFlags(viewFlagValues, viewFlagMasks); 5566 } 5567 5568 if (initializeScrollbars) { 5569 initializeScrollbarsInternal(a); 5570 } 5571 5572 if (initializeScrollIndicators) { 5573 initializeScrollIndicatorsInternal(); 5574 } 5575 5576 a.recycle(); 5577 5578 // Needs to be called after mViewFlags is set 5579 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 5580 recomputePadding(); 5581 } 5582 5583 if (x != 0 || y != 0) { 5584 scrollTo(x, y); 5585 } 5586 5587 if (transformSet) { 5588 setTranslationX(tx); 5589 setTranslationY(ty); 5590 setTranslationZ(tz); 5591 setElevation(elevation); 5592 setRotation(rotation); 5593 setRotationX(rotationX); 5594 setRotationY(rotationY); 5595 setScaleX(sx); 5596 setScaleY(sy); 5597 } 5598 5599 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 5600 setScrollContainer(true); 5601 } 5602 5603 computeOpaqueFlags(); 5604 } 5605 5606 /** 5607 * An implementation of OnClickListener that attempts to lazily load a 5608 * named click handling method from a parent or ancestor context. 5609 */ 5610 private static class DeclaredOnClickListener implements OnClickListener { 5611 private final View mHostView; 5612 private final String mMethodName; 5613 5614 private Method mResolvedMethod; 5615 private Context mResolvedContext; 5616 5617 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { 5618 mHostView = hostView; 5619 mMethodName = methodName; 5620 } 5621 5622 @Override 5623 public void onClick(@NonNull View v) { 5624 if (mResolvedMethod == null) { 5625 resolveMethod(mHostView.getContext(), mMethodName); 5626 } 5627 5628 try { 5629 mResolvedMethod.invoke(mResolvedContext, v); 5630 } catch (IllegalAccessException e) { 5631 throw new IllegalStateException( 5632 "Could not execute non-public method for android:onClick", e); 5633 } catch (InvocationTargetException e) { 5634 throw new IllegalStateException( 5635 "Could not execute method for android:onClick", e); 5636 } 5637 } 5638 5639 @NonNull 5640 private void resolveMethod(@Nullable Context context, @NonNull String name) { 5641 while (context != null) { 5642 try { 5643 if (!context.isRestricted()) { 5644 final Method method = context.getClass().getMethod(mMethodName, View.class); 5645 if (method != null) { 5646 mResolvedMethod = method; 5647 mResolvedContext = context; 5648 return; 5649 } 5650 } 5651 } catch (NoSuchMethodException e) { 5652 // Failed to find method, keep searching up the hierarchy. 5653 } 5654 5655 if (context instanceof ContextWrapper) { 5656 context = ((ContextWrapper) context).getBaseContext(); 5657 } else { 5658 // Can't search up the hierarchy, null out and fail. 5659 context = null; 5660 } 5661 } 5662 5663 final int id = mHostView.getId(); 5664 final String idText = id == NO_ID ? "" : " with id '" 5665 + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; 5666 throw new IllegalStateException("Could not find method " + mMethodName 5667 + "(View) in a parent or ancestor Context for android:onClick " 5668 + "attribute defined on view " + mHostView.getClass() + idText); 5669 } 5670 } 5671 5672 /** 5673 * Non-public constructor for use in testing 5674 */ 5675 View() { 5676 mResources = null; 5677 mRenderNode = RenderNode.create(getClass().getName(), this); 5678 } 5679 5680 final boolean debugDraw() { 5681 return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout; 5682 } 5683 5684 private static SparseArray<String> getAttributeMap() { 5685 if (mAttributeMap == null) { 5686 mAttributeMap = new SparseArray<>(); 5687 } 5688 return mAttributeMap; 5689 } 5690 5691 private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { 5692 final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); 5693 final int indexCount = t.getIndexCount(); 5694 final String[] attributes = new String[(attrsCount + indexCount) * 2]; 5695 5696 int i = 0; 5697 5698 // Store raw XML attributes. 5699 for (int j = 0; j < attrsCount; ++j) { 5700 attributes[i] = attrs.getAttributeName(j); 5701 attributes[i + 1] = attrs.getAttributeValue(j); 5702 i += 2; 5703 } 5704 5705 // Store resolved styleable attributes. 5706 final Resources res = t.getResources(); 5707 final SparseArray<String> attributeMap = getAttributeMap(); 5708 for (int j = 0; j < indexCount; ++j) { 5709 final int index = t.getIndex(j); 5710 if (!t.hasValueOrEmpty(index)) { 5711 // Value is undefined. Skip it. 5712 continue; 5713 } 5714 5715 final int resourceId = t.getResourceId(index, 0); 5716 if (resourceId == 0) { 5717 // Value is not a reference. Skip it. 5718 continue; 5719 } 5720 5721 String resourceName = attributeMap.get(resourceId); 5722 if (resourceName == null) { 5723 try { 5724 resourceName = res.getResourceName(resourceId); 5725 } catch (Resources.NotFoundException e) { 5726 resourceName = "0x" + Integer.toHexString(resourceId); 5727 } 5728 attributeMap.put(resourceId, resourceName); 5729 } 5730 5731 attributes[i] = resourceName; 5732 attributes[i + 1] = t.getString(index); 5733 i += 2; 5734 } 5735 5736 // Trim to fit contents. 5737 final String[] trimmed = new String[i]; 5738 System.arraycopy(attributes, 0, trimmed, 0, i); 5739 mAttributes = trimmed; 5740 } 5741 5742 public String toString() { 5743 StringBuilder out = new StringBuilder(128); 5744 out.append(getClass().getName()); 5745 out.append('{'); 5746 out.append(Integer.toHexString(System.identityHashCode(this))); 5747 out.append(' '); 5748 switch (mViewFlags&VISIBILITY_MASK) { 5749 case VISIBLE: out.append('V'); break; 5750 case INVISIBLE: out.append('I'); break; 5751 case GONE: out.append('G'); break; 5752 default: out.append('.'); break; 5753 } 5754 out.append((mViewFlags & FOCUSABLE) == FOCUSABLE ? 'F' : '.'); 5755 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 5756 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 5757 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 5758 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 5759 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 5760 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 5761 out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.'); 5762 out.append(' '); 5763 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 5764 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 5765 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 5766 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 5767 out.append('p'); 5768 } else { 5769 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 5770 } 5771 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 5772 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 5773 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 5774 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 5775 out.append(' '); 5776 out.append(mLeft); 5777 out.append(','); 5778 out.append(mTop); 5779 out.append('-'); 5780 out.append(mRight); 5781 out.append(','); 5782 out.append(mBottom); 5783 final int id = getId(); 5784 if (id != NO_ID) { 5785 out.append(" #"); 5786 out.append(Integer.toHexString(id)); 5787 final Resources r = mResources; 5788 if (id > 0 && Resources.resourceHasPackage(id) && r != null) { 5789 try { 5790 String pkgname; 5791 switch (id&0xff000000) { 5792 case 0x7f000000: 5793 pkgname="app"; 5794 break; 5795 case 0x01000000: 5796 pkgname="android"; 5797 break; 5798 default: 5799 pkgname = r.getResourcePackageName(id); 5800 break; 5801 } 5802 String typename = r.getResourceTypeName(id); 5803 String entryname = r.getResourceEntryName(id); 5804 out.append(" "); 5805 out.append(pkgname); 5806 out.append(":"); 5807 out.append(typename); 5808 out.append("/"); 5809 out.append(entryname); 5810 } catch (Resources.NotFoundException e) { 5811 } 5812 } 5813 } 5814 out.append("}"); 5815 return out.toString(); 5816 } 5817 5818 /** 5819 * <p> 5820 * Initializes the fading edges from a given set of styled attributes. This 5821 * method should be called by subclasses that need fading edges and when an 5822 * instance of these subclasses is created programmatically rather than 5823 * being inflated from XML. This method is automatically called when the XML 5824 * is inflated. 5825 * </p> 5826 * 5827 * @param a the styled attributes set to initialize the fading edges from 5828 * 5829 * @removed 5830 */ 5831 protected void initializeFadingEdge(TypedArray a) { 5832 // This method probably shouldn't have been included in the SDK to begin with. 5833 // It relies on 'a' having been initialized using an attribute filter array that is 5834 // not publicly available to the SDK. The old method has been renamed 5835 // to initializeFadingEdgeInternal and hidden for framework use only; 5836 // this one initializes using defaults to make it safe to call for apps. 5837 5838 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 5839 5840 initializeFadingEdgeInternal(arr); 5841 5842 arr.recycle(); 5843 } 5844 5845 /** 5846 * <p> 5847 * Initializes the fading edges from a given set of styled attributes. This 5848 * method should be called by subclasses that need fading edges and when an 5849 * instance of these subclasses is created programmatically rather than 5850 * being inflated from XML. This method is automatically called when the XML 5851 * is inflated. 5852 * </p> 5853 * 5854 * @param a the styled attributes set to initialize the fading edges from 5855 * @hide This is the real method; the public one is shimmed to be safe to call from apps. 5856 */ 5857 protected void initializeFadingEdgeInternal(TypedArray a) { 5858 initScrollCache(); 5859 5860 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 5861 R.styleable.View_fadingEdgeLength, 5862 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 5863 } 5864 5865 /** 5866 * Returns the size of the vertical faded edges used to indicate that more 5867 * content in this view is visible. 5868 * 5869 * @return The size in pixels of the vertical faded edge or 0 if vertical 5870 * faded edges are not enabled for this view. 5871 * @attr ref android.R.styleable#View_fadingEdgeLength 5872 */ 5873 public int getVerticalFadingEdgeLength() { 5874 if (isVerticalFadingEdgeEnabled()) { 5875 ScrollabilityCache cache = mScrollCache; 5876 if (cache != null) { 5877 return cache.fadingEdgeLength; 5878 } 5879 } 5880 return 0; 5881 } 5882 5883 /** 5884 * Set the size of the faded edge used to indicate that more content in this 5885 * view is available. Will not change whether the fading edge is enabled; use 5886 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 5887 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 5888 * for the vertical or horizontal fading edges. 5889 * 5890 * @param length The size in pixels of the faded edge used to indicate that more 5891 * content in this view is visible. 5892 */ 5893 public void setFadingEdgeLength(int length) { 5894 initScrollCache(); 5895 mScrollCache.fadingEdgeLength = length; 5896 } 5897 5898 /** 5899 * Returns the size of the horizontal faded edges used to indicate that more 5900 * content in this view is visible. 5901 * 5902 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 5903 * faded edges are not enabled for this view. 5904 * @attr ref android.R.styleable#View_fadingEdgeLength 5905 */ 5906 public int getHorizontalFadingEdgeLength() { 5907 if (isHorizontalFadingEdgeEnabled()) { 5908 ScrollabilityCache cache = mScrollCache; 5909 if (cache != null) { 5910 return cache.fadingEdgeLength; 5911 } 5912 } 5913 return 0; 5914 } 5915 5916 /** 5917 * Returns the width of the vertical scrollbar. 5918 * 5919 * @return The width in pixels of the vertical scrollbar or 0 if there 5920 * is no vertical scrollbar. 5921 */ 5922 public int getVerticalScrollbarWidth() { 5923 ScrollabilityCache cache = mScrollCache; 5924 if (cache != null) { 5925 ScrollBarDrawable scrollBar = cache.scrollBar; 5926 if (scrollBar != null) { 5927 int size = scrollBar.getSize(true); 5928 if (size <= 0) { 5929 size = cache.scrollBarSize; 5930 } 5931 return size; 5932 } 5933 return 0; 5934 } 5935 return 0; 5936 } 5937 5938 /** 5939 * Returns the height of the horizontal scrollbar. 5940 * 5941 * @return The height in pixels of the horizontal scrollbar or 0 if 5942 * there is no horizontal scrollbar. 5943 */ 5944 protected int getHorizontalScrollbarHeight() { 5945 ScrollabilityCache cache = mScrollCache; 5946 if (cache != null) { 5947 ScrollBarDrawable scrollBar = cache.scrollBar; 5948 if (scrollBar != null) { 5949 int size = scrollBar.getSize(false); 5950 if (size <= 0) { 5951 size = cache.scrollBarSize; 5952 } 5953 return size; 5954 } 5955 return 0; 5956 } 5957 return 0; 5958 } 5959 5960 /** 5961 * <p> 5962 * Initializes the scrollbars from a given set of styled attributes. This 5963 * method should be called by subclasses that need scrollbars and when an 5964 * instance of these subclasses is created programmatically rather than 5965 * being inflated from XML. This method is automatically called when the XML 5966 * is inflated. 5967 * </p> 5968 * 5969 * @param a the styled attributes set to initialize the scrollbars from 5970 * 5971 * @removed 5972 */ 5973 protected void initializeScrollbars(TypedArray a) { 5974 // It's not safe to use this method from apps. The parameter 'a' must have been obtained 5975 // using the View filter array which is not available to the SDK. As such, internal 5976 // framework usage now uses initializeScrollbarsInternal and we grab a default 5977 // TypedArray with the right filter instead here. 5978 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 5979 5980 initializeScrollbarsInternal(arr); 5981 5982 // We ignored the method parameter. Recycle the one we actually did use. 5983 arr.recycle(); 5984 } 5985 5986 /** 5987 * <p> 5988 * Initializes the scrollbars from a given set of styled attributes. This 5989 * method should be called by subclasses that need scrollbars and when an 5990 * instance of these subclasses is created programmatically rather than 5991 * being inflated from XML. This method is automatically called when the XML 5992 * is inflated. 5993 * </p> 5994 * 5995 * @param a the styled attributes set to initialize the scrollbars from 5996 * @hide 5997 */ 5998 protected void initializeScrollbarsInternal(TypedArray a) { 5999 initScrollCache(); 6000 6001 final ScrollabilityCache scrollabilityCache = mScrollCache; 6002 6003 if (scrollabilityCache.scrollBar == null) { 6004 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 6005 scrollabilityCache.scrollBar.setState(getDrawableState()); 6006 scrollabilityCache.scrollBar.setCallback(this); 6007 } 6008 6009 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 6010 6011 if (!fadeScrollbars) { 6012 scrollabilityCache.state = ScrollabilityCache.ON; 6013 } 6014 scrollabilityCache.fadeScrollBars = fadeScrollbars; 6015 6016 6017 scrollabilityCache.scrollBarFadeDuration = a.getInt( 6018 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 6019 .getScrollBarFadeDuration()); 6020 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 6021 R.styleable.View_scrollbarDefaultDelayBeforeFade, 6022 ViewConfiguration.getScrollDefaultDelay()); 6023 6024 6025 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 6026 com.android.internal.R.styleable.View_scrollbarSize, 6027 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 6028 6029 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 6030 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 6031 6032 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 6033 if (thumb != null) { 6034 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 6035 } 6036 6037 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 6038 false); 6039 if (alwaysDraw) { 6040 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 6041 } 6042 6043 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 6044 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 6045 6046 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 6047 if (thumb != null) { 6048 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 6049 } 6050 6051 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 6052 false); 6053 if (alwaysDraw) { 6054 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 6055 } 6056 6057 // Apply layout direction to the new Drawables if needed 6058 final int layoutDirection = getLayoutDirection(); 6059 if (track != null) { 6060 track.setLayoutDirection(layoutDirection); 6061 } 6062 if (thumb != null) { 6063 thumb.setLayoutDirection(layoutDirection); 6064 } 6065 6066 // Re-apply user/background padding so that scrollbar(s) get added 6067 resolvePadding(); 6068 } 6069 6070 private void initializeScrollIndicatorsInternal() { 6071 // Some day maybe we'll break this into top/left/start/etc. and let the 6072 // client control it. Until then, you can have any scroll indicator you 6073 // want as long as it's a 1dp foreground-colored rectangle. 6074 if (mScrollIndicatorDrawable == null) { 6075 mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); 6076 } 6077 } 6078 6079 /** 6080 * <p> 6081 * Initalizes the scrollability cache if necessary. 6082 * </p> 6083 */ 6084 private void initScrollCache() { 6085 if (mScrollCache == null) { 6086 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 6087 } 6088 } 6089 6090 private ScrollabilityCache getScrollCache() { 6091 initScrollCache(); 6092 return mScrollCache; 6093 } 6094 6095 /** 6096 * Set the position of the vertical scroll bar. Should be one of 6097 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 6098 * {@link #SCROLLBAR_POSITION_RIGHT}. 6099 * 6100 * @param position Where the vertical scroll bar should be positioned. 6101 */ 6102 public void setVerticalScrollbarPosition(int position) { 6103 if (mVerticalScrollbarPosition != position) { 6104 mVerticalScrollbarPosition = position; 6105 computeOpaqueFlags(); 6106 resolvePadding(); 6107 } 6108 } 6109 6110 /** 6111 * @return The position where the vertical scroll bar will show, if applicable. 6112 * @see #setVerticalScrollbarPosition(int) 6113 */ 6114 public int getVerticalScrollbarPosition() { 6115 return mVerticalScrollbarPosition; 6116 } 6117 6118 boolean isOnScrollbar(float x, float y) { 6119 if (mScrollCache == null) { 6120 return false; 6121 } 6122 x += getScrollX(); 6123 y += getScrollY(); 6124 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 6125 final Rect touchBounds = mScrollCache.mScrollBarTouchBounds; 6126 getVerticalScrollBarBounds(null, touchBounds); 6127 if (touchBounds.contains((int) x, (int) y)) { 6128 return true; 6129 } 6130 } 6131 if (isHorizontalScrollBarEnabled()) { 6132 final Rect touchBounds = mScrollCache.mScrollBarTouchBounds; 6133 getHorizontalScrollBarBounds(null, touchBounds); 6134 if (touchBounds.contains((int) x, (int) y)) { 6135 return true; 6136 } 6137 } 6138 return false; 6139 } 6140 6141 boolean isOnScrollbarThumb(float x, float y) { 6142 return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y); 6143 } 6144 6145 private boolean isOnVerticalScrollbarThumb(float x, float y) { 6146 if (mScrollCache == null) { 6147 return false; 6148 } 6149 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 6150 x += getScrollX(); 6151 y += getScrollY(); 6152 final Rect bounds = mScrollCache.mScrollBarBounds; 6153 final Rect touchBounds = mScrollCache.mScrollBarTouchBounds; 6154 getVerticalScrollBarBounds(bounds, touchBounds); 6155 final int range = computeVerticalScrollRange(); 6156 final int offset = computeVerticalScrollOffset(); 6157 final int extent = computeVerticalScrollExtent(); 6158 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(), 6159 extent, range); 6160 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength, 6161 extent, range, offset); 6162 final int thumbTop = bounds.top + thumbOffset; 6163 final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2; 6164 if (x >= touchBounds.left && x <= touchBounds.right 6165 && y >= thumbTop - adjust && y <= thumbTop + thumbLength + adjust) { 6166 return true; 6167 } 6168 } 6169 return false; 6170 } 6171 6172 private boolean isOnHorizontalScrollbarThumb(float x, float y) { 6173 if (mScrollCache == null) { 6174 return false; 6175 } 6176 if (isHorizontalScrollBarEnabled()) { 6177 x += getScrollX(); 6178 y += getScrollY(); 6179 final Rect bounds = mScrollCache.mScrollBarBounds; 6180 final Rect touchBounds = mScrollCache.mScrollBarTouchBounds; 6181 getHorizontalScrollBarBounds(bounds, touchBounds); 6182 final int range = computeHorizontalScrollRange(); 6183 final int offset = computeHorizontalScrollOffset(); 6184 final int extent = computeHorizontalScrollExtent(); 6185 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(), 6186 extent, range); 6187 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength, 6188 extent, range, offset); 6189 final int thumbLeft = bounds.left + thumbOffset; 6190 final int adjust = Math.max(mScrollCache.scrollBarMinTouchTarget - thumbLength, 0) / 2; 6191 if (x >= thumbLeft - adjust && x <= thumbLeft + thumbLength + adjust 6192 && y >= touchBounds.top && y <= touchBounds.bottom) { 6193 return true; 6194 } 6195 } 6196 return false; 6197 } 6198 6199 boolean isDraggingScrollBar() { 6200 return mScrollCache != null 6201 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING; 6202 } 6203 6204 /** 6205 * Sets the state of all scroll indicators. 6206 * <p> 6207 * See {@link #setScrollIndicators(int, int)} for usage information. 6208 * 6209 * @param indicators a bitmask of indicators that should be enabled, or 6210 * {@code 0} to disable all indicators 6211 * @see #setScrollIndicators(int, int) 6212 * @see #getScrollIndicators() 6213 * @attr ref android.R.styleable#View_scrollIndicators 6214 */ 6215 public void setScrollIndicators(@ScrollIndicators int indicators) { 6216 setScrollIndicators(indicators, 6217 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT); 6218 } 6219 6220 /** 6221 * Sets the state of the scroll indicators specified by the mask. To change 6222 * all scroll indicators at once, see {@link #setScrollIndicators(int)}. 6223 * <p> 6224 * When a scroll indicator is enabled, it will be displayed if the view 6225 * can scroll in the direction of the indicator. 6226 * <p> 6227 * Multiple indicator types may be enabled or disabled by passing the 6228 * logical OR of the desired types. If multiple types are specified, they 6229 * will all be set to the same enabled state. 6230 * <p> 6231 * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators 6232 * 6233 * @param indicators the indicator direction, or the logical OR of multiple 6234 * indicator directions. One or more of: 6235 * <ul> 6236 * <li>{@link #SCROLL_INDICATOR_TOP}</li> 6237 * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> 6238 * <li>{@link #SCROLL_INDICATOR_LEFT}</li> 6239 * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> 6240 * <li>{@link #SCROLL_INDICATOR_START}</li> 6241 * <li>{@link #SCROLL_INDICATOR_END}</li> 6242 * </ul> 6243 * @see #setScrollIndicators(int) 6244 * @see #getScrollIndicators() 6245 * @attr ref android.R.styleable#View_scrollIndicators 6246 */ 6247 public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { 6248 // Shift and sanitize mask. 6249 mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 6250 mask &= SCROLL_INDICATORS_PFLAG3_MASK; 6251 6252 // Shift and mask indicators. 6253 indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 6254 indicators &= mask; 6255 6256 // Merge with non-masked flags. 6257 final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); 6258 6259 if (mPrivateFlags3 != updatedFlags) { 6260 mPrivateFlags3 = updatedFlags; 6261 6262 if (indicators != 0) { 6263 initializeScrollIndicatorsInternal(); 6264 } 6265 invalidate(); 6266 } 6267 } 6268 6269 /** 6270 * Returns a bitmask representing the enabled scroll indicators. 6271 * <p> 6272 * For example, if the top and left scroll indicators are enabled and all 6273 * other indicators are disabled, the return value will be 6274 * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. 6275 * <p> 6276 * To check whether the bottom scroll indicator is enabled, use the value 6277 * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. 6278 * 6279 * @return a bitmask representing the enabled scroll indicators 6280 */ 6281 @ScrollIndicators 6282 public int getScrollIndicators() { 6283 return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) 6284 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 6285 } 6286 6287 ListenerInfo getListenerInfo() { 6288 if (mListenerInfo != null) { 6289 return mListenerInfo; 6290 } 6291 mListenerInfo = new ListenerInfo(); 6292 return mListenerInfo; 6293 } 6294 6295 /** 6296 * Register a callback to be invoked when the scroll X or Y positions of 6297 * this view change. 6298 * <p> 6299 * <b>Note:</b> Some views handle scrolling independently from View and may 6300 * have their own separate listeners for scroll-type events. For example, 6301 * {@link android.widget.ListView ListView} allows clients to register an 6302 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 6303 * to listen for changes in list scroll position. 6304 * 6305 * @param l The listener to notify when the scroll X or Y position changes. 6306 * @see android.view.View#getScrollX() 6307 * @see android.view.View#getScrollY() 6308 */ 6309 public void setOnScrollChangeListener(OnScrollChangeListener l) { 6310 getListenerInfo().mOnScrollChangeListener = l; 6311 } 6312 6313 /** 6314 * Register a callback to be invoked when focus of this view changed. 6315 * 6316 * @param l The callback that will run. 6317 */ 6318 public void setOnFocusChangeListener(OnFocusChangeListener l) { 6319 getListenerInfo().mOnFocusChangeListener = l; 6320 } 6321 6322 /** 6323 * Add a listener that will be called when the bounds of the view change due to 6324 * layout processing. 6325 * 6326 * @param listener The listener that will be called when layout bounds change. 6327 */ 6328 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 6329 ListenerInfo li = getListenerInfo(); 6330 if (li.mOnLayoutChangeListeners == null) { 6331 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 6332 } 6333 if (!li.mOnLayoutChangeListeners.contains(listener)) { 6334 li.mOnLayoutChangeListeners.add(listener); 6335 } 6336 } 6337 6338 /** 6339 * Remove a listener for layout changes. 6340 * 6341 * @param listener The listener for layout bounds change. 6342 */ 6343 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 6344 ListenerInfo li = mListenerInfo; 6345 if (li == null || li.mOnLayoutChangeListeners == null) { 6346 return; 6347 } 6348 li.mOnLayoutChangeListeners.remove(listener); 6349 } 6350 6351 /** 6352 * Add a listener for attach state changes. 6353 * 6354 * This listener will be called whenever this view is attached or detached 6355 * from a window. Remove the listener using 6356 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 6357 * 6358 * @param listener Listener to attach 6359 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 6360 */ 6361 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 6362 ListenerInfo li = getListenerInfo(); 6363 if (li.mOnAttachStateChangeListeners == null) { 6364 li.mOnAttachStateChangeListeners 6365 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 6366 } 6367 li.mOnAttachStateChangeListeners.add(listener); 6368 } 6369 6370 /** 6371 * Remove a listener for attach state changes. The listener will receive no further 6372 * notification of window attach/detach events. 6373 * 6374 * @param listener Listener to remove 6375 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 6376 */ 6377 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 6378 ListenerInfo li = mListenerInfo; 6379 if (li == null || li.mOnAttachStateChangeListeners == null) { 6380 return; 6381 } 6382 li.mOnAttachStateChangeListeners.remove(listener); 6383 } 6384 6385 /** 6386 * Returns the focus-change callback registered for this view. 6387 * 6388 * @return The callback, or null if one is not registered. 6389 */ 6390 public OnFocusChangeListener getOnFocusChangeListener() { 6391 ListenerInfo li = mListenerInfo; 6392 return li != null ? li.mOnFocusChangeListener : null; 6393 } 6394 6395 /** 6396 * Register a callback to be invoked when this view is clicked. If this view is not 6397 * clickable, it becomes clickable. 6398 * 6399 * @param l The callback that will run 6400 * 6401 * @see #setClickable(boolean) 6402 */ 6403 public void setOnClickListener(@Nullable OnClickListener l) { 6404 if (!isClickable()) { 6405 setClickable(true); 6406 } 6407 getListenerInfo().mOnClickListener = l; 6408 } 6409 6410 /** 6411 * Return whether this view has an attached OnClickListener. Returns 6412 * true if there is a listener, false if there is none. 6413 */ 6414 public boolean hasOnClickListeners() { 6415 ListenerInfo li = mListenerInfo; 6416 return (li != null && li.mOnClickListener != null); 6417 } 6418 6419 /** 6420 * Register a callback to be invoked when this view is clicked and held. If this view is not 6421 * long clickable, it becomes long clickable. 6422 * 6423 * @param l The callback that will run 6424 * 6425 * @see #setLongClickable(boolean) 6426 */ 6427 public void setOnLongClickListener(@Nullable OnLongClickListener l) { 6428 if (!isLongClickable()) { 6429 setLongClickable(true); 6430 } 6431 getListenerInfo().mOnLongClickListener = l; 6432 } 6433 6434 /** 6435 * Register a callback to be invoked when this view is context clicked. If the view is not 6436 * context clickable, it becomes context clickable. 6437 * 6438 * @param l The callback that will run 6439 * @see #setContextClickable(boolean) 6440 */ 6441 public void setOnContextClickListener(@Nullable OnContextClickListener l) { 6442 if (!isContextClickable()) { 6443 setContextClickable(true); 6444 } 6445 getListenerInfo().mOnContextClickListener = l; 6446 } 6447 6448 /** 6449 * Register a callback to be invoked when the context menu for this view is 6450 * being built. If this view is not long clickable, it becomes long clickable. 6451 * 6452 * @param l The callback that will run 6453 * 6454 */ 6455 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 6456 if (!isLongClickable()) { 6457 setLongClickable(true); 6458 } 6459 getListenerInfo().mOnCreateContextMenuListener = l; 6460 } 6461 6462 /** 6463 * Set an observer to collect stats for each frame rendered for this view. 6464 * 6465 * @hide 6466 */ 6467 public void addFrameMetricsListener(Window window, 6468 Window.OnFrameMetricsAvailableListener listener, 6469 Handler handler) { 6470 if (mAttachInfo != null) { 6471 if (mAttachInfo.mThreadedRenderer != null) { 6472 if (mFrameMetricsObservers == null) { 6473 mFrameMetricsObservers = new ArrayList<>(); 6474 } 6475 6476 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 6477 handler.getLooper(), listener); 6478 mFrameMetricsObservers.add(fmo); 6479 mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo); 6480 } else { 6481 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 6482 } 6483 } else { 6484 if (mFrameMetricsObservers == null) { 6485 mFrameMetricsObservers = new ArrayList<>(); 6486 } 6487 6488 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 6489 handler.getLooper(), listener); 6490 mFrameMetricsObservers.add(fmo); 6491 } 6492 } 6493 6494 /** 6495 * Remove observer configured to collect frame stats for this view. 6496 * 6497 * @hide 6498 */ 6499 public void removeFrameMetricsListener( 6500 Window.OnFrameMetricsAvailableListener listener) { 6501 ThreadedRenderer renderer = getThreadedRenderer(); 6502 FrameMetricsObserver fmo = findFrameMetricsObserver(listener); 6503 if (fmo == null) { 6504 throw new IllegalArgumentException( 6505 "attempt to remove OnFrameMetricsAvailableListener that was never added"); 6506 } 6507 6508 if (mFrameMetricsObservers != null) { 6509 mFrameMetricsObservers.remove(fmo); 6510 if (renderer != null) { 6511 renderer.removeFrameMetricsObserver(fmo); 6512 } 6513 } 6514 } 6515 6516 private void registerPendingFrameMetricsObservers() { 6517 if (mFrameMetricsObservers != null) { 6518 ThreadedRenderer renderer = getThreadedRenderer(); 6519 if (renderer != null) { 6520 for (FrameMetricsObserver fmo : mFrameMetricsObservers) { 6521 renderer.addFrameMetricsObserver(fmo); 6522 } 6523 } else { 6524 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 6525 } 6526 } 6527 } 6528 6529 private FrameMetricsObserver findFrameMetricsObserver( 6530 Window.OnFrameMetricsAvailableListener listener) { 6531 for (int i = 0; i < mFrameMetricsObservers.size(); i++) { 6532 FrameMetricsObserver observer = mFrameMetricsObservers.get(i); 6533 if (observer.mListener == listener) { 6534 return observer; 6535 } 6536 } 6537 6538 return null; 6539 } 6540 6541 /** @hide */ 6542 public void setNotifyAutofillManagerOnClick(boolean notify) { 6543 if (notify) { 6544 mPrivateFlags |= PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK; 6545 } else { 6546 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK; 6547 } 6548 } 6549 6550 private void notifyAutofillManagerOnClick() { 6551 if ((mPrivateFlags & PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK) != 0) { 6552 try { 6553 getAutofillManager().notifyViewClicked(this); 6554 } finally { 6555 // Set it to already called so it's not called twice when called by 6556 // performClickInternal() 6557 mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK; 6558 } 6559 } 6560 } 6561 6562 /** 6563 * Entry point for {@link #performClick()} - other methods on View should call it instead of 6564 * {@code performClick()} directly to make sure the autofill manager is notified when 6565 * necessary (as subclasses could extend {@code performClick()} without calling the parent's 6566 * method). 6567 */ 6568 private boolean performClickInternal() { 6569 // Must notify autofill manager before performing the click actions to avoid scenarios where 6570 // the app has a click listener that changes the state of views the autofill service might 6571 // be interested on. 6572 notifyAutofillManagerOnClick(); 6573 6574 return performClick(); 6575 } 6576 6577 /** 6578 * Call this view's OnClickListener, if it is defined. Performs all normal 6579 * actions associated with clicking: reporting accessibility event, playing 6580 * a sound, etc. 6581 * 6582 * @return True there was an assigned OnClickListener that was called, false 6583 * otherwise is returned. 6584 */ 6585 // NOTE: other methods on View should not call this method directly, but performClickInternal() 6586 // instead, to guarantee that the autofill manager is notified when necessary (as subclasses 6587 // could extend this method without calling super.performClick()). 6588 public boolean performClick() { 6589 // We still need to call this method to handle the cases where performClick() was called 6590 // externally, instead of through performClickInternal() 6591 notifyAutofillManagerOnClick(); 6592 6593 final boolean result; 6594 final ListenerInfo li = mListenerInfo; 6595 if (li != null && li.mOnClickListener != null) { 6596 playSoundEffect(SoundEffectConstants.CLICK); 6597 li.mOnClickListener.onClick(this); 6598 result = true; 6599 } else { 6600 result = false; 6601 } 6602 6603 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 6604 6605 notifyEnterOrExitForAutoFillIfNeeded(true); 6606 6607 return result; 6608 } 6609 6610 /** 6611 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 6612 * this only calls the listener, and does not do any associated clicking 6613 * actions like reporting an accessibility event. 6614 * 6615 * @return True there was an assigned OnClickListener that was called, false 6616 * otherwise is returned. 6617 */ 6618 public boolean callOnClick() { 6619 ListenerInfo li = mListenerInfo; 6620 if (li != null && li.mOnClickListener != null) { 6621 li.mOnClickListener.onClick(this); 6622 return true; 6623 } 6624 return false; 6625 } 6626 6627 /** 6628 * Calls this view's OnLongClickListener, if it is defined. Invokes the 6629 * context menu if the OnLongClickListener did not consume the event. 6630 * 6631 * @return {@code true} if one of the above receivers consumed the event, 6632 * {@code false} otherwise 6633 */ 6634 public boolean performLongClick() { 6635 return performLongClickInternal(mLongClickX, mLongClickY); 6636 } 6637 6638 /** 6639 * Calls this view's OnLongClickListener, if it is defined. Invokes the 6640 * context menu if the OnLongClickListener did not consume the event, 6641 * anchoring it to an (x,y) coordinate. 6642 * 6643 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 6644 * to disable anchoring 6645 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 6646 * to disable anchoring 6647 * @return {@code true} if one of the above receivers consumed the event, 6648 * {@code false} otherwise 6649 */ 6650 public boolean performLongClick(float x, float y) { 6651 mLongClickX = x; 6652 mLongClickY = y; 6653 final boolean handled = performLongClick(); 6654 mLongClickX = Float.NaN; 6655 mLongClickY = Float.NaN; 6656 return handled; 6657 } 6658 6659 /** 6660 * Calls this view's OnLongClickListener, if it is defined. Invokes the 6661 * context menu if the OnLongClickListener did not consume the event, 6662 * optionally anchoring it to an (x,y) coordinate. 6663 * 6664 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 6665 * to disable anchoring 6666 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 6667 * to disable anchoring 6668 * @return {@code true} if one of the above receivers consumed the event, 6669 * {@code false} otherwise 6670 */ 6671 private boolean performLongClickInternal(float x, float y) { 6672 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 6673 6674 boolean handled = false; 6675 final ListenerInfo li = mListenerInfo; 6676 if (li != null && li.mOnLongClickListener != null) { 6677 handled = li.mOnLongClickListener.onLongClick(View.this); 6678 } 6679 if (!handled) { 6680 final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y); 6681 handled = isAnchored ? showContextMenu(x, y) : showContextMenu(); 6682 } 6683 if ((mViewFlags & TOOLTIP) == TOOLTIP) { 6684 if (!handled) { 6685 handled = showLongClickTooltip((int) x, (int) y); 6686 } 6687 } 6688 if (handled) { 6689 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 6690 } 6691 return handled; 6692 } 6693 6694 /** 6695 * Call this view's OnContextClickListener, if it is defined. 6696 * 6697 * @param x the x coordinate of the context click 6698 * @param y the y coordinate of the context click 6699 * @return True if there was an assigned OnContextClickListener that consumed the event, false 6700 * otherwise. 6701 */ 6702 public boolean performContextClick(float x, float y) { 6703 return performContextClick(); 6704 } 6705 6706 /** 6707 * Call this view's OnContextClickListener, if it is defined. 6708 * 6709 * @return True if there was an assigned OnContextClickListener that consumed the event, false 6710 * otherwise. 6711 */ 6712 public boolean performContextClick() { 6713 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED); 6714 6715 boolean handled = false; 6716 ListenerInfo li = mListenerInfo; 6717 if (li != null && li.mOnContextClickListener != null) { 6718 handled = li.mOnContextClickListener.onContextClick(View.this); 6719 } 6720 if (handled) { 6721 performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK); 6722 } 6723 return handled; 6724 } 6725 6726 /** 6727 * Performs button-related actions during a touch down event. 6728 * 6729 * @param event The event. 6730 * @return True if the down was consumed. 6731 * 6732 * @hide 6733 */ 6734 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 6735 if (event.isFromSource(InputDevice.SOURCE_MOUSE) && 6736 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 6737 showContextMenu(event.getX(), event.getY()); 6738 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 6739 return true; 6740 } 6741 return false; 6742 } 6743 6744 /** 6745 * Shows the context menu for this view. 6746 * 6747 * @return {@code true} if the context menu was shown, {@code false} 6748 * otherwise 6749 * @see #showContextMenu(float, float) 6750 */ 6751 public boolean showContextMenu() { 6752 return getParent().showContextMenuForChild(this); 6753 } 6754 6755 /** 6756 * Shows the context menu for this view anchored to the specified 6757 * view-relative coordinate. 6758 * 6759 * @param x the X coordinate in pixels relative to the view to which the 6760 * menu should be anchored, or {@link Float#NaN} to disable anchoring 6761 * @param y the Y coordinate in pixels relative to the view to which the 6762 * menu should be anchored, or {@link Float#NaN} to disable anchoring 6763 * @return {@code true} if the context menu was shown, {@code false} 6764 * otherwise 6765 */ 6766 public boolean showContextMenu(float x, float y) { 6767 return getParent().showContextMenuForChild(this, x, y); 6768 } 6769 6770 /** 6771 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}. 6772 * 6773 * @param callback Callback that will control the lifecycle of the action mode 6774 * @return The new action mode if it is started, null otherwise 6775 * 6776 * @see ActionMode 6777 * @see #startActionMode(android.view.ActionMode.Callback, int) 6778 */ 6779 public ActionMode startActionMode(ActionMode.Callback callback) { 6780 return startActionMode(callback, ActionMode.TYPE_PRIMARY); 6781 } 6782 6783 /** 6784 * Start an action mode with the given type. 6785 * 6786 * @param callback Callback that will control the lifecycle of the action mode 6787 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}. 6788 * @return The new action mode if it is started, null otherwise 6789 * 6790 * @see ActionMode 6791 */ 6792 public ActionMode startActionMode(ActionMode.Callback callback, int type) { 6793 ViewParent parent = getParent(); 6794 if (parent == null) return null; 6795 try { 6796 return parent.startActionModeForChild(this, callback, type); 6797 } catch (AbstractMethodError ame) { 6798 // Older implementations of custom views might not implement this. 6799 return parent.startActionModeForChild(this, callback); 6800 } 6801 } 6802 6803 /** 6804 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's 6805 * Context, creating a unique View identifier to retrieve the result. 6806 * 6807 * @param intent The Intent to be started. 6808 * @param requestCode The request code to use. 6809 * @hide 6810 */ 6811 public void startActivityForResult(Intent intent, int requestCode) { 6812 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this); 6813 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null); 6814 } 6815 6816 /** 6817 * If this View corresponds to the calling who, dispatches the activity result. 6818 * @param who The identifier for the targeted View to receive the result. 6819 * @param requestCode The integer request code originally supplied to 6820 * startActivityForResult(), allowing you to identify who this 6821 * result came from. 6822 * @param resultCode The integer result code returned by the child activity 6823 * through its setResult(). 6824 * @param data An Intent, which can return result data to the caller 6825 * (various data can be attached to Intent "extras"). 6826 * @return {@code true} if the activity result was dispatched. 6827 * @hide 6828 */ 6829 public boolean dispatchActivityResult( 6830 String who, int requestCode, int resultCode, Intent data) { 6831 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) { 6832 onActivityResult(requestCode, resultCode, data); 6833 mStartActivityRequestWho = null; 6834 return true; 6835 } 6836 return false; 6837 } 6838 6839 /** 6840 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. 6841 * 6842 * @param requestCode The integer request code originally supplied to 6843 * startActivityForResult(), allowing you to identify who this 6844 * result came from. 6845 * @param resultCode The integer result code returned by the child activity 6846 * through its setResult(). 6847 * @param data An Intent, which can return result data to the caller 6848 * (various data can be attached to Intent "extras"). 6849 * @hide 6850 */ 6851 public void onActivityResult(int requestCode, int resultCode, Intent data) { 6852 // Do nothing. 6853 } 6854 6855 /** 6856 * Register a callback to be invoked when a hardware key is pressed in this view. 6857 * Key presses in software input methods will generally not trigger the methods of 6858 * this listener. 6859 * @param l the key listener to attach to this view 6860 */ 6861 public void setOnKeyListener(OnKeyListener l) { 6862 getListenerInfo().mOnKeyListener = l; 6863 } 6864 6865 /** 6866 * Register a callback to be invoked when a touch event is sent to this view. 6867 * @param l the touch listener to attach to this view 6868 */ 6869 public void setOnTouchListener(OnTouchListener l) { 6870 getListenerInfo().mOnTouchListener = l; 6871 } 6872 6873 /** 6874 * Register a callback to be invoked when a generic motion event is sent to this view. 6875 * @param l the generic motion listener to attach to this view 6876 */ 6877 public void setOnGenericMotionListener(OnGenericMotionListener l) { 6878 getListenerInfo().mOnGenericMotionListener = l; 6879 } 6880 6881 /** 6882 * Register a callback to be invoked when a hover event is sent to this view. 6883 * @param l the hover listener to attach to this view 6884 */ 6885 public void setOnHoverListener(OnHoverListener l) { 6886 getListenerInfo().mOnHoverListener = l; 6887 } 6888 6889 /** 6890 * Register a drag event listener callback object for this View. The parameter is 6891 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 6892 * View, the system calls the 6893 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 6894 * @param l An implementation of {@link android.view.View.OnDragListener}. 6895 */ 6896 public void setOnDragListener(OnDragListener l) { 6897 getListenerInfo().mOnDragListener = l; 6898 } 6899 6900 /** 6901 * Give this view focus. This will cause 6902 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 6903 * 6904 * Note: this does not check whether this {@link View} should get focus, it just 6905 * gives it focus no matter what. It should only be called internally by framework 6906 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 6907 * 6908 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 6909 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 6910 * focus moved when requestFocus() is called. It may not always 6911 * apply, in which case use the default View.FOCUS_DOWN. 6912 * @param previouslyFocusedRect The rectangle of the view that had focus 6913 * prior in this View's coordinate system. 6914 */ 6915 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) { 6916 if (DBG) { 6917 System.out.println(this + " requestFocus()"); 6918 } 6919 6920 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 6921 mPrivateFlags |= PFLAG_FOCUSED; 6922 6923 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 6924 6925 if (mParent != null) { 6926 mParent.requestChildFocus(this, this); 6927 updateFocusedInCluster(oldFocus, direction); 6928 } 6929 6930 if (mAttachInfo != null) { 6931 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 6932 } 6933 6934 onFocusChanged(true, direction, previouslyFocusedRect); 6935 refreshDrawableState(); 6936 } 6937 } 6938 6939 /** 6940 * Sets this view's preference for reveal behavior when it gains focus. 6941 * 6942 * <p>When set to true, this is a signal to ancestor views in the hierarchy that 6943 * this view would prefer to be brought fully into view when it gains focus. 6944 * For example, a text field that a user is meant to type into. Other views such 6945 * as scrolling containers may prefer to opt-out of this behavior.</p> 6946 * 6947 * <p>The default value for views is true, though subclasses may change this 6948 * based on their preferred behavior.</p> 6949 * 6950 * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise 6951 * 6952 * @see #getRevealOnFocusHint() 6953 */ 6954 public final void setRevealOnFocusHint(boolean revealOnFocus) { 6955 if (revealOnFocus) { 6956 mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS; 6957 } else { 6958 mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS; 6959 } 6960 } 6961 6962 /** 6963 * Returns this view's preference for reveal behavior when it gains focus. 6964 * 6965 * <p>When this method returns true for a child view requesting focus, ancestor 6966 * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)} 6967 * should make a best effort to make the newly focused child fully visible to the user. 6968 * When it returns false, ancestor views should preferably not disrupt scroll positioning or 6969 * other properties affecting visibility to the user as part of the focus change.</p> 6970 * 6971 * @return true if this view would prefer to become fully visible when it gains focus, 6972 * false if it would prefer not to disrupt scroll positioning 6973 * 6974 * @see #setRevealOnFocusHint(boolean) 6975 */ 6976 public final boolean getRevealOnFocusHint() { 6977 return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0; 6978 } 6979 6980 /** 6981 * Populates <code>outRect</code> with the hotspot bounds. By default, 6982 * the hotspot bounds are identical to the screen bounds. 6983 * 6984 * @param outRect rect to populate with hotspot bounds 6985 * @hide Only for internal use by views and widgets. 6986 */ 6987 public void getHotspotBounds(Rect outRect) { 6988 final Drawable background = getBackground(); 6989 if (background != null) { 6990 background.getHotspotBounds(outRect); 6991 } else { 6992 getBoundsOnScreen(outRect); 6993 } 6994 } 6995 6996 /** 6997 * Request that a rectangle of this view be visible on the screen, 6998 * scrolling if necessary just enough. 6999 * 7000 * <p>A View should call this if it maintains some notion of which part 7001 * of its content is interesting. For example, a text editing view 7002 * should call this when its cursor moves. 7003 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 7004 * It should not be affected by which part of the View is currently visible or its scroll 7005 * position. 7006 * 7007 * @param rectangle The rectangle in the View's content coordinate space 7008 * @return Whether any parent scrolled. 7009 */ 7010 public boolean requestRectangleOnScreen(Rect rectangle) { 7011 return requestRectangleOnScreen(rectangle, false); 7012 } 7013 7014 /** 7015 * Request that a rectangle of this view be visible on the screen, 7016 * scrolling if necessary just enough. 7017 * 7018 * <p>A View should call this if it maintains some notion of which part 7019 * of its content is interesting. For example, a text editing view 7020 * should call this when its cursor moves. 7021 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 7022 * It should not be affected by which part of the View is currently visible or its scroll 7023 * position. 7024 * <p>When <code>immediate</code> is set to true, scrolling will not be 7025 * animated. 7026 * 7027 * @param rectangle The rectangle in the View's content coordinate space 7028 * @param immediate True to forbid animated scrolling, false otherwise 7029 * @return Whether any parent scrolled. 7030 */ 7031 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 7032 if (mParent == null) { 7033 return false; 7034 } 7035 7036 View child = this; 7037 7038 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 7039 position.set(rectangle); 7040 7041 ViewParent parent = mParent; 7042 boolean scrolled = false; 7043 while (parent != null) { 7044 rectangle.set((int) position.left, (int) position.top, 7045 (int) position.right, (int) position.bottom); 7046 7047 scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate); 7048 7049 if (!(parent instanceof View)) { 7050 break; 7051 } 7052 7053 // move it from child's content coordinate space to parent's content coordinate space 7054 position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY()); 7055 7056 child = (View) parent; 7057 parent = child.getParent(); 7058 } 7059 7060 return scrolled; 7061 } 7062 7063 /** 7064 * Called when this view wants to give up focus. If focus is cleared 7065 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 7066 * <p> 7067 * <strong>Note:</strong> When not in touch-mode, the framework will try to give focus 7068 * to the first focusable View from the top after focus is cleared. Hence, if this 7069 * View is the first from the top that can take focus, then all callbacks 7070 * related to clearing focus will be invoked after which the framework will 7071 * give focus to this view. 7072 * </p> 7073 */ 7074 public void clearFocus() { 7075 if (DBG) { 7076 System.out.println(this + " clearFocus()"); 7077 } 7078 7079 final boolean refocus = sAlwaysAssignFocus || !isInTouchMode(); 7080 clearFocusInternal(null, true, refocus); 7081 } 7082 7083 /** 7084 * Clears focus from the view, optionally propagating the change up through 7085 * the parent hierarchy and requesting that the root view place new focus. 7086 * 7087 * @param propagate whether to propagate the change up through the parent 7088 * hierarchy 7089 * @param refocus when propagate is true, specifies whether to request the 7090 * root view place new focus 7091 */ 7092 void clearFocusInternal(View focused, boolean propagate, boolean refocus) { 7093 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 7094 mPrivateFlags &= ~PFLAG_FOCUSED; 7095 clearParentsWantFocus(); 7096 7097 if (propagate && mParent != null) { 7098 mParent.clearChildFocus(this); 7099 } 7100 7101 onFocusChanged(false, 0, null); 7102 refreshDrawableState(); 7103 7104 if (propagate && (!refocus || !rootViewRequestFocus())) { 7105 notifyGlobalFocusCleared(this); 7106 } 7107 } 7108 } 7109 7110 void notifyGlobalFocusCleared(View oldFocus) { 7111 if (oldFocus != null && mAttachInfo != null) { 7112 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 7113 } 7114 } 7115 7116 boolean rootViewRequestFocus() { 7117 final View root = getRootView(); 7118 return root != null && root.requestFocus(); 7119 } 7120 7121 /** 7122 * Called internally by the view system when a new view is getting focus. 7123 * This is what clears the old focus. 7124 * <p> 7125 * <b>NOTE:</b> The parent view's focused child must be updated manually 7126 * after calling this method. Otherwise, the view hierarchy may be left in 7127 * an inconstent state. 7128 */ 7129 void unFocus(View focused) { 7130 if (DBG) { 7131 System.out.println(this + " unFocus()"); 7132 } 7133 7134 clearFocusInternal(focused, false, false); 7135 } 7136 7137 /** 7138 * Returns true if this view has focus itself, or is the ancestor of the 7139 * view that has focus. 7140 * 7141 * @return True if this view has or contains focus, false otherwise. 7142 */ 7143 @ViewDebug.ExportedProperty(category = "focus") 7144 public boolean hasFocus() { 7145 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 7146 } 7147 7148 /** 7149 * Returns true if this view is focusable or if it contains a reachable View 7150 * for which {@link #hasFocusable()} returns {@code true}. A "reachable hasFocusable()" 7151 * is a view whose parents do not block descendants focus. 7152 * Only {@link #VISIBLE} views are considered focusable. 7153 * 7154 * <p>As of {@link Build.VERSION_CODES#O} views that are determined to be focusable 7155 * through {@link #FOCUSABLE_AUTO} will also cause this method to return {@code true}. 7156 * Apps that declare a {@link android.content.pm.ApplicationInfo#targetSdkVersion} of 7157 * earlier than {@link Build.VERSION_CODES#O} will continue to see this method return 7158 * {@code false} for views not explicitly marked as focusable. 7159 * Use {@link #hasExplicitFocusable()} if you require the pre-{@link Build.VERSION_CODES#O} 7160 * behavior.</p> 7161 * 7162 * @return {@code true} if the view is focusable or if the view contains a focusable 7163 * view, {@code false} otherwise 7164 * 7165 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 7166 * @see ViewGroup#getTouchscreenBlocksFocus() 7167 * @see #hasExplicitFocusable() 7168 */ 7169 public boolean hasFocusable() { 7170 return hasFocusable(!sHasFocusableExcludeAutoFocusable, false); 7171 } 7172 7173 /** 7174 * Returns true if this view is focusable or if it contains a reachable View 7175 * for which {@link #hasExplicitFocusable()} returns {@code true}. 7176 * A "reachable hasExplicitFocusable()" is a view whose parents do not block descendants focus. 7177 * Only {@link #VISIBLE} views for which {@link #getFocusable()} would return 7178 * {@link #FOCUSABLE} are considered focusable. 7179 * 7180 * <p>This method preserves the pre-{@link Build.VERSION_CODES#O} behavior of 7181 * {@link #hasFocusable()} in that only views explicitly set focusable will cause 7182 * this method to return true. A view set to {@link #FOCUSABLE_AUTO} that resolves 7183 * to focusable will not.</p> 7184 * 7185 * @return {@code true} if the view is focusable or if the view contains a focusable 7186 * view, {@code false} otherwise 7187 * 7188 * @see #hasFocusable() 7189 */ 7190 public boolean hasExplicitFocusable() { 7191 return hasFocusable(false, true); 7192 } 7193 7194 boolean hasFocusable(boolean allowAutoFocus, boolean dispatchExplicit) { 7195 if (!isFocusableInTouchMode()) { 7196 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) { 7197 final ViewGroup g = (ViewGroup) p; 7198 if (g.shouldBlockFocusForTouchscreen()) { 7199 return false; 7200 } 7201 } 7202 } 7203 7204 // Invisible, gone, or disabled views are never focusable. 7205 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE 7206 || (mViewFlags & ENABLED_MASK) != ENABLED) { 7207 return false; 7208 } 7209 7210 // Only use effective focusable value when allowed. 7211 if ((allowAutoFocus || getFocusable() != FOCUSABLE_AUTO) && isFocusable()) { 7212 return true; 7213 } 7214 7215 return false; 7216 } 7217 7218 /** 7219 * Called by the view system when the focus state of this view changes. 7220 * When the focus change event is caused by directional navigation, direction 7221 * and previouslyFocusedRect provide insight into where the focus is coming from. 7222 * When overriding, be sure to call up through to the super class so that 7223 * the standard focus handling will occur. 7224 * 7225 * @param gainFocus True if the View has focus; false otherwise. 7226 * @param direction The direction focus has moved when requestFocus() 7227 * is called to give this view focus. Values are 7228 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 7229 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 7230 * It may not always apply, in which case use the default. 7231 * @param previouslyFocusedRect The rectangle, in this view's coordinate 7232 * system, of the previously focused view. If applicable, this will be 7233 * passed in as finer grained information about where the focus is coming 7234 * from (in addition to direction). Will be <code>null</code> otherwise. 7235 */ 7236 @CallSuper 7237 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, 7238 @Nullable Rect previouslyFocusedRect) { 7239 if (gainFocus) { 7240 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 7241 } else { 7242 notifyViewAccessibilityStateChangedIfNeeded( 7243 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7244 } 7245 7246 // Here we check whether we still need the default focus highlight, and switch it on/off. 7247 switchDefaultFocusHighlight(); 7248 7249 InputMethodManager imm = InputMethodManager.peekInstance(); 7250 if (!gainFocus) { 7251 if (isPressed()) { 7252 setPressed(false); 7253 } 7254 if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) { 7255 imm.focusOut(this); 7256 } 7257 onFocusLost(); 7258 } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) { 7259 imm.focusIn(this); 7260 } 7261 7262 invalidate(true); 7263 ListenerInfo li = mListenerInfo; 7264 if (li != null && li.mOnFocusChangeListener != null) { 7265 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 7266 } 7267 7268 if (mAttachInfo != null) { 7269 mAttachInfo.mKeyDispatchState.reset(this); 7270 } 7271 7272 notifyEnterOrExitForAutoFillIfNeeded(gainFocus); 7273 } 7274 7275 /** @hide */ 7276 public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) { 7277 if (canNotifyAutofillEnterExitEvent()) { 7278 AutofillManager afm = getAutofillManager(); 7279 if (afm != null) { 7280 if (enter && isFocused()) { 7281 // We have not been laid out yet, hence cannot evaluate 7282 // whether this view is visible to the user, we will do 7283 // the evaluation once layout is complete. 7284 if (!isLaidOut()) { 7285 mPrivateFlags3 |= PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT; 7286 } else if (isVisibleToUser()) { 7287 // TODO This is a potential problem that View gets focus before it's visible 7288 // to User. Ideally View should handle the event when isVisibleToUser() 7289 // becomes true where it should issue notifyViewEntered(). 7290 afm.notifyViewEntered(this); 7291 } 7292 } else if (!enter && !isFocused()) { 7293 afm.notifyViewExited(this); 7294 } 7295 } 7296 } 7297 } 7298 7299 /** 7300 * Visually distinct portion of a window with window-like semantics are considered panes for 7301 * accessibility purposes. One example is the content view of a fragment that is replaced. 7302 * In order for accessibility services to understand a pane's window-like behavior, panes 7303 * should have descriptive titles. Views with pane titles produce {@link AccessibilityEvent}s 7304 * when they appear, disappear, or change title. 7305 * 7306 * @param accessibilityPaneTitle The pane's title. Setting to {@code null} indicates that this 7307 * View is not a pane. 7308 * 7309 * {@see AccessibilityNodeInfo#setPaneTitle(CharSequence)} 7310 */ 7311 public void setAccessibilityPaneTitle(@Nullable CharSequence accessibilityPaneTitle) { 7312 if (!TextUtils.equals(accessibilityPaneTitle, mAccessibilityPaneTitle)) { 7313 mAccessibilityPaneTitle = accessibilityPaneTitle; 7314 notifyViewAccessibilityStateChangedIfNeeded( 7315 AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE); 7316 } 7317 } 7318 7319 /** 7320 * Get the title of the pane for purposes of accessibility. 7321 * 7322 * @return The current pane title. 7323 * 7324 * {@see #setAccessibilityPaneTitle}. 7325 */ 7326 @Nullable public CharSequence getAccessibilityPaneTitle() { 7327 return mAccessibilityPaneTitle; 7328 } 7329 7330 private boolean isAccessibilityPane() { 7331 return mAccessibilityPaneTitle != null; 7332 } 7333 7334 /** 7335 * Sends an accessibility event of the given type. If accessibility is 7336 * not enabled this method has no effect. The default implementation calls 7337 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 7338 * to populate information about the event source (this View), then calls 7339 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 7340 * populate the text content of the event source including its descendants, 7341 * and last calls 7342 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 7343 * on its parent to request sending of the event to interested parties. 7344 * <p> 7345 * If an {@link AccessibilityDelegate} has been specified via calling 7346 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7347 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 7348 * responsible for handling this call. 7349 * </p> 7350 * 7351 * @param eventType The type of the event to send, as defined by several types from 7352 * {@link android.view.accessibility.AccessibilityEvent}, such as 7353 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 7354 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 7355 * 7356 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 7357 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 7358 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 7359 * @see AccessibilityDelegate 7360 */ 7361 public void sendAccessibilityEvent(int eventType) { 7362 if (mAccessibilityDelegate != null) { 7363 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 7364 } else { 7365 sendAccessibilityEventInternal(eventType); 7366 } 7367 } 7368 7369 /** 7370 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 7371 * {@link AccessibilityEvent} to make an announcement which is related to some 7372 * sort of a context change for which none of the events representing UI transitions 7373 * is a good fit. For example, announcing a new page in a book. If accessibility 7374 * is not enabled this method does nothing. 7375 * 7376 * @param text The announcement text. 7377 */ 7378 public void announceForAccessibility(CharSequence text) { 7379 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 7380 AccessibilityEvent event = AccessibilityEvent.obtain( 7381 AccessibilityEvent.TYPE_ANNOUNCEMENT); 7382 onInitializeAccessibilityEvent(event); 7383 event.getText().add(text); 7384 event.setContentDescription(null); 7385 mParent.requestSendAccessibilityEvent(this, event); 7386 } 7387 } 7388 7389 /** 7390 * @see #sendAccessibilityEvent(int) 7391 * 7392 * Note: Called from the default {@link AccessibilityDelegate}. 7393 * 7394 * @hide 7395 */ 7396 public void sendAccessibilityEventInternal(int eventType) { 7397 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 7398 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 7399 } 7400 } 7401 7402 /** 7403 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 7404 * takes as an argument an empty {@link AccessibilityEvent} and does not 7405 * perform a check whether accessibility is enabled. 7406 * <p> 7407 * If an {@link AccessibilityDelegate} has been specified via calling 7408 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7409 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 7410 * is responsible for handling this call. 7411 * </p> 7412 * 7413 * @param event The event to send. 7414 * 7415 * @see #sendAccessibilityEvent(int) 7416 */ 7417 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 7418 if (mAccessibilityDelegate != null) { 7419 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 7420 } else { 7421 sendAccessibilityEventUncheckedInternal(event); 7422 } 7423 } 7424 7425 /** 7426 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 7427 * 7428 * Note: Called from the default {@link AccessibilityDelegate}. 7429 * 7430 * @hide 7431 */ 7432 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 7433 // Panes disappearing are relevant even if though the view is no longer visible. 7434 boolean isWindowStateChanged = 7435 (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 7436 boolean isWindowDisappearedEvent = isWindowStateChanged && ((event.getContentChangeTypes() 7437 & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED) != 0); 7438 if (!isShown() && !isWindowDisappearedEvent) { 7439 return; 7440 } 7441 onInitializeAccessibilityEvent(event); 7442 // Only a subset of accessibility events populates text content. 7443 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 7444 dispatchPopulateAccessibilityEvent(event); 7445 } 7446 // In the beginning we called #isShown(), so we know that getParent() is not null. 7447 ViewParent parent = getParent(); 7448 if (parent != null) { 7449 getParent().requestSendAccessibilityEvent(this, event); 7450 } 7451 } 7452 7453 /** 7454 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 7455 * to its children for adding their text content to the event. Note that the 7456 * event text is populated in a separate dispatch path since we add to the 7457 * event not only the text of the source but also the text of all its descendants. 7458 * A typical implementation will call 7459 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 7460 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 7461 * on each child. Override this method if custom population of the event text 7462 * content is required. 7463 * <p> 7464 * If an {@link AccessibilityDelegate} has been specified via calling 7465 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7466 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 7467 * is responsible for handling this call. 7468 * </p> 7469 * <p> 7470 * <em>Note:</em> Accessibility events of certain types are not dispatched for 7471 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 7472 * </p> 7473 * 7474 * @param event The event. 7475 * 7476 * @return True if the event population was completed. 7477 */ 7478 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 7479 if (mAccessibilityDelegate != null) { 7480 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 7481 } else { 7482 return dispatchPopulateAccessibilityEventInternal(event); 7483 } 7484 } 7485 7486 /** 7487 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 7488 * 7489 * Note: Called from the default {@link AccessibilityDelegate}. 7490 * 7491 * @hide 7492 */ 7493 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 7494 onPopulateAccessibilityEvent(event); 7495 return false; 7496 } 7497 7498 /** 7499 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 7500 * giving a chance to this View to populate the accessibility event with its 7501 * text content. While this method is free to modify event 7502 * attributes other than text content, doing so should normally be performed in 7503 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 7504 * <p> 7505 * Example: Adding formatted date string to an accessibility event in addition 7506 * to the text added by the super implementation: 7507 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 7508 * super.onPopulateAccessibilityEvent(event); 7509 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 7510 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 7511 * mCurrentDate.getTimeInMillis(), flags); 7512 * event.getText().add(selectedDateUtterance); 7513 * }</pre> 7514 * <p> 7515 * If an {@link AccessibilityDelegate} has been specified via calling 7516 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7517 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 7518 * is responsible for handling this call. 7519 * </p> 7520 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 7521 * information to the event, in case the default implementation has basic information to add. 7522 * </p> 7523 * 7524 * @param event The accessibility event which to populate. 7525 * 7526 * @see #sendAccessibilityEvent(int) 7527 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 7528 */ 7529 @CallSuper 7530 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 7531 if (mAccessibilityDelegate != null) { 7532 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 7533 } else { 7534 onPopulateAccessibilityEventInternal(event); 7535 } 7536 } 7537 7538 /** 7539 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 7540 * 7541 * Note: Called from the default {@link AccessibilityDelegate}. 7542 * 7543 * @hide 7544 */ 7545 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 7546 if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) 7547 && !TextUtils.isEmpty(getAccessibilityPaneTitle())) { 7548 event.getText().add(getAccessibilityPaneTitle()); 7549 } 7550 } 7551 7552 /** 7553 * Initializes an {@link AccessibilityEvent} with information about 7554 * this View which is the event source. In other words, the source of 7555 * an accessibility event is the view whose state change triggered firing 7556 * the event. 7557 * <p> 7558 * Example: Setting the password property of an event in addition 7559 * to properties set by the super implementation: 7560 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 7561 * super.onInitializeAccessibilityEvent(event); 7562 * event.setPassword(true); 7563 * }</pre> 7564 * <p> 7565 * If an {@link AccessibilityDelegate} has been specified via calling 7566 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7567 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 7568 * is responsible for handling this call. 7569 * </p> 7570 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 7571 * information to the event, in case the default implementation has basic information to add. 7572 * </p> 7573 * @param event The event to initialize. 7574 * 7575 * @see #sendAccessibilityEvent(int) 7576 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 7577 */ 7578 @CallSuper 7579 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 7580 if (mAccessibilityDelegate != null) { 7581 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 7582 } else { 7583 onInitializeAccessibilityEventInternal(event); 7584 } 7585 } 7586 7587 /** 7588 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 7589 * 7590 * Note: Called from the default {@link AccessibilityDelegate}. 7591 * 7592 * @hide 7593 */ 7594 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 7595 event.setSource(this); 7596 event.setClassName(getAccessibilityClassName()); 7597 event.setPackageName(getContext().getPackageName()); 7598 event.setEnabled(isEnabled()); 7599 event.setContentDescription(mContentDescription); 7600 7601 switch (event.getEventType()) { 7602 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 7603 ArrayList<View> focusablesTempList = (mAttachInfo != null) 7604 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 7605 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 7606 event.setItemCount(focusablesTempList.size()); 7607 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 7608 if (mAttachInfo != null) { 7609 focusablesTempList.clear(); 7610 } 7611 } break; 7612 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 7613 CharSequence text = getIterableTextForAccessibility(); 7614 if (text != null && text.length() > 0) { 7615 event.setFromIndex(getAccessibilitySelectionStart()); 7616 event.setToIndex(getAccessibilitySelectionEnd()); 7617 event.setItemCount(text.length()); 7618 } 7619 } break; 7620 } 7621 } 7622 7623 /** 7624 * Returns an {@link AccessibilityNodeInfo} representing this view from the 7625 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 7626 * This method is responsible for obtaining an accessibility node info from a 7627 * pool of reusable instances and calling 7628 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 7629 * initialize the former. 7630 * <p> 7631 * Note: The client is responsible for recycling the obtained instance by calling 7632 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 7633 * </p> 7634 * 7635 * @return A populated {@link AccessibilityNodeInfo}. 7636 * 7637 * @see AccessibilityNodeInfo 7638 */ 7639 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 7640 if (mAccessibilityDelegate != null) { 7641 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 7642 } else { 7643 return createAccessibilityNodeInfoInternal(); 7644 } 7645 } 7646 7647 /** 7648 * @see #createAccessibilityNodeInfo() 7649 * 7650 * @hide 7651 */ 7652 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 7653 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 7654 if (provider != null) { 7655 return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID); 7656 } else { 7657 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 7658 onInitializeAccessibilityNodeInfo(info); 7659 return info; 7660 } 7661 } 7662 7663 /** 7664 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 7665 * The base implementation sets: 7666 * <ul> 7667 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 7668 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 7669 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 7670 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 7671 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 7672 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 7673 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 7674 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 7675 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 7676 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 7677 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 7678 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 7679 * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li> 7680 * </ul> 7681 * <p> 7682 * Subclasses should override this method, call the super implementation, 7683 * and set additional attributes. 7684 * </p> 7685 * <p> 7686 * If an {@link AccessibilityDelegate} has been specified via calling 7687 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7688 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 7689 * is responsible for handling this call. 7690 * </p> 7691 * 7692 * @param info The instance to initialize. 7693 */ 7694 @CallSuper 7695 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 7696 if (mAccessibilityDelegate != null) { 7697 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 7698 } else { 7699 onInitializeAccessibilityNodeInfoInternal(info); 7700 } 7701 } 7702 7703 /** 7704 * Gets the location of this view in screen coordinates. 7705 * 7706 * @param outRect The output location 7707 * @hide 7708 */ 7709 public void getBoundsOnScreen(Rect outRect) { 7710 getBoundsOnScreen(outRect, false); 7711 } 7712 7713 /** 7714 * Gets the location of this view in screen coordinates. 7715 * 7716 * @param outRect The output location 7717 * @param clipToParent Whether to clip child bounds to the parent ones. 7718 * @hide 7719 */ 7720 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { 7721 if (mAttachInfo == null) { 7722 return; 7723 } 7724 7725 RectF position = mAttachInfo.mTmpTransformRect; 7726 position.set(0, 0, mRight - mLeft, mBottom - mTop); 7727 mapRectFromViewToScreenCoords(position, clipToParent); 7728 outRect.set(Math.round(position.left), Math.round(position.top), 7729 Math.round(position.right), Math.round(position.bottom)); 7730 } 7731 7732 /** 7733 * Map a rectangle from view-relative coordinates to screen-relative coordinates 7734 * 7735 * @param rect The rectangle to be mapped 7736 * @param clipToParent Whether to clip child bounds to the parent ones. 7737 * @hide 7738 */ 7739 public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) { 7740 if (!hasIdentityMatrix()) { 7741 getMatrix().mapRect(rect); 7742 } 7743 7744 rect.offset(mLeft, mTop); 7745 7746 ViewParent parent = mParent; 7747 while (parent instanceof View) { 7748 View parentView = (View) parent; 7749 7750 rect.offset(-parentView.mScrollX, -parentView.mScrollY); 7751 7752 if (clipToParent) { 7753 rect.left = Math.max(rect.left, 0); 7754 rect.top = Math.max(rect.top, 0); 7755 rect.right = Math.min(rect.right, parentView.getWidth()); 7756 rect.bottom = Math.min(rect.bottom, parentView.getHeight()); 7757 } 7758 7759 if (!parentView.hasIdentityMatrix()) { 7760 parentView.getMatrix().mapRect(rect); 7761 } 7762 7763 rect.offset(parentView.mLeft, parentView.mTop); 7764 7765 parent = parentView.mParent; 7766 } 7767 7768 if (parent instanceof ViewRootImpl) { 7769 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 7770 rect.offset(0, -viewRootImpl.mCurScrollY); 7771 } 7772 7773 rect.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 7774 } 7775 7776 /** 7777 * Return the class name of this object to be used for accessibility purposes. 7778 * Subclasses should only override this if they are implementing something that 7779 * should be seen as a completely new class of view when used by accessibility, 7780 * unrelated to the class it is deriving from. This is used to fill in 7781 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}. 7782 */ 7783 public CharSequence getAccessibilityClassName() { 7784 return View.class.getName(); 7785 } 7786 7787 /** 7788 * Called when assist structure is being retrieved from a view as part of 7789 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. 7790 * @param structure Fill in with structured view data. The default implementation 7791 * fills in all data that can be inferred from the view itself. 7792 */ 7793 public void onProvideStructure(ViewStructure structure) { 7794 onProvideStructureForAssistOrAutofill(structure, false, 0); 7795 } 7796 7797 /** 7798 * Populates a {@link ViewStructure} to fullfil an autofill request. 7799 * 7800 * <p>The structure should contain at least the following properties: 7801 * <ul> 7802 * <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}). 7803 * <li>Autofill type ({@link ViewStructure#setAutofillType(int)}). 7804 * <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}). 7805 * <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}). 7806 * </ul> 7807 * 7808 * <p>It's also recommended to set the following properties - the more properties the structure 7809 * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly 7810 * using the structure: 7811 * 7812 * <ul> 7813 * <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}). 7814 * <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the 7815 * view can only be filled with predefined values (typically used when the autofill type 7816 * is {@link #AUTOFILL_TYPE_LIST}). 7817 * <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}). 7818 * <li>Class name ({@link ViewStructure#setClassName(String)}). 7819 * <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}). 7820 * <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}), 7821 * dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and 7822 * opacity ({@link ViewStructure#setOpaque(boolean)}). 7823 * <li>For views representing text fields, text properties such as the text itself 7824 * ({@link ViewStructure#setText(CharSequence)}), text hints 7825 * ({@link ViewStructure#setHint(CharSequence)}, input type 7826 * ({@link ViewStructure#setInputType(int)}), 7827 * <li>For views representing HTML nodes, its web domain 7828 * ({@link ViewStructure#setWebDomain(String)}) and HTML properties 7829 * (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}). 7830 * </ul> 7831 * 7832 * <p>The default implementation of this method already sets most of these properties based on 7833 * related {@link View} methods (for example, the autofill id is set using 7834 * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.), 7835 * and views in the standard Android widgets library also override it to set their 7836 * relevant properties (for example, {@link android.widget.TextView} already sets the text 7837 * properties), so it's recommended to only override this method 7838 * (and call {@code super.onProvideAutofillStructure()}) when: 7839 * 7840 * <ul> 7841 * <li>The view contents does not include PII (Personally Identifiable Information), so it 7842 * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}. 7843 * <li>The view can only be autofilled with predefined options, so it can call 7844 * {@link ViewStructure#setAutofillOptions(CharSequence[])}. 7845 * </ul> 7846 * 7847 * <p><b>Note:</b> The {@code left} and {@code top} values set in 7848 * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next 7849 * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure. 7850 * 7851 * <p>Views support the Autofill Framework mainly by: 7852 * <ul> 7853 * <li>Providing the metadata defining what the view means and how it can be autofilled. 7854 * <li>Notifying the Android System when the view value changed by calling 7855 * {@link AutofillManager#notifyValueChanged(View)}. 7856 * <li>Implementing the methods that autofill the view. 7857 * </ul> 7858 * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible 7859 * for the latter. 7860 * 7861 * @param structure fill in with structured view data for autofill purposes. 7862 * @param flags optional flags. 7863 * 7864 * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 7865 */ 7866 public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) { 7867 onProvideStructureForAssistOrAutofill(structure, true, flags); 7868 } 7869 7870 private void onProvideStructureForAssistOrAutofill(ViewStructure structure, 7871 boolean forAutofill, @AutofillFlags int flags) { 7872 final int id = mID; 7873 if (id != NO_ID && !isViewIdGenerated(id)) { 7874 String pkg, type, entry; 7875 try { 7876 final Resources res = getResources(); 7877 entry = res.getResourceEntryName(id); 7878 type = res.getResourceTypeName(id); 7879 pkg = res.getResourcePackageName(id); 7880 } catch (Resources.NotFoundException e) { 7881 entry = type = pkg = null; 7882 } 7883 structure.setId(id, pkg, type, entry); 7884 } else { 7885 structure.setId(id, null, null, null); 7886 } 7887 7888 if (forAutofill) { 7889 final @AutofillType int autofillType = getAutofillType(); 7890 // Don't need to fill autofill info if view does not support it. 7891 // For example, only TextViews that are editable support autofill 7892 if (autofillType != AUTOFILL_TYPE_NONE) { 7893 structure.setAutofillType(autofillType); 7894 structure.setAutofillHints(getAutofillHints()); 7895 structure.setAutofillValue(getAutofillValue()); 7896 } 7897 structure.setImportantForAutofill(getImportantForAutofill()); 7898 } 7899 7900 int ignoredParentLeft = 0; 7901 int ignoredParentTop = 0; 7902 if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) { 7903 View parentGroup = null; 7904 7905 ViewParent viewParent = getParent(); 7906 if (viewParent instanceof View) { 7907 parentGroup = (View) viewParent; 7908 } 7909 7910 while (parentGroup != null && !parentGroup.isImportantForAutofill()) { 7911 ignoredParentLeft += parentGroup.mLeft; 7912 ignoredParentTop += parentGroup.mTop; 7913 7914 viewParent = parentGroup.getParent(); 7915 if (viewParent instanceof View) { 7916 parentGroup = (View) viewParent; 7917 } else { 7918 break; 7919 } 7920 } 7921 } 7922 7923 structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY, 7924 mRight - mLeft, mBottom - mTop); 7925 if (!forAutofill) { 7926 if (!hasIdentityMatrix()) { 7927 structure.setTransformation(getMatrix()); 7928 } 7929 structure.setElevation(getZ()); 7930 } 7931 structure.setVisibility(getVisibility()); 7932 structure.setEnabled(isEnabled()); 7933 if (isClickable()) { 7934 structure.setClickable(true); 7935 } 7936 if (isFocusable()) { 7937 structure.setFocusable(true); 7938 } 7939 if (isFocused()) { 7940 structure.setFocused(true); 7941 } 7942 if (isAccessibilityFocused()) { 7943 structure.setAccessibilityFocused(true); 7944 } 7945 if (isSelected()) { 7946 structure.setSelected(true); 7947 } 7948 if (isActivated()) { 7949 structure.setActivated(true); 7950 } 7951 if (isLongClickable()) { 7952 structure.setLongClickable(true); 7953 } 7954 if (this instanceof Checkable) { 7955 structure.setCheckable(true); 7956 if (((Checkable)this).isChecked()) { 7957 structure.setChecked(true); 7958 } 7959 } 7960 if (isOpaque()) { 7961 structure.setOpaque(true); 7962 } 7963 if (isContextClickable()) { 7964 structure.setContextClickable(true); 7965 } 7966 structure.setClassName(getAccessibilityClassName().toString()); 7967 structure.setContentDescription(getContentDescription()); 7968 } 7969 7970 /** 7971 * Called when assist structure is being retrieved from a view as part of 7972 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to 7973 * generate additional virtual structure under this view. The defaullt implementation 7974 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the 7975 * view's virtual accessibility nodes, if any. You can override this for a more 7976 * optimal implementation providing this data. 7977 */ 7978 public void onProvideVirtualStructure(ViewStructure structure) { 7979 onProvideVirtualStructureCompat(structure, false); 7980 } 7981 7982 /** 7983 * Fallback implementation to populate a ViewStructure from accessibility state. 7984 * 7985 * @param structure The structure to populate. 7986 * @param forAutofill Whether the structure is needed for autofill. 7987 */ 7988 private void onProvideVirtualStructureCompat(ViewStructure structure, boolean forAutofill) { 7989 final AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 7990 if (provider != null) { 7991 if (android.view.autofill.Helper.sVerbose && forAutofill) { 7992 Log.v(VIEW_LOG_TAG, "onProvideVirtualStructureCompat() for " + this); 7993 } 7994 7995 final AccessibilityNodeInfo info = createAccessibilityNodeInfo(); 7996 structure.setChildCount(1); 7997 final ViewStructure root = structure.newChild(0); 7998 populateVirtualStructure(root, provider, info, forAutofill); 7999 info.recycle(); 8000 } 8001 } 8002 8003 /** 8004 * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill 8005 * request. 8006 * 8007 * <p>This method should be used when the view manages a virtual structure under this view. For 8008 * example, a view that draws input fields using {@link #draw(Canvas)}. 8009 * 8010 * <p>When implementing this method, subclasses must follow the rules below: 8011 * 8012 * <ul> 8013 * <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or 8014 * {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id 8015 * identifying the children in the virtual structure. 8016 * <li>The children hierarchy can have multiple levels if necessary, but ideally it should 8017 * exclude intermediate levels that are irrelevant for autofill; that would improve the 8018 * autofill performance. 8019 * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual 8020 * children. 8021 * <li>Set the autofill properties of the child structure as defined by 8022 * {@link #onProvideAutofillStructure(ViewStructure, int)}, using 8023 * {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id. 8024 * <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)} 8025 * and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)} 8026 * when the focused virtual child changed. 8027 * <li>Override {@link #isVisibleToUserForAutofill(int)} to allow the platform to query 8028 * whether a given virtual view is visible to the user in order to support triggering 8029 * save when all views of interest go away. 8030 * <li>Call 8031 * {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)} 8032 * when the value of a virtual child changed. 8033 * <li>Call {@link 8034 * android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)} 8035 * when the visibility of a virtual child changed. 8036 * <li>Call 8037 * {@link android.view.autofill.AutofillManager#notifyViewClicked(View, int)} when a virtual 8038 * child is clicked. 8039 * <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure 8040 * changed and the current context should be committed (for example, when the user tapped 8041 * a {@code SUBMIT} button in an HTML page). 8042 * <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure 8043 * changed and the current context should be canceled (for example, when the user tapped 8044 * a {@code CANCEL} button in an HTML page). 8045 * <li>Provide ways for users to manually request autofill by calling 8046 * {@link AutofillManager#requestAutofill(View, int, Rect)}. 8047 * <li>The {@code left} and {@code top} values set in 8048 * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the 8049 * next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the 8050 * structure. 8051 * </ul> 8052 * 8053 * <p>Views with virtual children support the Autofill Framework mainly by: 8054 * <ul> 8055 * <li>Providing the metadata defining what the virtual children mean and how they can be 8056 * autofilled. 8057 * <li>Implementing the methods that autofill the virtual children. 8058 * </ul> 8059 * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible 8060 * for the latter. 8061 * 8062 * @param structure fill in with virtual children data for autofill purposes. 8063 * @param flags optional flags. 8064 * 8065 * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 8066 */ 8067 public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) { 8068 if (mContext.isAutofillCompatibilityEnabled()) { 8069 onProvideVirtualStructureCompat(structure, true); 8070 } 8071 } 8072 8073 /** 8074 * Automatically fills the content of this view with the {@code value}. 8075 * 8076 * <p>Views support the Autofill Framework mainly by: 8077 * <ul> 8078 * <li>Providing the metadata defining what the view means and how it can be autofilled. 8079 * <li>Implementing the methods that autofill the view. 8080 * </ul> 8081 * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former, 8082 * this method is responsible for latter. 8083 * 8084 * <p>This method does nothing by default, but when overridden it typically: 8085 * <ol> 8086 * <li>Checks if the provided value matches the expected type (which is defined by 8087 * {@link #getAutofillType()}). 8088 * <li>Checks if the view is editable - if it isn't, it should return right away. 8089 * <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value. 8090 * <li>Pass the actual value to the equivalent setter in the view. 8091 * </ol> 8092 * 8093 * <p>For example, a text-field view could implement the method this way: 8094 * 8095 * <pre class="prettyprint"> 8096 * @Override 8097 * public void autofill(AutofillValue value) { 8098 * if (!value.isText() || !this.isEditable()) { 8099 * return; 8100 * } 8101 * CharSequence text = value.getTextValue(); 8102 * if (text != null) { 8103 * this.setText(text); 8104 * } 8105 * } 8106 * </pre> 8107 * 8108 * <p>If the value is updated asynchronously, the next call to 8109 * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was 8110 * changed to the autofilled value. If not, the view will not be considered autofilled. 8111 * 8112 * <p><b>Note:</b> After this method is called, the value returned by 8113 * {@link #getAutofillValue()} must be equal to the {@code value} passed to it, otherwise the 8114 * view will not be highlighted as autofilled. 8115 * 8116 * @param value value to be autofilled. 8117 */ 8118 public void autofill(@SuppressWarnings("unused") AutofillValue value) { 8119 } 8120 8121 /** 8122 * Automatically fills the content of the virtual children within this view. 8123 * 8124 * <p>Views with virtual children support the Autofill Framework mainly by: 8125 * <ul> 8126 * <li>Providing the metadata defining what the virtual children mean and how they can be 8127 * autofilled. 8128 * <li>Implementing the methods that autofill the virtual children. 8129 * </ul> 8130 * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the 8131 * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and 8132 * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill. 8133 * 8134 * <p>If a child value is updated asynchronously, the next call to 8135 * {@link AutofillManager#notifyValueChanged(View, int, AutofillValue)} must happen 8136 * <b>after</b> the value was changed to the autofilled value. If not, the child will not be 8137 * considered autofilled. 8138 * 8139 * <p><b>Note:</b> To indicate that a virtual view was autofilled, 8140 * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data 8141 * changes. 8142 * 8143 * @param values map of values to be autofilled, keyed by virtual child id. 8144 * 8145 * @attr ref android.R.styleable#Theme_autofilledHighlight 8146 */ 8147 public void autofill(@NonNull @SuppressWarnings("unused") SparseArray<AutofillValue> values) { 8148 if (!mContext.isAutofillCompatibilityEnabled()) { 8149 return; 8150 } 8151 final AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 8152 if (provider == null) { 8153 return; 8154 } 8155 final int valueCount = values.size(); 8156 for (int i = 0; i < valueCount; i++) { 8157 final AutofillValue value = values.valueAt(i); 8158 if (value.isText()) { 8159 final int virtualId = values.keyAt(i); 8160 final CharSequence text = value.getTextValue(); 8161 final Bundle arguments = new Bundle(); 8162 arguments.putCharSequence( 8163 AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text); 8164 provider.performAction(virtualId, AccessibilityNodeInfo.ACTION_SET_TEXT, arguments); 8165 } 8166 } 8167 } 8168 8169 /** 8170 * Gets the unique, logical identifier of this view in the activity, for autofill purposes. 8171 * 8172 * <p>The autofill id is created on demand, unless it is explicitly set by 8173 * {@link #setAutofillId(AutofillId)}. 8174 * 8175 * <p>See {@link #setAutofillId(AutofillId)} for more info. 8176 * 8177 * @return The View's autofill id. 8178 */ 8179 public final AutofillId getAutofillId() { 8180 if (mAutofillId == null) { 8181 // The autofill id needs to be unique, but its value doesn't matter, 8182 // so it's better to reuse the accessibility id to save space. 8183 mAutofillId = new AutofillId(getAutofillViewId()); 8184 } 8185 return mAutofillId; 8186 } 8187 8188 /** 8189 * Sets the unique, logical identifier of this view in the activity, for autofill purposes. 8190 * 8191 * <p>The autofill id is created on demand, and this method should only be called when a view is 8192 * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as 8193 * that method creates a snapshot of the view that is passed along to the autofill service. 8194 * 8195 * <p>This method is typically used when view subtrees are recycled to represent different 8196 * content* —in this case, the autofill id can be saved before the view content is swapped 8197 * out, and restored later when it's swapped back in. For example: 8198 * 8199 * <pre> 8200 * EditText reusableView = ...; 8201 * ViewGroup parentView = ...; 8202 * AutofillManager afm = ...; 8203 * 8204 * // Swap out the view and change its contents 8205 * AutofillId oldId = reusableView.getAutofillId(); 8206 * CharSequence oldText = reusableView.getText(); 8207 * parentView.removeView(reusableView); 8208 * AutofillId newId = afm.getNextAutofillId(); 8209 * reusableView.setText("New I am"); 8210 * reusableView.setAutofillId(newId); 8211 * parentView.addView(reusableView); 8212 * 8213 * // Later, swap the old content back in 8214 * parentView.removeView(reusableView); 8215 * reusableView.setAutofillId(oldId); 8216 * reusableView.setText(oldText); 8217 * parentView.addView(reusableView); 8218 * </pre> 8219 * 8220 * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view, 8221 * or {@code null} to reset it. Usually it's an id previously allocated to another view (and 8222 * obtained through {@link #getAutofillId()}), or a new value obtained through 8223 * {@link AutofillManager#getNextAutofillId()}. 8224 * 8225 * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to 8226 * a window}. 8227 * 8228 * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view. 8229 */ 8230 public void setAutofillId(@Nullable AutofillId id) { 8231 // TODO(b/37566627): add unit / CTS test for all possible combinations below 8232 if (android.view.autofill.Helper.sVerbose) { 8233 Log.v(VIEW_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id); 8234 } 8235 if (isAttachedToWindow()) { 8236 throw new IllegalStateException("Cannot set autofill id when view is attached"); 8237 } 8238 if (id != null && id.isVirtual()) { 8239 throw new IllegalStateException("Cannot set autofill id assigned to virtual views"); 8240 } 8241 if (id == null && (mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) == 0) { 8242 // Ignore reset because it was never explicitly set before. 8243 return; 8244 } 8245 mAutofillId = id; 8246 if (id != null) { 8247 mAutofillViewId = id.getViewId(); 8248 mPrivateFlags3 |= PFLAG3_AUTOFILLID_EXPLICITLY_SET; 8249 } else { 8250 mAutofillViewId = NO_ID; 8251 mPrivateFlags3 &= ~PFLAG3_AUTOFILLID_EXPLICITLY_SET; 8252 } 8253 } 8254 8255 /** 8256 * Describes the autofill type of this view, so an 8257 * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue} 8258 * when autofilling the view. 8259 * 8260 * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly 8261 * support the Autofill Framework. 8262 * 8263 * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT}, 8264 * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}. 8265 * 8266 * @see #onProvideAutofillStructure(ViewStructure, int) 8267 * @see #autofill(AutofillValue) 8268 */ 8269 public @AutofillType int getAutofillType() { 8270 return AUTOFILL_TYPE_NONE; 8271 } 8272 8273 /** 8274 * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how 8275 * to autofill the view with the user's data. 8276 * 8277 * <p>See {@link #setAutofillHints(String...)} for more info about these hints. 8278 * 8279 * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or 8280 * {@code null} if no hints were set. 8281 * 8282 * @attr ref android.R.styleable#View_autofillHints 8283 */ 8284 @ViewDebug.ExportedProperty() 8285 @Nullable public String[] getAutofillHints() { 8286 return mAutofillHints; 8287 } 8288 8289 /** 8290 * @hide 8291 */ 8292 public boolean isAutofilled() { 8293 return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0; 8294 } 8295 8296 /** 8297 * Gets the {@link View}'s current autofill value. 8298 * 8299 * <p>By default returns {@code null}, but subclasses should override it and return an 8300 * appropriate value to properly support the Autofill Framework. 8301 * 8302 * @see #onProvideAutofillStructure(ViewStructure, int) 8303 * @see #autofill(AutofillValue) 8304 */ 8305 @Nullable 8306 public AutofillValue getAutofillValue() { 8307 return null; 8308 } 8309 8310 /** 8311 * Gets the mode for determining whether this view is important for autofill. 8312 * 8313 * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more 8314 * info about this mode. 8315 * 8316 * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to 8317 * {@link #setImportantForAutofill(int)}. 8318 * 8319 * @attr ref android.R.styleable#View_importantForAutofill 8320 */ 8321 @ViewDebug.ExportedProperty(mapping = { 8322 @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_AUTO, to = "auto"), 8323 @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES, to = "yes"), 8324 @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO, to = "no"), 8325 @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS, 8326 to = "yesExcludeDescendants"), 8327 @ViewDebug.IntToString(from = IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS, 8328 to = "noExcludeDescendants")}) 8329 public @AutofillImportance int getImportantForAutofill() { 8330 return (mPrivateFlags3 8331 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK) >> PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT; 8332 } 8333 8334 /** 8335 * Sets the mode for determining whether this view is considered important for autofill. 8336 * 8337 * <p>The platform determines the importance for autofill automatically but you 8338 * can use this method to customize the behavior. For example: 8339 * 8340 * <ol> 8341 * <li>When the view contents is irrelevant for autofill (for example, a text field used in a 8342 * "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}. 8343 * <li>When both the view and its children are irrelevant for autofill (for example, the root 8344 * view of an activity containing a spreadhseet editor), it should be 8345 * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}. 8346 * <li>When the view content is relevant for autofill but its children aren't (for example, 8347 * a credit card expiration date represented by a custom view that overrides the proper 8348 * autofill methods and has 2 children representing the month and year), it should 8349 * be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}. 8350 * </ol> 8351 * 8352 * <p><b>Note:</b> Setting the mode as {@link #IMPORTANT_FOR_AUTOFILL_NO} or 8353 * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its 8354 * children) will be always be considered not important; for example, when the user explicitly 8355 * makes an autofill request, all views are considered important. See 8356 * {@link #isImportantForAutofill()} for more details about how the View's importance for 8357 * autofill is used. 8358 * 8359 * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES}, 8360 * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, 8361 * or {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}. 8362 * 8363 * @attr ref android.R.styleable#View_importantForAutofill 8364 */ 8365 public void setImportantForAutofill(@AutofillImportance int mode) { 8366 mPrivateFlags3 &= ~PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK; 8367 mPrivateFlags3 |= (mode << PFLAG3_IMPORTANT_FOR_AUTOFILL_SHIFT) 8368 & PFLAG3_IMPORTANT_FOR_AUTOFILL_MASK; 8369 } 8370 8371 /** 8372 * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode} 8373 * associated with this view is considered important for autofill purposes. 8374 * 8375 * <p>Generally speaking, a view is important for autofill if: 8376 * <ol> 8377 * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}. 8378 * <li>The view contents can help an {@link android.service.autofill.AutofillService} 8379 * determine how other views can be autofilled. 8380 * <ol> 8381 * 8382 * <p>For example, view containers should typically return {@code false} for performance reasons 8383 * (since the important info is provided by their children), but if its properties have relevant 8384 * information (for example, a resource id called {@code credentials}, it should return 8385 * {@code true}. On the other hand, views representing labels or editable fields should 8386 * typically return {@code true}, but in some cases they could return {@code false} 8387 * (for example, if they're part of a "Captcha" mechanism). 8388 * 8389 * <p>The value returned by this method depends on the value returned by 8390 * {@link #getImportantForAutofill()}: 8391 * 8392 * <ol> 8393 * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or 8394 * {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true} 8395 * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or 8396 * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false} 8397 * <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics 8398 * that can return {@code true} in some cases (like a container with a resource id), 8399 * but {@code false} in most. 8400 * <li>otherwise, it returns {@code false}. 8401 * </ol> 8402 * 8403 * <p>When a view is considered important for autofill: 8404 * <ul> 8405 * <li>The view might automatically trigger an autofill request when focused on. 8406 * <li>The contents of the view are included in the {@link ViewStructure} used in an autofill 8407 * request. 8408 * </ul> 8409 * 8410 * <p>On the other hand, when a view is considered not important for autofill: 8411 * <ul> 8412 * <li>The view never automatically triggers autofill requests, but it can trigger a manual 8413 * request through {@link AutofillManager#requestAutofill(View)}. 8414 * <li>The contents of the view are not included in the {@link ViewStructure} used in an 8415 * autofill request, unless the request has the 8416 * {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag. 8417 * </ul> 8418 * 8419 * @return whether the view is considered important for autofill. 8420 * 8421 * @see #setImportantForAutofill(int) 8422 * @see #IMPORTANT_FOR_AUTOFILL_AUTO 8423 * @see #IMPORTANT_FOR_AUTOFILL_YES 8424 * @see #IMPORTANT_FOR_AUTOFILL_NO 8425 * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS 8426 * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS 8427 * @see AutofillManager#requestAutofill(View) 8428 */ 8429 public final boolean isImportantForAutofill() { 8430 // Check parent mode to ensure we're not hidden. 8431 ViewParent parent = mParent; 8432 while (parent instanceof View) { 8433 final int parentImportance = ((View) parent).getImportantForAutofill(); 8434 if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS 8435 || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) { 8436 return false; 8437 } 8438 parent = parent.getParent(); 8439 } 8440 8441 final int importance = getImportantForAutofill(); 8442 8443 // First, check the explicit states. 8444 if (importance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS 8445 || importance == IMPORTANT_FOR_AUTOFILL_YES) { 8446 return true; 8447 } 8448 if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS 8449 || importance == IMPORTANT_FOR_AUTOFILL_NO) { 8450 return false; 8451 } 8452 8453 // Then use some heuristics to handle AUTO. 8454 8455 // Always include views that have an explicit resource id. 8456 final int id = mID; 8457 if (id != NO_ID && !isViewIdGenerated(id)) { 8458 final Resources res = getResources(); 8459 String entry = null; 8460 String pkg = null; 8461 try { 8462 entry = res.getResourceEntryName(id); 8463 pkg = res.getResourcePackageName(id); 8464 } catch (Resources.NotFoundException e) { 8465 // ignore 8466 } 8467 if (entry != null && pkg != null && pkg.equals(mContext.getPackageName())) { 8468 return true; 8469 } 8470 } 8471 8472 // If the app developer explicitly set hints for it, it's important. 8473 if (getAutofillHints() != null) { 8474 return true; 8475 } 8476 8477 // Otherwise, assume it's not important... 8478 return false; 8479 } 8480 8481 @Nullable 8482 private AutofillManager getAutofillManager() { 8483 return mContext.getSystemService(AutofillManager.class); 8484 } 8485 8486 private boolean isAutofillable() { 8487 return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill() 8488 && getAutofillViewId() > LAST_APP_AUTOFILL_ID; 8489 } 8490 8491 /** @hide */ 8492 public boolean canNotifyAutofillEnterExitEvent() { 8493 return isAutofillable() && isAttachedToWindow(); 8494 } 8495 8496 private void populateVirtualStructure(ViewStructure structure, 8497 AccessibilityNodeProvider provider, AccessibilityNodeInfo info, 8498 boolean forAutofill) { 8499 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), 8500 null, null, info.getViewIdResourceName()); 8501 Rect rect = structure.getTempRect(); 8502 info.getBoundsInParent(rect); 8503 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height()); 8504 structure.setVisibility(VISIBLE); 8505 structure.setEnabled(info.isEnabled()); 8506 if (info.isClickable()) { 8507 structure.setClickable(true); 8508 } 8509 if (info.isFocusable()) { 8510 structure.setFocusable(true); 8511 } 8512 if (info.isFocused()) { 8513 structure.setFocused(true); 8514 } 8515 if (info.isAccessibilityFocused()) { 8516 structure.setAccessibilityFocused(true); 8517 } 8518 if (info.isSelected()) { 8519 structure.setSelected(true); 8520 } 8521 if (info.isLongClickable()) { 8522 structure.setLongClickable(true); 8523 } 8524 if (info.isCheckable()) { 8525 structure.setCheckable(true); 8526 if (info.isChecked()) { 8527 structure.setChecked(true); 8528 } 8529 } 8530 if (info.isContextClickable()) { 8531 structure.setContextClickable(true); 8532 } 8533 if (forAutofill) { 8534 structure.setAutofillId(new AutofillId(getAutofillId(), 8535 AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()))); 8536 } 8537 CharSequence cname = info.getClassName(); 8538 structure.setClassName(cname != null ? cname.toString() : null); 8539 structure.setContentDescription(info.getContentDescription()); 8540 if (forAutofill) { 8541 final int maxTextLength = info.getMaxTextLength(); 8542 if (maxTextLength != -1) { 8543 structure.setMaxTextLength(maxTextLength); 8544 } 8545 structure.setHint(info.getHintText()); 8546 } 8547 CharSequence text = info.getText(); 8548 boolean hasText = text != null || info.getError() != null; 8549 if (hasText) { 8550 structure.setText(text, info.getTextSelectionStart(), info.getTextSelectionEnd()); 8551 } 8552 if (forAutofill) { 8553 if (info.isEditable()) { 8554 structure.setDataIsSensitive(true); 8555 if (hasText) { 8556 structure.setAutofillType(AUTOFILL_TYPE_TEXT); 8557 structure.setAutofillValue(AutofillValue.forText(text)); 8558 } 8559 int inputType = info.getInputType(); 8560 if (inputType == 0 && info.isPassword()) { 8561 inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD; 8562 } 8563 structure.setInputType(inputType); 8564 } else { 8565 structure.setDataIsSensitive(false); 8566 } 8567 } 8568 final int NCHILDREN = info.getChildCount(); 8569 if (NCHILDREN > 0) { 8570 structure.setChildCount(NCHILDREN); 8571 for (int i=0; i<NCHILDREN; i++) { 8572 if (AccessibilityNodeInfo.getVirtualDescendantId(info.getChildNodeIds().get(i)) 8573 == AccessibilityNodeProvider.HOST_VIEW_ID) { 8574 Log.e(VIEW_LOG_TAG, "Virtual view pointing to its host. Ignoring"); 8575 continue; 8576 } 8577 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( 8578 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); 8579 ViewStructure child = structure.newChild(i); 8580 populateVirtualStructure(child, provider, cinfo, forAutofill); 8581 cinfo.recycle(); 8582 } 8583 } 8584 } 8585 8586 /** 8587 * Dispatch creation of {@link ViewStructure} down the hierarchy. The default 8588 * implementation calls {@link #onProvideStructure} and 8589 * {@link #onProvideVirtualStructure}. 8590 */ 8591 public void dispatchProvideStructure(ViewStructure structure) { 8592 dispatchProvideStructureForAssistOrAutofill(structure, false, 0); 8593 } 8594 8595 /** 8596 * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy, 8597 * when an Assist structure is being created as part of an autofill request. 8598 * 8599 * <p>The default implementation does the following: 8600 * <ul> 8601 * <li>Sets the {@link AutofillId} in the structure. 8602 * <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}. 8603 * <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}. 8604 * </ul> 8605 * 8606 * <p>Typically, this method should only be overridden by subclasses that provide a view 8607 * hierarchy (such as {@link ViewGroup}) - other classes should override 8608 * {@link #onProvideAutofillStructure(ViewStructure, int)} or 8609 * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead. 8610 * 8611 * <p>When overridden, it must: 8612 * 8613 * <ul> 8614 * <li>Either call 8615 * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly 8616 * set the {@link AutofillId} in the structure (for example, by calling 8617 * {@code structure.setAutofillId(getAutofillId())}). 8618 * <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when 8619 * set, all views in the structure should be considered important for autofill, 8620 * regardless of what {@link #isImportantForAutofill()} returns. We encourage you to 8621 * respect this flag to provide a better user experience - this flag is typically used 8622 * when an user explicitly requested autofill. If the flag is not set, 8623 * then only views marked as important for autofill should be included in the 8624 * structure - skipping non-important views optimizes the overall autofill performance. 8625 * </ul> 8626 * 8627 * @param structure fill in with structured view data for autofill purposes. 8628 * @param flags optional flags. 8629 * 8630 * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 8631 */ 8632 public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure, 8633 @AutofillFlags int flags) { 8634 dispatchProvideStructureForAssistOrAutofill(structure, true, flags); 8635 } 8636 8637 private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure, 8638 boolean forAutofill, @AutofillFlags int flags) { 8639 if (forAutofill) { 8640 structure.setAutofillId(getAutofillId()); 8641 onProvideAutofillStructure(structure, flags); 8642 onProvideAutofillVirtualStructure(structure, flags); 8643 } else if (!isAssistBlocked()) { 8644 onProvideStructure(structure); 8645 onProvideVirtualStructure(structure); 8646 } else { 8647 structure.setClassName(getAccessibilityClassName().toString()); 8648 structure.setAssistBlocked(true); 8649 } 8650 } 8651 8652 /** 8653 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 8654 * 8655 * Note: Called from the default {@link AccessibilityDelegate}. 8656 * 8657 * @hide 8658 */ 8659 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 8660 if (mAttachInfo == null) { 8661 return; 8662 } 8663 8664 Rect bounds = mAttachInfo.mTmpInvalRect; 8665 8666 getDrawingRect(bounds); 8667 info.setBoundsInParent(bounds); 8668 8669 getBoundsOnScreen(bounds, true); 8670 info.setBoundsInScreen(bounds); 8671 8672 ViewParent parent = getParentForAccessibility(); 8673 if (parent instanceof View) { 8674 info.setParent((View) parent); 8675 } 8676 8677 if (mID != View.NO_ID) { 8678 View rootView = getRootView(); 8679 if (rootView == null) { 8680 rootView = this; 8681 } 8682 8683 View label = rootView.findLabelForView(this, mID); 8684 if (label != null) { 8685 info.setLabeledBy(label); 8686 } 8687 8688 if ((mAttachInfo.mAccessibilityFetchFlags 8689 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 8690 && Resources.resourceHasPackage(mID)) { 8691 try { 8692 String viewId = getResources().getResourceName(mID); 8693 info.setViewIdResourceName(viewId); 8694 } catch (Resources.NotFoundException nfe) { 8695 /* ignore */ 8696 } 8697 } 8698 } 8699 8700 if (mLabelForId != View.NO_ID) { 8701 View rootView = getRootView(); 8702 if (rootView == null) { 8703 rootView = this; 8704 } 8705 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 8706 if (labeled != null) { 8707 info.setLabelFor(labeled); 8708 } 8709 } 8710 8711 if (mAccessibilityTraversalBeforeId != View.NO_ID) { 8712 View rootView = getRootView(); 8713 if (rootView == null) { 8714 rootView = this; 8715 } 8716 View next = rootView.findViewInsideOutShouldExist(this, 8717 mAccessibilityTraversalBeforeId); 8718 if (next != null && next.includeForAccessibility()) { 8719 info.setTraversalBefore(next); 8720 } 8721 } 8722 8723 if (mAccessibilityTraversalAfterId != View.NO_ID) { 8724 View rootView = getRootView(); 8725 if (rootView == null) { 8726 rootView = this; 8727 } 8728 View next = rootView.findViewInsideOutShouldExist(this, 8729 mAccessibilityTraversalAfterId); 8730 if (next != null && next.includeForAccessibility()) { 8731 info.setTraversalAfter(next); 8732 } 8733 } 8734 8735 info.setVisibleToUser(isVisibleToUser()); 8736 8737 info.setImportantForAccessibility(isImportantForAccessibility()); 8738 info.setPackageName(mContext.getPackageName()); 8739 info.setClassName(getAccessibilityClassName()); 8740 info.setContentDescription(getContentDescription()); 8741 8742 info.setEnabled(isEnabled()); 8743 info.setClickable(isClickable()); 8744 info.setFocusable(isFocusable()); 8745 info.setScreenReaderFocusable(isScreenReaderFocusable()); 8746 info.setFocused(isFocused()); 8747 info.setAccessibilityFocused(isAccessibilityFocused()); 8748 info.setSelected(isSelected()); 8749 info.setLongClickable(isLongClickable()); 8750 info.setContextClickable(isContextClickable()); 8751 info.setLiveRegion(getAccessibilityLiveRegion()); 8752 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) { 8753 info.setTooltipText(mTooltipInfo.mTooltipText); 8754 info.addAction((mTooltipInfo.mTooltipPopup == null) 8755 ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP 8756 : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP); 8757 } 8758 8759 // TODO: These make sense only if we are in an AdapterView but all 8760 // views can be selected. Maybe from accessibility perspective 8761 // we should report as selectable view in an AdapterView. 8762 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 8763 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 8764 8765 if (isFocusable()) { 8766 if (isFocused()) { 8767 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 8768 } else { 8769 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 8770 } 8771 } 8772 8773 if (!isAccessibilityFocused()) { 8774 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 8775 } else { 8776 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 8777 } 8778 8779 if (isClickable() && isEnabled()) { 8780 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 8781 } 8782 8783 if (isLongClickable() && isEnabled()) { 8784 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 8785 } 8786 8787 if (isContextClickable() && isEnabled()) { 8788 info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK); 8789 } 8790 8791 CharSequence text = getIterableTextForAccessibility(); 8792 if (text != null && text.length() > 0) { 8793 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 8794 8795 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 8796 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 8797 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 8798 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 8799 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 8800 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 8801 } 8802 8803 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); 8804 populateAccessibilityNodeInfoDrawingOrderInParent(info); 8805 info.setPaneTitle(mAccessibilityPaneTitle); 8806 info.setHeading(isAccessibilityHeading()); 8807 } 8808 8809 /** 8810 * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the 8811 * additional data. 8812 * <p> 8813 * This method only needs overloading if the node is marked as having extra data available. 8814 * </p> 8815 * 8816 * @param info The info to which to add the extra data. Never {@code null}. 8817 * @param extraDataKey A key specifying the type of extra data to add to the info. The 8818 * extra data should be added to the {@link Bundle} returned by 8819 * the info's {@link AccessibilityNodeInfo#getExtras} method. Never 8820 * {@code null}. 8821 * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be 8822 * {@code null} if the service provided no arguments. 8823 * 8824 * @see AccessibilityNodeInfo#setAvailableExtraData(List) 8825 */ 8826 public void addExtraDataToAccessibilityNodeInfo( 8827 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, 8828 @Nullable Bundle arguments) { 8829 } 8830 8831 /** 8832 * Determine the order in which this view will be drawn relative to its siblings for a11y 8833 * 8834 * @param info The info whose drawing order should be populated 8835 */ 8836 private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) { 8837 /* 8838 * If the view's bounds haven't been set yet, layout has not completed. In that situation, 8839 * drawing order may not be well-defined, and some Views with custom drawing order may 8840 * not be initialized sufficiently to respond properly getChildDrawingOrder. 8841 */ 8842 if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) { 8843 info.setDrawingOrder(0); 8844 return; 8845 } 8846 int drawingOrderInParent = 1; 8847 // Iterate up the hierarchy if parents are not important for a11y 8848 View viewAtDrawingLevel = this; 8849 final ViewParent parent = getParentForAccessibility(); 8850 while (viewAtDrawingLevel != parent) { 8851 final ViewParent currentParent = viewAtDrawingLevel.getParent(); 8852 if (!(currentParent instanceof ViewGroup)) { 8853 // Should only happen for the Decor 8854 drawingOrderInParent = 0; 8855 break; 8856 } else { 8857 final ViewGroup parentGroup = (ViewGroup) currentParent; 8858 final int childCount = parentGroup.getChildCount(); 8859 if (childCount > 1) { 8860 List<View> preorderedList = parentGroup.buildOrderedChildList(); 8861 if (preorderedList != null) { 8862 final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel); 8863 for (int i = 0; i < childDrawIndex; i++) { 8864 drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i)); 8865 } 8866 } else { 8867 final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel); 8868 final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled(); 8869 final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup 8870 .getChildDrawingOrder(childCount, childIndex) : childIndex; 8871 final int numChildrenToIterate = customOrder ? childCount : childDrawIndex; 8872 if (childDrawIndex != 0) { 8873 for (int i = 0; i < numChildrenToIterate; i++) { 8874 final int otherDrawIndex = (customOrder ? 8875 parentGroup.getChildDrawingOrder(childCount, i) : i); 8876 if (otherDrawIndex < childDrawIndex) { 8877 drawingOrderInParent += 8878 numViewsForAccessibility(parentGroup.getChildAt(i)); 8879 } 8880 } 8881 } 8882 } 8883 } 8884 } 8885 viewAtDrawingLevel = (View) currentParent; 8886 } 8887 info.setDrawingOrder(drawingOrderInParent); 8888 } 8889 8890 private static int numViewsForAccessibility(View view) { 8891 if (view != null) { 8892 if (view.includeForAccessibility()) { 8893 return 1; 8894 } else if (view instanceof ViewGroup) { 8895 return ((ViewGroup) view).getNumChildrenForAccessibility(); 8896 } 8897 } 8898 return 0; 8899 } 8900 8901 private View findLabelForView(View view, int labeledId) { 8902 if (mMatchLabelForPredicate == null) { 8903 mMatchLabelForPredicate = new MatchLabelForPredicate(); 8904 } 8905 mMatchLabelForPredicate.mLabeledId = labeledId; 8906 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 8907 } 8908 8909 /** 8910 * Computes whether this virtual autofill view is visible to the user. 8911 * 8912 * <p><b>Note: </b>By default it returns {@code true}, but views providing a virtual hierarchy 8913 * view must override it. 8914 * 8915 * @return Whether the view is visible on the screen. 8916 */ 8917 public boolean isVisibleToUserForAutofill(int virtualId) { 8918 if (mContext.isAutofillCompatibilityEnabled()) { 8919 final AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 8920 if (provider != null) { 8921 final AccessibilityNodeInfo node = provider.createAccessibilityNodeInfo(virtualId); 8922 if (node != null) { 8923 return node.isVisibleToUser(); 8924 } 8925 // if node is null, assume it's not visible anymore 8926 } else { 8927 Log.w(VIEW_LOG_TAG, "isVisibleToUserForAutofill(" + virtualId + "): no provider"); 8928 } 8929 return false; 8930 } 8931 return true; 8932 } 8933 8934 /** 8935 * Computes whether this view is visible to the user. Such a view is 8936 * attached, visible, all its predecessors are visible, it is not clipped 8937 * entirely by its predecessors, and has an alpha greater than zero. 8938 * 8939 * @return Whether the view is visible on the screen. 8940 * 8941 * @hide 8942 */ 8943 public boolean isVisibleToUser() { 8944 return isVisibleToUser(null); 8945 } 8946 8947 /** 8948 * Computes whether the given portion of this view is visible to the user. 8949 * Such a view is attached, visible, all its predecessors are visible, 8950 * has an alpha greater than zero, and the specified portion is not 8951 * clipped entirely by its predecessors. 8952 * 8953 * @param boundInView the portion of the view to test; coordinates should be relative; may be 8954 * <code>null</code>, and the entire view will be tested in this case. 8955 * When <code>true</code> is returned by the function, the actual visible 8956 * region will be stored in this parameter; that is, if boundInView is fully 8957 * contained within the view, no modification will be made, otherwise regions 8958 * outside of the visible area of the view will be clipped. 8959 * 8960 * @return Whether the specified portion of the view is visible on the screen. 8961 * 8962 * @hide 8963 */ 8964 protected boolean isVisibleToUser(Rect boundInView) { 8965 if (mAttachInfo != null) { 8966 // Attached to invisible window means this view is not visible. 8967 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 8968 return false; 8969 } 8970 // An invisible predecessor or one with alpha zero means 8971 // that this view is not visible to the user. 8972 Object current = this; 8973 while (current instanceof View) { 8974 View view = (View) current; 8975 // We have attach info so this view is attached and there is no 8976 // need to check whether we reach to ViewRootImpl on the way up. 8977 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 8978 view.getVisibility() != VISIBLE) { 8979 return false; 8980 } 8981 current = view.mParent; 8982 } 8983 // Check if the view is entirely covered by its predecessors. 8984 Rect visibleRect = mAttachInfo.mTmpInvalRect; 8985 Point offset = mAttachInfo.mPoint; 8986 if (!getGlobalVisibleRect(visibleRect, offset)) { 8987 return false; 8988 } 8989 // Check if the visible portion intersects the rectangle of interest. 8990 if (boundInView != null) { 8991 visibleRect.offset(-offset.x, -offset.y); 8992 return boundInView.intersect(visibleRect); 8993 } 8994 return true; 8995 } 8996 return false; 8997 } 8998 8999 /** 9000 * Returns the delegate for implementing accessibility support via 9001 * composition. For more details see {@link AccessibilityDelegate}. 9002 * 9003 * @return The delegate, or null if none set. 9004 * 9005 * @hide 9006 */ 9007 public AccessibilityDelegate getAccessibilityDelegate() { 9008 return mAccessibilityDelegate; 9009 } 9010 9011 /** 9012 * Sets a delegate for implementing accessibility support via composition 9013 * (as opposed to inheritance). For more details, see 9014 * {@link AccessibilityDelegate}. 9015 * <p> 9016 * <strong>Note:</strong> On platform versions prior to 9017 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 9018 * views in the {@code android.widget.*} package are called <i>before</i> 9019 * host methods. This prevents certain properties such as class name from 9020 * being modified by overriding 9021 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 9022 * as any changes will be overwritten by the host class. 9023 * <p> 9024 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 9025 * methods are called <i>after</i> host methods, which all properties to be 9026 * modified without being overwritten by the host class. 9027 * 9028 * @param delegate the object to which accessibility method calls should be 9029 * delegated 9030 * @see AccessibilityDelegate 9031 */ 9032 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) { 9033 mAccessibilityDelegate = delegate; 9034 } 9035 9036 /** 9037 * Gets the provider for managing a virtual view hierarchy rooted at this View 9038 * and reported to {@link android.accessibilityservice.AccessibilityService}s 9039 * that explore the window content. 9040 * <p> 9041 * If this method returns an instance, this instance is responsible for managing 9042 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 9043 * View including the one representing the View itself. Similarly the returned 9044 * instance is responsible for performing accessibility actions on any virtual 9045 * view or the root view itself. 9046 * </p> 9047 * <p> 9048 * If an {@link AccessibilityDelegate} has been specified via calling 9049 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 9050 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 9051 * is responsible for handling this call. 9052 * </p> 9053 * 9054 * @return The provider. 9055 * 9056 * @see AccessibilityNodeProvider 9057 */ 9058 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 9059 if (mAccessibilityDelegate != null) { 9060 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 9061 } else { 9062 return null; 9063 } 9064 } 9065 9066 /** 9067 * Gets the unique identifier of this view on the screen for accessibility purposes. 9068 * 9069 * @return The view accessibility id. 9070 * 9071 * @hide 9072 */ 9073 public int getAccessibilityViewId() { 9074 if (mAccessibilityViewId == NO_ID) { 9075 mAccessibilityViewId = sNextAccessibilityViewId++; 9076 } 9077 return mAccessibilityViewId; 9078 } 9079 9080 /** 9081 * Gets the unique identifier of this view on the screen for autofill purposes. 9082 * 9083 * @return The view autofill id. 9084 * 9085 * @hide 9086 */ 9087 public int getAutofillViewId() { 9088 if (mAutofillViewId == NO_ID) { 9089 mAutofillViewId = mContext.getNextAutofillId(); 9090 } 9091 return mAutofillViewId; 9092 } 9093 9094 /** 9095 * Gets the unique identifier of the window in which this View reseides. 9096 * 9097 * @return The window accessibility id. 9098 * 9099 * @hide 9100 */ 9101 public int getAccessibilityWindowId() { 9102 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId 9103 : AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 9104 } 9105 9106 /** 9107 * Returns the {@link View}'s content description. 9108 * <p> 9109 * <strong>Note:</strong> Do not override this method, as it will have no 9110 * effect on the content description presented to accessibility services. 9111 * You must call {@link #setContentDescription(CharSequence)} to modify the 9112 * content description. 9113 * 9114 * @return the content description 9115 * @see #setContentDescription(CharSequence) 9116 * @attr ref android.R.styleable#View_contentDescription 9117 */ 9118 @ViewDebug.ExportedProperty(category = "accessibility") 9119 public CharSequence getContentDescription() { 9120 return mContentDescription; 9121 } 9122 9123 /** 9124 * Sets the {@link View}'s content description. 9125 * <p> 9126 * A content description briefly describes the view and is primarily used 9127 * for accessibility support to determine how a view should be presented to 9128 * the user. In the case of a view with no textual representation, such as 9129 * {@link android.widget.ImageButton}, a useful content description 9130 * explains what the view does. For example, an image button with a phone 9131 * icon that is used to place a call may use "Call" as its content 9132 * description. An image of a floppy disk that is used to save a file may 9133 * use "Save". 9134 * 9135 * @param contentDescription The content description. 9136 * @see #getContentDescription() 9137 * @attr ref android.R.styleable#View_contentDescription 9138 */ 9139 @RemotableViewMethod 9140 public void setContentDescription(CharSequence contentDescription) { 9141 if (mContentDescription == null) { 9142 if (contentDescription == null) { 9143 return; 9144 } 9145 } else if (mContentDescription.equals(contentDescription)) { 9146 return; 9147 } 9148 mContentDescription = contentDescription; 9149 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 9150 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 9151 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 9152 notifySubtreeAccessibilityStateChangedIfNeeded(); 9153 } else { 9154 notifyViewAccessibilityStateChangedIfNeeded( 9155 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 9156 } 9157 } 9158 9159 /** 9160 * Sets the id of a view before which this one is visited in accessibility traversal. 9161 * A screen-reader must visit the content of this view before the content of the one 9162 * it precedes. For example, if view B is set to be before view A, then a screen-reader 9163 * will traverse the entire content of B before traversing the entire content of A, 9164 * regardles of what traversal strategy it is using. 9165 * <p> 9166 * Views that do not have specified before/after relationships are traversed in order 9167 * determined by the screen-reader. 9168 * </p> 9169 * <p> 9170 * Setting that this view is before a view that is not important for accessibility 9171 * or if this view is not important for accessibility will have no effect as the 9172 * screen-reader is not aware of unimportant views. 9173 * </p> 9174 * 9175 * @param beforeId The id of a view this one precedes in accessibility traversal. 9176 * 9177 * @attr ref android.R.styleable#View_accessibilityTraversalBefore 9178 * 9179 * @see #setImportantForAccessibility(int) 9180 */ 9181 @RemotableViewMethod 9182 public void setAccessibilityTraversalBefore(int beforeId) { 9183 if (mAccessibilityTraversalBeforeId == beforeId) { 9184 return; 9185 } 9186 mAccessibilityTraversalBeforeId = beforeId; 9187 notifyViewAccessibilityStateChangedIfNeeded( 9188 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9189 } 9190 9191 /** 9192 * Gets the id of a view before which this one is visited in accessibility traversal. 9193 * 9194 * @return The id of a view this one precedes in accessibility traversal if 9195 * specified, otherwise {@link #NO_ID}. 9196 * 9197 * @see #setAccessibilityTraversalBefore(int) 9198 */ 9199 public int getAccessibilityTraversalBefore() { 9200 return mAccessibilityTraversalBeforeId; 9201 } 9202 9203 /** 9204 * Sets the id of a view after which this one is visited in accessibility traversal. 9205 * A screen-reader must visit the content of the other view before the content of this 9206 * one. For example, if view B is set to be after view A, then a screen-reader 9207 * will traverse the entire content of A before traversing the entire content of B, 9208 * regardles of what traversal strategy it is using. 9209 * <p> 9210 * Views that do not have specified before/after relationships are traversed in order 9211 * determined by the screen-reader. 9212 * </p> 9213 * <p> 9214 * Setting that this view is after a view that is not important for accessibility 9215 * or if this view is not important for accessibility will have no effect as the 9216 * screen-reader is not aware of unimportant views. 9217 * </p> 9218 * 9219 * @param afterId The id of a view this one succedees in accessibility traversal. 9220 * 9221 * @attr ref android.R.styleable#View_accessibilityTraversalAfter 9222 * 9223 * @see #setImportantForAccessibility(int) 9224 */ 9225 @RemotableViewMethod 9226 public void setAccessibilityTraversalAfter(int afterId) { 9227 if (mAccessibilityTraversalAfterId == afterId) { 9228 return; 9229 } 9230 mAccessibilityTraversalAfterId = afterId; 9231 notifyViewAccessibilityStateChangedIfNeeded( 9232 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9233 } 9234 9235 /** 9236 * Gets the id of a view after which this one is visited in accessibility traversal. 9237 * 9238 * @return The id of a view this one succeedes in accessibility traversal if 9239 * specified, otherwise {@link #NO_ID}. 9240 * 9241 * @see #setAccessibilityTraversalAfter(int) 9242 */ 9243 public int getAccessibilityTraversalAfter() { 9244 return mAccessibilityTraversalAfterId; 9245 } 9246 9247 /** 9248 * Gets the id of a view for which this view serves as a label for 9249 * accessibility purposes. 9250 * 9251 * @return The labeled view id. 9252 */ 9253 @ViewDebug.ExportedProperty(category = "accessibility") 9254 public int getLabelFor() { 9255 return mLabelForId; 9256 } 9257 9258 /** 9259 * Sets the id of a view for which this view serves as a label for 9260 * accessibility purposes. 9261 * 9262 * @param id The labeled view id. 9263 */ 9264 @RemotableViewMethod 9265 public void setLabelFor(@IdRes int id) { 9266 if (mLabelForId == id) { 9267 return; 9268 } 9269 mLabelForId = id; 9270 if (mLabelForId != View.NO_ID 9271 && mID == View.NO_ID) { 9272 mID = generateViewId(); 9273 } 9274 notifyViewAccessibilityStateChangedIfNeeded( 9275 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9276 } 9277 9278 /** 9279 * Invoked whenever this view loses focus, either by losing window focus or by losing 9280 * focus within its window. This method can be used to clear any state tied to the 9281 * focus. For instance, if a button is held pressed with the trackball and the window 9282 * loses focus, this method can be used to cancel the press. 9283 * 9284 * Subclasses of View overriding this method should always call super.onFocusLost(). 9285 * 9286 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 9287 * @see #onWindowFocusChanged(boolean) 9288 * 9289 * @hide pending API council approval 9290 */ 9291 @CallSuper 9292 protected void onFocusLost() { 9293 resetPressedState(); 9294 } 9295 9296 private void resetPressedState() { 9297 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 9298 return; 9299 } 9300 9301 if (isPressed()) { 9302 setPressed(false); 9303 9304 if (!mHasPerformedLongPress) { 9305 removeLongPressCallback(); 9306 } 9307 } 9308 } 9309 9310 /** 9311 * Returns true if this view has focus 9312 * 9313 * @return True if this view has focus, false otherwise. 9314 */ 9315 @ViewDebug.ExportedProperty(category = "focus") 9316 public boolean isFocused() { 9317 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 9318 } 9319 9320 /** 9321 * Find the view in the hierarchy rooted at this view that currently has 9322 * focus. 9323 * 9324 * @return The view that currently has focus, or null if no focused view can 9325 * be found. 9326 */ 9327 public View findFocus() { 9328 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 9329 } 9330 9331 /** 9332 * Indicates whether this view is one of the set of scrollable containers in 9333 * its window. 9334 * 9335 * @return whether this view is one of the set of scrollable containers in 9336 * its window 9337 * 9338 * @attr ref android.R.styleable#View_isScrollContainer 9339 */ 9340 public boolean isScrollContainer() { 9341 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 9342 } 9343 9344 /** 9345 * Change whether this view is one of the set of scrollable containers in 9346 * its window. This will be used to determine whether the window can 9347 * resize or must pan when a soft input area is open -- scrollable 9348 * containers allow the window to use resize mode since the container 9349 * will appropriately shrink. 9350 * 9351 * @attr ref android.R.styleable#View_isScrollContainer 9352 */ 9353 public void setScrollContainer(boolean isScrollContainer) { 9354 if (isScrollContainer) { 9355 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 9356 mAttachInfo.mScrollContainers.add(this); 9357 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 9358 } 9359 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 9360 } else { 9361 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 9362 mAttachInfo.mScrollContainers.remove(this); 9363 } 9364 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 9365 } 9366 } 9367 9368 /** 9369 * Returns the quality of the drawing cache. 9370 * 9371 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 9372 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 9373 * 9374 * @see #setDrawingCacheQuality(int) 9375 * @see #setDrawingCacheEnabled(boolean) 9376 * @see #isDrawingCacheEnabled() 9377 * 9378 * @attr ref android.R.styleable#View_drawingCacheQuality 9379 * 9380 * @deprecated The view drawing cache was largely made obsolete with the introduction of 9381 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 9382 * layers are largely unnecessary and can easily result in a net loss in performance due to the 9383 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 9384 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 9385 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 9386 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 9387 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 9388 * software-rendered usages are discouraged and have compatibility issues with hardware-only 9389 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 9390 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 9391 * reports or unit testing the {@link PixelCopy} API is recommended. 9392 */ 9393 @Deprecated 9394 @DrawingCacheQuality 9395 public int getDrawingCacheQuality() { 9396 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 9397 } 9398 9399 /** 9400 * Set the drawing cache quality of this view. This value is used only when the 9401 * drawing cache is enabled 9402 * 9403 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 9404 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 9405 * 9406 * @see #getDrawingCacheQuality() 9407 * @see #setDrawingCacheEnabled(boolean) 9408 * @see #isDrawingCacheEnabled() 9409 * 9410 * @attr ref android.R.styleable#View_drawingCacheQuality 9411 * 9412 * @deprecated The view drawing cache was largely made obsolete with the introduction of 9413 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 9414 * layers are largely unnecessary and can easily result in a net loss in performance due to the 9415 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 9416 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 9417 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 9418 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 9419 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 9420 * software-rendered usages are discouraged and have compatibility issues with hardware-only 9421 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 9422 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 9423 * reports or unit testing the {@link PixelCopy} API is recommended. 9424 */ 9425 @Deprecated 9426 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) { 9427 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 9428 } 9429 9430 /** 9431 * Returns whether the screen should remain on, corresponding to the current 9432 * value of {@link #KEEP_SCREEN_ON}. 9433 * 9434 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 9435 * 9436 * @see #setKeepScreenOn(boolean) 9437 * 9438 * @attr ref android.R.styleable#View_keepScreenOn 9439 */ 9440 public boolean getKeepScreenOn() { 9441 return (mViewFlags & KEEP_SCREEN_ON) != 0; 9442 } 9443 9444 /** 9445 * Controls whether the screen should remain on, modifying the 9446 * value of {@link #KEEP_SCREEN_ON}. 9447 * 9448 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 9449 * 9450 * @see #getKeepScreenOn() 9451 * 9452 * @attr ref android.R.styleable#View_keepScreenOn 9453 */ 9454 public void setKeepScreenOn(boolean keepScreenOn) { 9455 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 9456 } 9457 9458 /** 9459 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 9460 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 9461 * 9462 * @attr ref android.R.styleable#View_nextFocusLeft 9463 */ 9464 public int getNextFocusLeftId() { 9465 return mNextFocusLeftId; 9466 } 9467 9468 /** 9469 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 9470 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 9471 * decide automatically. 9472 * 9473 * @attr ref android.R.styleable#View_nextFocusLeft 9474 */ 9475 public void setNextFocusLeftId(int nextFocusLeftId) { 9476 mNextFocusLeftId = nextFocusLeftId; 9477 } 9478 9479 /** 9480 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 9481 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 9482 * 9483 * @attr ref android.R.styleable#View_nextFocusRight 9484 */ 9485 public int getNextFocusRightId() { 9486 return mNextFocusRightId; 9487 } 9488 9489 /** 9490 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 9491 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 9492 * decide automatically. 9493 * 9494 * @attr ref android.R.styleable#View_nextFocusRight 9495 */ 9496 public void setNextFocusRightId(int nextFocusRightId) { 9497 mNextFocusRightId = nextFocusRightId; 9498 } 9499 9500 /** 9501 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 9502 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 9503 * 9504 * @attr ref android.R.styleable#View_nextFocusUp 9505 */ 9506 public int getNextFocusUpId() { 9507 return mNextFocusUpId; 9508 } 9509 9510 /** 9511 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 9512 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 9513 * decide automatically. 9514 * 9515 * @attr ref android.R.styleable#View_nextFocusUp 9516 */ 9517 public void setNextFocusUpId(int nextFocusUpId) { 9518 mNextFocusUpId = nextFocusUpId; 9519 } 9520 9521 /** 9522 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 9523 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 9524 * 9525 * @attr ref android.R.styleable#View_nextFocusDown 9526 */ 9527 public int getNextFocusDownId() { 9528 return mNextFocusDownId; 9529 } 9530 9531 /** 9532 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 9533 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 9534 * decide automatically. 9535 * 9536 * @attr ref android.R.styleable#View_nextFocusDown 9537 */ 9538 public void setNextFocusDownId(int nextFocusDownId) { 9539 mNextFocusDownId = nextFocusDownId; 9540 } 9541 9542 /** 9543 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 9544 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 9545 * 9546 * @attr ref android.R.styleable#View_nextFocusForward 9547 */ 9548 public int getNextFocusForwardId() { 9549 return mNextFocusForwardId; 9550 } 9551 9552 /** 9553 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 9554 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 9555 * decide automatically. 9556 * 9557 * @attr ref android.R.styleable#View_nextFocusForward 9558 */ 9559 public void setNextFocusForwardId(int nextFocusForwardId) { 9560 mNextFocusForwardId = nextFocusForwardId; 9561 } 9562 9563 /** 9564 * Gets the id of the root of the next keyboard navigation cluster. 9565 * @return The next keyboard navigation cluster ID, or {@link #NO_ID} if the framework should 9566 * decide automatically. 9567 * 9568 * @attr ref android.R.styleable#View_nextClusterForward 9569 */ 9570 public int getNextClusterForwardId() { 9571 return mNextClusterForwardId; 9572 } 9573 9574 /** 9575 * Sets the id of the view to use as the root of the next keyboard navigation cluster. 9576 * @param nextClusterForwardId The next cluster ID, or {@link #NO_ID} if the framework should 9577 * decide automatically. 9578 * 9579 * @attr ref android.R.styleable#View_nextClusterForward 9580 */ 9581 public void setNextClusterForwardId(int nextClusterForwardId) { 9582 mNextClusterForwardId = nextClusterForwardId; 9583 } 9584 9585 /** 9586 * Returns the visibility of this view and all of its ancestors 9587 * 9588 * @return True if this view and all of its ancestors are {@link #VISIBLE} 9589 */ 9590 public boolean isShown() { 9591 View current = this; 9592 //noinspection ConstantConditions 9593 do { 9594 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 9595 return false; 9596 } 9597 ViewParent parent = current.mParent; 9598 if (parent == null) { 9599 return false; // We are not attached to the view root 9600 } 9601 if (!(parent instanceof View)) { 9602 return true; 9603 } 9604 current = (View) parent; 9605 } while (current != null); 9606 9607 return false; 9608 } 9609 9610 /** 9611 * Called by the view hierarchy when the content insets for a window have 9612 * changed, to allow it to adjust its content to fit within those windows. 9613 * The content insets tell you the space that the status bar, input method, 9614 * and other system windows infringe on the application's window. 9615 * 9616 * <p>You do not normally need to deal with this function, since the default 9617 * window decoration given to applications takes care of applying it to the 9618 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 9619 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 9620 * and your content can be placed under those system elements. You can then 9621 * use this method within your view hierarchy if you have parts of your UI 9622 * which you would like to ensure are not being covered. 9623 * 9624 * <p>The default implementation of this method simply applies the content 9625 * insets to the view's padding, consuming that content (modifying the 9626 * insets to be 0), and returning true. This behavior is off by default, but can 9627 * be enabled through {@link #setFitsSystemWindows(boolean)}. 9628 * 9629 * <p>This function's traversal down the hierarchy is depth-first. The same content 9630 * insets object is propagated down the hierarchy, so any changes made to it will 9631 * be seen by all following views (including potentially ones above in 9632 * the hierarchy since this is a depth-first traversal). The first view 9633 * that returns true will abort the entire traversal. 9634 * 9635 * <p>The default implementation works well for a situation where it is 9636 * used with a container that covers the entire window, allowing it to 9637 * apply the appropriate insets to its content on all edges. If you need 9638 * a more complicated layout (such as two different views fitting system 9639 * windows, one on the top of the window, and one on the bottom), 9640 * you can override the method and handle the insets however you would like. 9641 * Note that the insets provided by the framework are always relative to the 9642 * far edges of the window, not accounting for the location of the called view 9643 * within that window. (In fact when this method is called you do not yet know 9644 * where the layout will place the view, as it is done before layout happens.) 9645 * 9646 * <p>Note: unlike many View methods, there is no dispatch phase to this 9647 * call. If you are overriding it in a ViewGroup and want to allow the 9648 * call to continue to your children, you must be sure to call the super 9649 * implementation. 9650 * 9651 * <p>Here is a sample layout that makes use of fitting system windows 9652 * to have controls for a video view placed inside of the window decorations 9653 * that it hides and shows. This can be used with code like the second 9654 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 9655 * 9656 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 9657 * 9658 * @param insets Current content insets of the window. Prior to 9659 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 9660 * the insets or else you and Android will be unhappy. 9661 * 9662 * @return {@code true} if this view applied the insets and it should not 9663 * continue propagating further down the hierarchy, {@code false} otherwise. 9664 * @see #getFitsSystemWindows() 9665 * @see #setFitsSystemWindows(boolean) 9666 * @see #setSystemUiVisibility(int) 9667 * 9668 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply 9669 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use 9670 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)} 9671 * to implement handling their own insets. 9672 */ 9673 @Deprecated 9674 protected boolean fitSystemWindows(Rect insets) { 9675 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) { 9676 if (insets == null) { 9677 // Null insets by definition have already been consumed. 9678 // This call cannot apply insets since there are none to apply, 9679 // so return false. 9680 return false; 9681 } 9682 // If we're not in the process of dispatching the newer apply insets call, 9683 // that means we're not in the compatibility path. Dispatch into the newer 9684 // apply insets path and take things from there. 9685 try { 9686 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS; 9687 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed(); 9688 } finally { 9689 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS; 9690 } 9691 } else { 9692 // We're being called from the newer apply insets path. 9693 // Perform the standard fallback behavior. 9694 return fitSystemWindowsInt(insets); 9695 } 9696 } 9697 9698 private boolean fitSystemWindowsInt(Rect insets) { 9699 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 9700 mUserPaddingStart = UNDEFINED_PADDING; 9701 mUserPaddingEnd = UNDEFINED_PADDING; 9702 Rect localInsets = sThreadLocal.get(); 9703 if (localInsets == null) { 9704 localInsets = new Rect(); 9705 sThreadLocal.set(localInsets); 9706 } 9707 boolean res = computeFitSystemWindows(insets, localInsets); 9708 mUserPaddingLeftInitial = localInsets.left; 9709 mUserPaddingRightInitial = localInsets.right; 9710 internalSetPadding(localInsets.left, localInsets.top, 9711 localInsets.right, localInsets.bottom); 9712 return res; 9713 } 9714 return false; 9715 } 9716 9717 /** 9718 * Called when the view should apply {@link WindowInsets} according to its internal policy. 9719 * 9720 * <p>This method should be overridden by views that wish to apply a policy different from or 9721 * in addition to the default behavior. Clients that wish to force a view subtree 9722 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p> 9723 * 9724 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set 9725 * it will be called during dispatch instead of this method. The listener may optionally 9726 * call this method from its own implementation if it wishes to apply the view's default 9727 * insets policy in addition to its own.</p> 9728 * 9729 * <p>Implementations of this method should either return the insets parameter unchanged 9730 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed 9731 * that this view applied itself. This allows new inset types added in future platform 9732 * versions to pass through existing implementations unchanged without being erroneously 9733 * consumed.</p> 9734 * 9735 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows} 9736 * property is set then the view will consume the system window insets and apply them 9737 * as padding for the view.</p> 9738 * 9739 * @param insets Insets to apply 9740 * @return The supplied insets with any applied insets consumed 9741 */ 9742 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 9743 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) { 9744 // We weren't called from within a direct call to fitSystemWindows, 9745 // call into it as a fallback in case we're in a class that overrides it 9746 // and has logic to perform. 9747 if (fitSystemWindows(insets.getSystemWindowInsets())) { 9748 return insets.consumeSystemWindowInsets(); 9749 } 9750 } else { 9751 // We were called from within a direct call to fitSystemWindows. 9752 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) { 9753 return insets.consumeSystemWindowInsets(); 9754 } 9755 } 9756 return insets; 9757 } 9758 9759 /** 9760 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying 9761 * window insets to this view. The listener's 9762 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 9763 * method will be called instead of the view's 9764 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 9765 * 9766 * @param listener Listener to set 9767 * 9768 * @see #onApplyWindowInsets(WindowInsets) 9769 */ 9770 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) { 9771 getListenerInfo().mOnApplyWindowInsetsListener = listener; 9772 } 9773 9774 /** 9775 * Request to apply the given window insets to this view or another view in its subtree. 9776 * 9777 * <p>This method should be called by clients wishing to apply insets corresponding to areas 9778 * obscured by window decorations or overlays. This can include the status and navigation bars, 9779 * action bars, input methods and more. New inset categories may be added in the future. 9780 * The method returns the insets provided minus any that were applied by this view or its 9781 * children.</p> 9782 * 9783 * <p>Clients wishing to provide custom behavior should override the 9784 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a 9785 * {@link OnApplyWindowInsetsListener} via the 9786 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener} 9787 * method.</p> 9788 * 9789 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method. 9790 * </p> 9791 * 9792 * @param insets Insets to apply 9793 * @return The provided insets minus the insets that were consumed 9794 */ 9795 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { 9796 try { 9797 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS; 9798 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) { 9799 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets); 9800 } else { 9801 return onApplyWindowInsets(insets); 9802 } 9803 } finally { 9804 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS; 9805 } 9806 } 9807 9808 /** 9809 * Compute the view's coordinate within the surface. 9810 * 9811 * <p>Computes the coordinates of this view in its surface. The argument 9812 * must be an array of two integers. After the method returns, the array 9813 * contains the x and y location in that order.</p> 9814 * @hide 9815 * @param location an array of two integers in which to hold the coordinates 9816 */ 9817 public void getLocationInSurface(@Size(2) int[] location) { 9818 getLocationInWindow(location); 9819 if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) { 9820 location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left; 9821 location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top; 9822 } 9823 } 9824 9825 /** 9826 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are 9827 * only available if the view is attached. 9828 * 9829 * @return WindowInsets from the top of the view hierarchy or null if View is detached 9830 */ 9831 public WindowInsets getRootWindowInsets() { 9832 if (mAttachInfo != null) { 9833 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */); 9834 } 9835 return null; 9836 } 9837 9838 /** 9839 * @hide Compute the insets that should be consumed by this view and the ones 9840 * that should propagate to those under it. 9841 * 9842 * Note: This is used by appcompat's ActionBarOverlayLayout through reflection. 9843 * 9844 * @param inoutInsets the insets given to this view 9845 * @param outLocalInsets the insets that should be applied to this view 9846 * @deprecated use {@link #computeSystemWindowInsets} 9847 * @return 9848 */ 9849 @Deprecated 9850 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 9851 WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets), 9852 outLocalInsets); 9853 inoutInsets.set(innerInsets.getSystemWindowInsets()); 9854 return innerInsets.isSystemWindowInsetsConsumed(); 9855 } 9856 9857 /** 9858 * Compute insets that should be consumed by this view and the ones that should propagate 9859 * to those under it. 9860 * 9861 * @param in Insets currently being processed by this View, likely received as a parameter 9862 * to {@link #onApplyWindowInsets(WindowInsets)}. 9863 * @param outLocalInsets A Rect that will receive the insets that should be consumed 9864 * by this view 9865 * @return Insets that should be passed along to views under this one 9866 */ 9867 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) { 9868 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 9869 || mAttachInfo == null 9870 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 9871 && !mAttachInfo.mOverscanRequested)) { 9872 outLocalInsets.set(in.getSystemWindowInsets()); 9873 return in.consumeSystemWindowInsets().inset(outLocalInsets); 9874 } else { 9875 // The application wants to take care of fitting system window for 9876 // the content... however we still need to take care of any overscan here. 9877 final Rect overscan = mAttachInfo.mOverscanInsets; 9878 outLocalInsets.set(overscan); 9879 return in.inset(outLocalInsets); 9880 } 9881 } 9882 9883 /** 9884 * Sets whether or not this view should account for system screen decorations 9885 * such as the status bar and inset its content; that is, controlling whether 9886 * the default implementation of {@link #fitSystemWindows(Rect)} will be 9887 * executed. See that method for more details. 9888 * 9889 * <p>Note that if you are providing your own implementation of 9890 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 9891 * flag to true -- your implementation will be overriding the default 9892 * implementation that checks this flag. 9893 * 9894 * @param fitSystemWindows If true, then the default implementation of 9895 * {@link #fitSystemWindows(Rect)} will be executed. 9896 * 9897 * @attr ref android.R.styleable#View_fitsSystemWindows 9898 * @see #getFitsSystemWindows() 9899 * @see #fitSystemWindows(Rect) 9900 * @see #setSystemUiVisibility(int) 9901 */ 9902 public void setFitsSystemWindows(boolean fitSystemWindows) { 9903 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 9904 } 9905 9906 /** 9907 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 9908 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 9909 * will be executed. 9910 * 9911 * @return {@code true} if the default implementation of 9912 * {@link #fitSystemWindows(Rect)} will be executed. 9913 * 9914 * @attr ref android.R.styleable#View_fitsSystemWindows 9915 * @see #setFitsSystemWindows(boolean) 9916 * @see #fitSystemWindows(Rect) 9917 * @see #setSystemUiVisibility(int) 9918 */ 9919 @ViewDebug.ExportedProperty 9920 public boolean getFitsSystemWindows() { 9921 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 9922 } 9923 9924 /** @hide */ 9925 public boolean fitsSystemWindows() { 9926 return getFitsSystemWindows(); 9927 } 9928 9929 /** 9930 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 9931 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions. 9932 */ 9933 @Deprecated 9934 public void requestFitSystemWindows() { 9935 if (mParent != null) { 9936 mParent.requestFitSystemWindows(); 9937 } 9938 } 9939 9940 /** 9941 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed. 9942 */ 9943 public void requestApplyInsets() { 9944 requestFitSystemWindows(); 9945 } 9946 9947 /** 9948 * For use by PhoneWindow to make its own system window fitting optional. 9949 * @hide 9950 */ 9951 public void makeOptionalFitsSystemWindows() { 9952 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 9953 } 9954 9955 /** 9956 * Returns the outsets, which areas of the device that aren't a surface, but we would like to 9957 * treat them as such. 9958 * @hide 9959 */ 9960 public void getOutsets(Rect outOutsetRect) { 9961 if (mAttachInfo != null) { 9962 outOutsetRect.set(mAttachInfo.mOutsets); 9963 } else { 9964 outOutsetRect.setEmpty(); 9965 } 9966 } 9967 9968 /** 9969 * Returns the visibility status for this view. 9970 * 9971 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 9972 * @attr ref android.R.styleable#View_visibility 9973 */ 9974 @ViewDebug.ExportedProperty(mapping = { 9975 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 9976 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 9977 @ViewDebug.IntToString(from = GONE, to = "GONE") 9978 }) 9979 @Visibility 9980 public int getVisibility() { 9981 return mViewFlags & VISIBILITY_MASK; 9982 } 9983 9984 /** 9985 * Set the visibility state of this view. 9986 * 9987 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 9988 * @attr ref android.R.styleable#View_visibility 9989 */ 9990 @RemotableViewMethod 9991 public void setVisibility(@Visibility int visibility) { 9992 setFlags(visibility, VISIBILITY_MASK); 9993 } 9994 9995 /** 9996 * Returns the enabled status for this view. The interpretation of the 9997 * enabled state varies by subclass. 9998 * 9999 * @return True if this view is enabled, false otherwise. 10000 */ 10001 @ViewDebug.ExportedProperty 10002 public boolean isEnabled() { 10003 return (mViewFlags & ENABLED_MASK) == ENABLED; 10004 } 10005 10006 /** 10007 * Set the enabled state of this view. The interpretation of the enabled 10008 * state varies by subclass. 10009 * 10010 * @param enabled True if this view is enabled, false otherwise. 10011 */ 10012 @RemotableViewMethod 10013 public void setEnabled(boolean enabled) { 10014 if (enabled == isEnabled()) return; 10015 10016 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 10017 10018 /* 10019 * The View most likely has to change its appearance, so refresh 10020 * the drawable state. 10021 */ 10022 refreshDrawableState(); 10023 10024 // Invalidate too, since the default behavior for views is to be 10025 // be drawn at 50% alpha rather than to change the drawable. 10026 invalidate(true); 10027 10028 if (!enabled) { 10029 cancelPendingInputEvents(); 10030 } 10031 } 10032 10033 /** 10034 * Set whether this view can receive the focus. 10035 * <p> 10036 * Setting this to false will also ensure that this view is not focusable 10037 * in touch mode. 10038 * 10039 * @param focusable If true, this view can receive the focus. 10040 * 10041 * @see #setFocusableInTouchMode(boolean) 10042 * @see #setFocusable(int) 10043 * @attr ref android.R.styleable#View_focusable 10044 */ 10045 public void setFocusable(boolean focusable) { 10046 setFocusable(focusable ? FOCUSABLE : NOT_FOCUSABLE); 10047 } 10048 10049 /** 10050 * Sets whether this view can receive focus. 10051 * <p> 10052 * Setting this to {@link #FOCUSABLE_AUTO} tells the framework to determine focusability 10053 * automatically based on the view's interactivity. This is the default. 10054 * <p> 10055 * Setting this to NOT_FOCUSABLE will ensure that this view is also not focusable 10056 * in touch mode. 10057 * 10058 * @param focusable One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, 10059 * or {@link #FOCUSABLE_AUTO}. 10060 * @see #setFocusableInTouchMode(boolean) 10061 * @attr ref android.R.styleable#View_focusable 10062 */ 10063 public void setFocusable(@Focusable int focusable) { 10064 if ((focusable & (FOCUSABLE_AUTO | FOCUSABLE)) == 0) { 10065 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 10066 } 10067 setFlags(focusable, FOCUSABLE_MASK); 10068 } 10069 10070 /** 10071 * Set whether this view can receive focus while in touch mode. 10072 * 10073 * Setting this to true will also ensure that this view is focusable. 10074 * 10075 * @param focusableInTouchMode If true, this view can receive the focus while 10076 * in touch mode. 10077 * 10078 * @see #setFocusable(boolean) 10079 * @attr ref android.R.styleable#View_focusableInTouchMode 10080 */ 10081 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 10082 // Focusable in touch mode should always be set before the focusable flag 10083 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 10084 // which, in touch mode, will not successfully request focus on this view 10085 // because the focusable in touch mode flag is not set 10086 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 10087 10088 // Clear FOCUSABLE_AUTO if set. 10089 if (focusableInTouchMode) { 10090 // Clears FOCUSABLE_AUTO if set. 10091 setFlags(FOCUSABLE, FOCUSABLE_MASK); 10092 } 10093 } 10094 10095 /** 10096 * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how 10097 * to autofill the view with the user's data. 10098 * 10099 * <p>Typically, there is only one way to autofill a view, but there could be more than one. 10100 * For example, if the application accepts either an username or email address to identify 10101 * an user. 10102 * 10103 * <p>These hints are not validated by the Android System, but passed "as is" to the service. 10104 * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_} 10105 * constants such as: 10106 * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD}, 10107 * {@link #AUTOFILL_HINT_EMAIL_ADDRESS}, 10108 * {@link #AUTOFILL_HINT_NAME}, 10109 * {@link #AUTOFILL_HINT_PHONE}, 10110 * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE}, 10111 * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}, 10112 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}, 10113 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}, 10114 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or 10115 * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}. 10116 * 10117 * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set. 10118 * @attr ref android.R.styleable#View_autofillHints 10119 */ 10120 public void setAutofillHints(@Nullable String... autofillHints) { 10121 if (autofillHints == null || autofillHints.length == 0) { 10122 mAutofillHints = null; 10123 } else { 10124 mAutofillHints = autofillHints; 10125 } 10126 } 10127 10128 /** 10129 * @hide 10130 */ 10131 @TestApi 10132 public void setAutofilled(boolean isAutofilled) { 10133 boolean wasChanged = isAutofilled != isAutofilled(); 10134 10135 if (wasChanged) { 10136 if (isAutofilled) { 10137 mPrivateFlags3 |= PFLAG3_IS_AUTOFILLED; 10138 } else { 10139 mPrivateFlags3 &= ~PFLAG3_IS_AUTOFILLED; 10140 } 10141 10142 invalidate(); 10143 } 10144 } 10145 10146 /** 10147 * Set whether this view should have sound effects enabled for events such as 10148 * clicking and touching. 10149 * 10150 * <p>You may wish to disable sound effects for a view if you already play sounds, 10151 * for instance, a dial key that plays dtmf tones. 10152 * 10153 * @param soundEffectsEnabled whether sound effects are enabled for this view. 10154 * @see #isSoundEffectsEnabled() 10155 * @see #playSoundEffect(int) 10156 * @attr ref android.R.styleable#View_soundEffectsEnabled 10157 */ 10158 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 10159 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 10160 } 10161 10162 /** 10163 * @return whether this view should have sound effects enabled for events such as 10164 * clicking and touching. 10165 * 10166 * @see #setSoundEffectsEnabled(boolean) 10167 * @see #playSoundEffect(int) 10168 * @attr ref android.R.styleable#View_soundEffectsEnabled 10169 */ 10170 @ViewDebug.ExportedProperty 10171 public boolean isSoundEffectsEnabled() { 10172 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 10173 } 10174 10175 /** 10176 * Set whether this view should have haptic feedback for events such as 10177 * long presses. 10178 * 10179 * <p>You may wish to disable haptic feedback if your view already controls 10180 * its own haptic feedback. 10181 * 10182 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 10183 * @see #isHapticFeedbackEnabled() 10184 * @see #performHapticFeedback(int) 10185 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 10186 */ 10187 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 10188 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 10189 } 10190 10191 /** 10192 * @return whether this view should have haptic feedback enabled for events 10193 * long presses. 10194 * 10195 * @see #setHapticFeedbackEnabled(boolean) 10196 * @see #performHapticFeedback(int) 10197 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 10198 */ 10199 @ViewDebug.ExportedProperty 10200 public boolean isHapticFeedbackEnabled() { 10201 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 10202 } 10203 10204 /** 10205 * Returns the layout direction for this view. 10206 * 10207 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 10208 * {@link #LAYOUT_DIRECTION_RTL}, 10209 * {@link #LAYOUT_DIRECTION_INHERIT} or 10210 * {@link #LAYOUT_DIRECTION_LOCALE}. 10211 * 10212 * @attr ref android.R.styleable#View_layoutDirection 10213 * 10214 * @hide 10215 */ 10216 @ViewDebug.ExportedProperty(category = "layout", mapping = { 10217 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 10218 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 10219 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 10220 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 10221 }) 10222 @LayoutDir 10223 public int getRawLayoutDirection() { 10224 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 10225 } 10226 10227 /** 10228 * Set the layout direction for this view. This will propagate a reset of layout direction 10229 * resolution to the view's children and resolve layout direction for this view. 10230 * 10231 * @param layoutDirection the layout direction to set. Should be one of: 10232 * 10233 * {@link #LAYOUT_DIRECTION_LTR}, 10234 * {@link #LAYOUT_DIRECTION_RTL}, 10235 * {@link #LAYOUT_DIRECTION_INHERIT}, 10236 * {@link #LAYOUT_DIRECTION_LOCALE}. 10237 * 10238 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 10239 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 10240 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 10241 * 10242 * @attr ref android.R.styleable#View_layoutDirection 10243 */ 10244 @RemotableViewMethod 10245 public void setLayoutDirection(@LayoutDir int layoutDirection) { 10246 if (getRawLayoutDirection() != layoutDirection) { 10247 // Reset the current layout direction and the resolved one 10248 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 10249 resetRtlProperties(); 10250 // Set the new layout direction (filtered) 10251 mPrivateFlags2 |= 10252 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 10253 // We need to resolve all RTL properties as they all depend on layout direction 10254 resolveRtlPropertiesIfNeeded(); 10255 requestLayout(); 10256 invalidate(true); 10257 } 10258 } 10259 10260 /** 10261 * Returns the resolved layout direction for this view. 10262 * 10263 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 10264 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 10265 * 10266 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 10267 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 10268 * 10269 * @attr ref android.R.styleable#View_layoutDirection 10270 */ 10271 @ViewDebug.ExportedProperty(category = "layout", mapping = { 10272 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 10273 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 10274 }) 10275 @ResolvedLayoutDir 10276 public int getLayoutDirection() { 10277 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 10278 if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) { 10279 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 10280 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 10281 } 10282 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 10283 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 10284 } 10285 10286 /** 10287 * Indicates whether or not this view's layout is right-to-left. This is resolved from 10288 * layout attribute and/or the inherited value from the parent 10289 * 10290 * @return true if the layout is right-to-left. 10291 * 10292 * @hide 10293 */ 10294 @ViewDebug.ExportedProperty(category = "layout") 10295 public boolean isLayoutRtl() { 10296 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 10297 } 10298 10299 /** 10300 * Indicates whether the view is currently tracking transient state that the 10301 * app should not need to concern itself with saving and restoring, but that 10302 * the framework should take special note to preserve when possible. 10303 * 10304 * <p>A view with transient state cannot be trivially rebound from an external 10305 * data source, such as an adapter binding item views in a list. This may be 10306 * because the view is performing an animation, tracking user selection 10307 * of content, or similar.</p> 10308 * 10309 * @return true if the view has transient state 10310 */ 10311 @ViewDebug.ExportedProperty(category = "layout") 10312 public boolean hasTransientState() { 10313 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 10314 } 10315 10316 /** 10317 * Set whether this view is currently tracking transient state that the 10318 * framework should attempt to preserve when possible. This flag is reference counted, 10319 * so every call to setHasTransientState(true) should be paired with a later call 10320 * to setHasTransientState(false). 10321 * 10322 * <p>A view with transient state cannot be trivially rebound from an external 10323 * data source, such as an adapter binding item views in a list. This may be 10324 * because the view is performing an animation, tracking user selection 10325 * of content, or similar.</p> 10326 * 10327 * @param hasTransientState true if this view has transient state 10328 */ 10329 public void setHasTransientState(boolean hasTransientState) { 10330 final boolean oldHasTransientState = hasTransientState(); 10331 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 10332 mTransientStateCount - 1; 10333 if (mTransientStateCount < 0) { 10334 mTransientStateCount = 0; 10335 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 10336 "unmatched pair of setHasTransientState calls"); 10337 } else if ((hasTransientState && mTransientStateCount == 1) || 10338 (!hasTransientState && mTransientStateCount == 0)) { 10339 // update flag if we've just incremented up from 0 or decremented down to 0 10340 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 10341 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 10342 final boolean newHasTransientState = hasTransientState(); 10343 if (mParent != null && newHasTransientState != oldHasTransientState) { 10344 try { 10345 mParent.childHasTransientStateChanged(this, newHasTransientState); 10346 } catch (AbstractMethodError e) { 10347 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 10348 " does not fully implement ViewParent", e); 10349 } 10350 } 10351 } 10352 } 10353 10354 /** 10355 * Returns true if this view is currently attached to a window. 10356 */ 10357 public boolean isAttachedToWindow() { 10358 return mAttachInfo != null; 10359 } 10360 10361 /** 10362 * Returns true if this view has been through at least one layout since it 10363 * was last attached to or detached from a window. 10364 */ 10365 public boolean isLaidOut() { 10366 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 10367 } 10368 10369 /** 10370 * @return {@code true} if laid-out and not about to do another layout. 10371 */ 10372 boolean isLayoutValid() { 10373 return isLaidOut() && ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == 0); 10374 } 10375 10376 /** 10377 * If this view doesn't do any drawing on its own, set this flag to 10378 * allow further optimizations. By default, this flag is not set on 10379 * View, but could be set on some View subclasses such as ViewGroup. 10380 * 10381 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 10382 * you should clear this flag. 10383 * 10384 * @param willNotDraw whether or not this View draw on its own 10385 */ 10386 public void setWillNotDraw(boolean willNotDraw) { 10387 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 10388 } 10389 10390 /** 10391 * Returns whether or not this View draws on its own. 10392 * 10393 * @return true if this view has nothing to draw, false otherwise 10394 */ 10395 @ViewDebug.ExportedProperty(category = "drawing") 10396 public boolean willNotDraw() { 10397 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 10398 } 10399 10400 /** 10401 * When a View's drawing cache is enabled, drawing is redirected to an 10402 * offscreen bitmap. Some views, like an ImageView, must be able to 10403 * bypass this mechanism if they already draw a single bitmap, to avoid 10404 * unnecessary usage of the memory. 10405 * 10406 * @param willNotCacheDrawing true if this view does not cache its 10407 * drawing, false otherwise 10408 * 10409 * @deprecated The view drawing cache was largely made obsolete with the introduction of 10410 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 10411 * layers are largely unnecessary and can easily result in a net loss in performance due to the 10412 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 10413 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 10414 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 10415 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 10416 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 10417 * software-rendered usages are discouraged and have compatibility issues with hardware-only 10418 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 10419 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 10420 * reports or unit testing the {@link PixelCopy} API is recommended. 10421 */ 10422 @Deprecated 10423 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 10424 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 10425 } 10426 10427 /** 10428 * Returns whether or not this View can cache its drawing or not. 10429 * 10430 * @return true if this view does not cache its drawing, false otherwise 10431 * 10432 * @deprecated The view drawing cache was largely made obsolete with the introduction of 10433 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 10434 * layers are largely unnecessary and can easily result in a net loss in performance due to the 10435 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 10436 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 10437 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 10438 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 10439 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 10440 * software-rendered usages are discouraged and have compatibility issues with hardware-only 10441 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 10442 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 10443 * reports or unit testing the {@link PixelCopy} API is recommended. 10444 */ 10445 @ViewDebug.ExportedProperty(category = "drawing") 10446 @Deprecated 10447 public boolean willNotCacheDrawing() { 10448 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 10449 } 10450 10451 /** 10452 * Indicates whether this view reacts to click events or not. 10453 * 10454 * @return true if the view is clickable, false otherwise 10455 * 10456 * @see #setClickable(boolean) 10457 * @attr ref android.R.styleable#View_clickable 10458 */ 10459 @ViewDebug.ExportedProperty 10460 public boolean isClickable() { 10461 return (mViewFlags & CLICKABLE) == CLICKABLE; 10462 } 10463 10464 /** 10465 * Enables or disables click events for this view. When a view 10466 * is clickable it will change its state to "pressed" on every click. 10467 * Subclasses should set the view clickable to visually react to 10468 * user's clicks. 10469 * 10470 * @param clickable true to make the view clickable, false otherwise 10471 * 10472 * @see #isClickable() 10473 * @attr ref android.R.styleable#View_clickable 10474 */ 10475 public void setClickable(boolean clickable) { 10476 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 10477 } 10478 10479 /** 10480 * Indicates whether this view reacts to long click events or not. 10481 * 10482 * @return true if the view is long clickable, false otherwise 10483 * 10484 * @see #setLongClickable(boolean) 10485 * @attr ref android.R.styleable#View_longClickable 10486 */ 10487 public boolean isLongClickable() { 10488 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 10489 } 10490 10491 /** 10492 * Enables or disables long click events for this view. When a view is long 10493 * clickable it reacts to the user holding down the button for a longer 10494 * duration than a tap. This event can either launch the listener or a 10495 * context menu. 10496 * 10497 * @param longClickable true to make the view long clickable, false otherwise 10498 * @see #isLongClickable() 10499 * @attr ref android.R.styleable#View_longClickable 10500 */ 10501 public void setLongClickable(boolean longClickable) { 10502 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 10503 } 10504 10505 /** 10506 * Indicates whether this view reacts to context clicks or not. 10507 * 10508 * @return true if the view is context clickable, false otherwise 10509 * @see #setContextClickable(boolean) 10510 * @attr ref android.R.styleable#View_contextClickable 10511 */ 10512 public boolean isContextClickable() { 10513 return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 10514 } 10515 10516 /** 10517 * Enables or disables context clicking for this view. This event can launch the listener. 10518 * 10519 * @param contextClickable true to make the view react to a context click, false otherwise 10520 * @see #isContextClickable() 10521 * @attr ref android.R.styleable#View_contextClickable 10522 */ 10523 public void setContextClickable(boolean contextClickable) { 10524 setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE); 10525 } 10526 10527 /** 10528 * Sets the pressed state for this view and provides a touch coordinate for 10529 * animation hinting. 10530 * 10531 * @param pressed Pass true to set the View's internal state to "pressed", 10532 * or false to reverts the View's internal state from a 10533 * previously set "pressed" state. 10534 * @param x The x coordinate of the touch that caused the press 10535 * @param y The y coordinate of the touch that caused the press 10536 */ 10537 private void setPressed(boolean pressed, float x, float y) { 10538 if (pressed) { 10539 drawableHotspotChanged(x, y); 10540 } 10541 10542 setPressed(pressed); 10543 } 10544 10545 /** 10546 * Sets the pressed state for this view. 10547 * 10548 * @see #isClickable() 10549 * @see #setClickable(boolean) 10550 * 10551 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 10552 * the View's internal state from a previously set "pressed" state. 10553 */ 10554 public void setPressed(boolean pressed) { 10555 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 10556 10557 if (pressed) { 10558 mPrivateFlags |= PFLAG_PRESSED; 10559 } else { 10560 mPrivateFlags &= ~PFLAG_PRESSED; 10561 } 10562 10563 if (needsRefresh) { 10564 refreshDrawableState(); 10565 } 10566 dispatchSetPressed(pressed); 10567 } 10568 10569 /** 10570 * Dispatch setPressed to all of this View's children. 10571 * 10572 * @see #setPressed(boolean) 10573 * 10574 * @param pressed The new pressed state 10575 */ 10576 protected void dispatchSetPressed(boolean pressed) { 10577 } 10578 10579 /** 10580 * Indicates whether the view is currently in pressed state. Unless 10581 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 10582 * the pressed state. 10583 * 10584 * @see #setPressed(boolean) 10585 * @see #isClickable() 10586 * @see #setClickable(boolean) 10587 * 10588 * @return true if the view is currently pressed, false otherwise 10589 */ 10590 @ViewDebug.ExportedProperty 10591 public boolean isPressed() { 10592 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 10593 } 10594 10595 /** 10596 * @hide 10597 * Indicates whether this view will participate in data collection through 10598 * {@link ViewStructure}. If true, it will not provide any data 10599 * for itself or its children. If false, the normal data collection will be allowed. 10600 * 10601 * @return Returns false if assist data collection is not blocked, else true. 10602 * 10603 * @see #setAssistBlocked(boolean) 10604 * @attr ref android.R.styleable#View_assistBlocked 10605 */ 10606 public boolean isAssistBlocked() { 10607 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0; 10608 } 10609 10610 /** 10611 * @hide 10612 * Controls whether assist data collection from this view and its children is enabled 10613 * (that is, whether {@link #onProvideStructure} and 10614 * {@link #onProvideVirtualStructure} will be called). The default value is false, 10615 * allowing normal assist collection. Setting this to false will disable assist collection. 10616 * 10617 * @param enabled Set to true to <em>disable</em> assist data collection, or false 10618 * (the default) to allow it. 10619 * 10620 * @see #isAssistBlocked() 10621 * @see #onProvideStructure 10622 * @see #onProvideVirtualStructure 10623 * @attr ref android.R.styleable#View_assistBlocked 10624 */ 10625 public void setAssistBlocked(boolean enabled) { 10626 if (enabled) { 10627 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; 10628 } else { 10629 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED; 10630 } 10631 } 10632 10633 /** 10634 * Indicates whether this view will save its state (that is, 10635 * whether its {@link #onSaveInstanceState} method will be called). 10636 * 10637 * @return Returns true if the view state saving is enabled, else false. 10638 * 10639 * @see #setSaveEnabled(boolean) 10640 * @attr ref android.R.styleable#View_saveEnabled 10641 */ 10642 public boolean isSaveEnabled() { 10643 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 10644 } 10645 10646 /** 10647 * Controls whether the saving of this view's state is 10648 * enabled (that is, whether its {@link #onSaveInstanceState} method 10649 * will be called). Note that even if freezing is enabled, the 10650 * view still must have an id assigned to it (via {@link #setId(int)}) 10651 * for its state to be saved. This flag can only disable the 10652 * saving of this view; any child views may still have their state saved. 10653 * 10654 * @param enabled Set to false to <em>disable</em> state saving, or true 10655 * (the default) to allow it. 10656 * 10657 * @see #isSaveEnabled() 10658 * @see #setId(int) 10659 * @see #onSaveInstanceState() 10660 * @attr ref android.R.styleable#View_saveEnabled 10661 */ 10662 public void setSaveEnabled(boolean enabled) { 10663 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 10664 } 10665 10666 /** 10667 * Gets whether the framework should discard touches when the view's 10668 * window is obscured by another visible window. 10669 * Refer to the {@link View} security documentation for more details. 10670 * 10671 * @return True if touch filtering is enabled. 10672 * 10673 * @see #setFilterTouchesWhenObscured(boolean) 10674 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 10675 */ 10676 @ViewDebug.ExportedProperty 10677 public boolean getFilterTouchesWhenObscured() { 10678 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 10679 } 10680 10681 /** 10682 * Sets whether the framework should discard touches when the view's 10683 * window is obscured by another visible window. 10684 * Refer to the {@link View} security documentation for more details. 10685 * 10686 * @param enabled True if touch filtering should be enabled. 10687 * 10688 * @see #getFilterTouchesWhenObscured 10689 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 10690 */ 10691 public void setFilterTouchesWhenObscured(boolean enabled) { 10692 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 10693 FILTER_TOUCHES_WHEN_OBSCURED); 10694 } 10695 10696 /** 10697 * Indicates whether the entire hierarchy under this view will save its 10698 * state when a state saving traversal occurs from its parent. The default 10699 * is true; if false, these views will not be saved unless 10700 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 10701 * 10702 * @return Returns true if the view state saving from parent is enabled, else false. 10703 * 10704 * @see #setSaveFromParentEnabled(boolean) 10705 */ 10706 public boolean isSaveFromParentEnabled() { 10707 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 10708 } 10709 10710 /** 10711 * Controls whether the entire hierarchy under this view will save its 10712 * state when a state saving traversal occurs from its parent. The default 10713 * is true; if false, these views will not be saved unless 10714 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 10715 * 10716 * @param enabled Set to false to <em>disable</em> state saving, or true 10717 * (the default) to allow it. 10718 * 10719 * @see #isSaveFromParentEnabled() 10720 * @see #setId(int) 10721 * @see #onSaveInstanceState() 10722 */ 10723 public void setSaveFromParentEnabled(boolean enabled) { 10724 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 10725 } 10726 10727 10728 /** 10729 * Returns whether this View is currently able to take focus. 10730 * 10731 * @return True if this view can take focus, or false otherwise. 10732 */ 10733 @ViewDebug.ExportedProperty(category = "focus") 10734 public final boolean isFocusable() { 10735 return FOCUSABLE == (mViewFlags & FOCUSABLE); 10736 } 10737 10738 /** 10739 * Returns the focusable setting for this view. 10740 * 10741 * @return One of {@link #NOT_FOCUSABLE}, {@link #FOCUSABLE}, or {@link #FOCUSABLE_AUTO}. 10742 * @attr ref android.R.styleable#View_focusable 10743 */ 10744 @ViewDebug.ExportedProperty(mapping = { 10745 @ViewDebug.IntToString(from = NOT_FOCUSABLE, to = "NOT_FOCUSABLE"), 10746 @ViewDebug.IntToString(from = FOCUSABLE, to = "FOCUSABLE"), 10747 @ViewDebug.IntToString(from = FOCUSABLE_AUTO, to = "FOCUSABLE_AUTO") 10748 }, category = "focus") 10749 @Focusable 10750 public int getFocusable() { 10751 return (mViewFlags & FOCUSABLE_AUTO) > 0 ? FOCUSABLE_AUTO : mViewFlags & FOCUSABLE; 10752 } 10753 10754 /** 10755 * When a view is focusable, it may not want to take focus when in touch mode. 10756 * For example, a button would like focus when the user is navigating via a D-pad 10757 * so that the user can click on it, but once the user starts touching the screen, 10758 * the button shouldn't take focus 10759 * @return Whether the view is focusable in touch mode. 10760 * @attr ref android.R.styleable#View_focusableInTouchMode 10761 */ 10762 @ViewDebug.ExportedProperty(category = "focus") 10763 public final boolean isFocusableInTouchMode() { 10764 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 10765 } 10766 10767 /** 10768 * Returns whether the view should be treated as a focusable unit by screen reader 10769 * accessibility tools. 10770 * @see #setScreenReaderFocusable(boolean) 10771 * 10772 * @return Whether the view should be treated as a focusable unit by screen reader. 10773 */ 10774 public boolean isScreenReaderFocusable() { 10775 return (mPrivateFlags3 & PFLAG3_SCREEN_READER_FOCUSABLE) != 0; 10776 } 10777 10778 /** 10779 * When screen readers (one type of accessibility tool) decide what should be read to the 10780 * user, they typically look for input focusable ({@link #isFocusable()}) parents of 10781 * non-focusable text items, and read those focusable parents and their non-focusable children 10782 * as a unit. In some situations, this behavior is desirable for views that should not take 10783 * input focus. Setting an item to be screen reader focusable requests that the view be 10784 * treated as a unit by screen readers without any effect on input focusability. The default 10785 * value of {@code false} lets screen readers use other signals, like focusable, to determine 10786 * how to group items. 10787 * 10788 * @param screenReaderFocusable Whether the view should be treated as a unit by screen reader 10789 * accessibility tools. 10790 */ 10791 public void setScreenReaderFocusable(boolean screenReaderFocusable) { 10792 updatePflags3AndNotifyA11yIfChanged(PFLAG3_SCREEN_READER_FOCUSABLE, screenReaderFocusable); 10793 } 10794 10795 /** 10796 * Gets whether this view is a heading for accessibility purposes. 10797 * 10798 * @return {@code true} if the view is a heading, {@code false} otherwise. 10799 * 10800 * @attr ref android.R.styleable#View_accessibilityHeading 10801 */ 10802 public boolean isAccessibilityHeading() { 10803 return (mPrivateFlags3 & PFLAG3_ACCESSIBILITY_HEADING) != 0; 10804 } 10805 10806 /** 10807 * Set if view is a heading for a section of content for accessibility purposes. 10808 * 10809 * @param isHeading {@code true} if the view is a heading, {@code false} otherwise. 10810 * 10811 * @attr ref android.R.styleable#View_accessibilityHeading 10812 */ 10813 public void setAccessibilityHeading(boolean isHeading) { 10814 updatePflags3AndNotifyA11yIfChanged(PFLAG3_ACCESSIBILITY_HEADING, isHeading); 10815 } 10816 10817 private void updatePflags3AndNotifyA11yIfChanged(int mask, boolean newValue) { 10818 int pflags3 = mPrivateFlags3; 10819 if (newValue) { 10820 pflags3 |= mask; 10821 } else { 10822 pflags3 &= ~mask; 10823 } 10824 10825 if (pflags3 != mPrivateFlags3) { 10826 mPrivateFlags3 = pflags3; 10827 notifyViewAccessibilityStateChangedIfNeeded( 10828 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 10829 } 10830 } 10831 10832 /** 10833 * Find the nearest view in the specified direction that can take focus. 10834 * This does not actually give focus to that view. 10835 * 10836 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 10837 * 10838 * @return The nearest focusable in the specified direction, or null if none 10839 * can be found. 10840 */ 10841 public View focusSearch(@FocusRealDirection int direction) { 10842 if (mParent != null) { 10843 return mParent.focusSearch(this, direction); 10844 } else { 10845 return null; 10846 } 10847 } 10848 10849 /** 10850 * Returns whether this View is a root of a keyboard navigation cluster. 10851 * 10852 * @return True if this view is a root of a cluster, or false otherwise. 10853 * @attr ref android.R.styleable#View_keyboardNavigationCluster 10854 */ 10855 @ViewDebug.ExportedProperty(category = "focus") 10856 public final boolean isKeyboardNavigationCluster() { 10857 return (mPrivateFlags3 & PFLAG3_CLUSTER) != 0; 10858 } 10859 10860 /** 10861 * Searches up the view hierarchy to find the top-most cluster. All deeper/nested clusters 10862 * will be ignored. 10863 * 10864 * @return the keyboard navigation cluster that this view is in (can be this view) 10865 * or {@code null} if not in one 10866 */ 10867 View findKeyboardNavigationCluster() { 10868 if (mParent instanceof View) { 10869 View cluster = ((View) mParent).findKeyboardNavigationCluster(); 10870 if (cluster != null) { 10871 return cluster; 10872 } else if (isKeyboardNavigationCluster()) { 10873 return this; 10874 } 10875 } 10876 return null; 10877 } 10878 10879 /** 10880 * Set whether this view is a root of a keyboard navigation cluster. 10881 * 10882 * @param isCluster If true, this view is a root of a cluster. 10883 * 10884 * @attr ref android.R.styleable#View_keyboardNavigationCluster 10885 */ 10886 public void setKeyboardNavigationCluster(boolean isCluster) { 10887 if (isCluster) { 10888 mPrivateFlags3 |= PFLAG3_CLUSTER; 10889 } else { 10890 mPrivateFlags3 &= ~PFLAG3_CLUSTER; 10891 } 10892 } 10893 10894 /** 10895 * Sets this View as the one which receives focus the next time cluster navigation jumps 10896 * to the cluster containing this View. This does NOT change focus even if the cluster 10897 * containing this view is current. 10898 * 10899 * @hide 10900 */ 10901 @TestApi 10902 public final void setFocusedInCluster() { 10903 setFocusedInCluster(findKeyboardNavigationCluster()); 10904 } 10905 10906 private void setFocusedInCluster(View cluster) { 10907 if (this instanceof ViewGroup) { 10908 ((ViewGroup) this).mFocusedInCluster = null; 10909 } 10910 if (cluster == this) { 10911 return; 10912 } 10913 ViewParent parent = mParent; 10914 View child = this; 10915 while (parent instanceof ViewGroup) { 10916 ((ViewGroup) parent).mFocusedInCluster = child; 10917 if (parent == cluster) { 10918 break; 10919 } 10920 child = (View) parent; 10921 parent = parent.getParent(); 10922 } 10923 } 10924 10925 private void updateFocusedInCluster(View oldFocus, @FocusDirection int direction) { 10926 if (oldFocus != null) { 10927 View oldCluster = oldFocus.findKeyboardNavigationCluster(); 10928 View cluster = findKeyboardNavigationCluster(); 10929 if (oldCluster != cluster) { 10930 // Going from one cluster to another, so save last-focused. 10931 // This covers cluster jumps because they are always FOCUS_DOWN 10932 oldFocus.setFocusedInCluster(oldCluster); 10933 if (!(oldFocus.mParent instanceof ViewGroup)) { 10934 return; 10935 } 10936 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) { 10937 // This is a result of ordered navigation so consider navigation through 10938 // the previous cluster "complete" and clear its last-focused memory. 10939 ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus); 10940 } else if (oldFocus instanceof ViewGroup 10941 && ((ViewGroup) oldFocus).getDescendantFocusability() 10942 == ViewGroup.FOCUS_AFTER_DESCENDANTS 10943 && ViewRootImpl.isViewDescendantOf(this, oldFocus)) { 10944 // This means oldFocus is not focusable since it obviously has a focusable 10945 // child (this). Don't restore focus to it in the future. 10946 ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus); 10947 } 10948 } 10949 } 10950 } 10951 10952 /** 10953 * Returns whether this View should receive focus when the focus is restored for the view 10954 * hierarchy containing this view. 10955 * <p> 10956 * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a 10957 * window or serves as a target of cluster navigation. 10958 * 10959 * @see #restoreDefaultFocus() 10960 * 10961 * @return {@code true} if this view is the default-focus view, {@code false} otherwise 10962 * @attr ref android.R.styleable#View_focusedByDefault 10963 */ 10964 @ViewDebug.ExportedProperty(category = "focus") 10965 public final boolean isFocusedByDefault() { 10966 return (mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0; 10967 } 10968 10969 /** 10970 * Sets whether this View should receive focus when the focus is restored for the view 10971 * hierarchy containing this view. 10972 * <p> 10973 * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a 10974 * window or serves as a target of cluster navigation. 10975 * 10976 * @param isFocusedByDefault {@code true} to set this view as the default-focus view, 10977 * {@code false} otherwise. 10978 * 10979 * @see #restoreDefaultFocus() 10980 * 10981 * @attr ref android.R.styleable#View_focusedByDefault 10982 */ 10983 public void setFocusedByDefault(boolean isFocusedByDefault) { 10984 if (isFocusedByDefault == ((mPrivateFlags3 & PFLAG3_FOCUSED_BY_DEFAULT) != 0)) { 10985 return; 10986 } 10987 10988 if (isFocusedByDefault) { 10989 mPrivateFlags3 |= PFLAG3_FOCUSED_BY_DEFAULT; 10990 } else { 10991 mPrivateFlags3 &= ~PFLAG3_FOCUSED_BY_DEFAULT; 10992 } 10993 10994 if (mParent instanceof ViewGroup) { 10995 if (isFocusedByDefault) { 10996 ((ViewGroup) mParent).setDefaultFocus(this); 10997 } else { 10998 ((ViewGroup) mParent).clearDefaultFocus(this); 10999 } 11000 } 11001 } 11002 11003 /** 11004 * Returns whether the view hierarchy with this view as a root contain a default-focus view. 11005 * 11006 * @return {@code true} if this view has default focus, {@code false} otherwise 11007 */ 11008 boolean hasDefaultFocus() { 11009 return isFocusedByDefault(); 11010 } 11011 11012 /** 11013 * Find the nearest keyboard navigation cluster in the specified direction. 11014 * This does not actually give focus to that cluster. 11015 * 11016 * @param currentCluster The starting point of the search. Null means the current cluster is not 11017 * found yet 11018 * @param direction Direction to look 11019 * 11020 * @return The nearest keyboard navigation cluster in the specified direction, or null if none 11021 * can be found 11022 */ 11023 public View keyboardNavigationClusterSearch(View currentCluster, 11024 @FocusDirection int direction) { 11025 if (isKeyboardNavigationCluster()) { 11026 currentCluster = this; 11027 } 11028 if (isRootNamespace()) { 11029 // Root namespace means we should consider ourselves the top of the 11030 // tree for group searching; otherwise we could be group searching 11031 // into other tabs. see LocalActivityManager and TabHost for more info. 11032 return FocusFinder.getInstance().findNextKeyboardNavigationCluster( 11033 this, currentCluster, direction); 11034 } else if (mParent != null) { 11035 return mParent.keyboardNavigationClusterSearch(currentCluster, direction); 11036 } 11037 return null; 11038 } 11039 11040 /** 11041 * This method is the last chance for the focused view and its ancestors to 11042 * respond to an arrow key. This is called when the focused view did not 11043 * consume the key internally, nor could the view system find a new view in 11044 * the requested direction to give focus to. 11045 * 11046 * @param focused The currently focused view. 11047 * @param direction The direction focus wants to move. One of FOCUS_UP, 11048 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 11049 * @return True if the this view consumed this unhandled move. 11050 */ 11051 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) { 11052 return false; 11053 } 11054 11055 /** 11056 * Sets whether this View should use a default focus highlight when it gets focused but doesn't 11057 * have {@link android.R.attr#state_focused} defined in its background. 11058 * 11059 * @param defaultFocusHighlightEnabled {@code true} to set this view to use a default focus 11060 * highlight, {@code false} otherwise. 11061 * 11062 * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled 11063 */ 11064 public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) { 11065 mDefaultFocusHighlightEnabled = defaultFocusHighlightEnabled; 11066 } 11067 11068 /** 11069 11070 /** 11071 * Returns whether this View should use a default focus highlight when it gets focused but 11072 * doesn't have {@link android.R.attr#state_focused} defined in its background. 11073 * 11074 * @return True if this View should use a default focus highlight. 11075 * @attr ref android.R.styleable#View_defaultFocusHighlightEnabled 11076 */ 11077 @ViewDebug.ExportedProperty(category = "focus") 11078 public final boolean getDefaultFocusHighlightEnabled() { 11079 return mDefaultFocusHighlightEnabled; 11080 } 11081 11082 /** 11083 * If a user manually specified the next view id for a particular direction, 11084 * use the root to look up the view. 11085 * @param root The root view of the hierarchy containing this view. 11086 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 11087 * or FOCUS_BACKWARD. 11088 * @return The user specified next view, or null if there is none. 11089 */ 11090 View findUserSetNextFocus(View root, @FocusDirection int direction) { 11091 switch (direction) { 11092 case FOCUS_LEFT: 11093 if (mNextFocusLeftId == View.NO_ID) return null; 11094 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 11095 case FOCUS_RIGHT: 11096 if (mNextFocusRightId == View.NO_ID) return null; 11097 return findViewInsideOutShouldExist(root, mNextFocusRightId); 11098 case FOCUS_UP: 11099 if (mNextFocusUpId == View.NO_ID) return null; 11100 return findViewInsideOutShouldExist(root, mNextFocusUpId); 11101 case FOCUS_DOWN: 11102 if (mNextFocusDownId == View.NO_ID) return null; 11103 return findViewInsideOutShouldExist(root, mNextFocusDownId); 11104 case FOCUS_FORWARD: 11105 if (mNextFocusForwardId == View.NO_ID) return null; 11106 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 11107 case FOCUS_BACKWARD: { 11108 if (mID == View.NO_ID) return null; 11109 final int id = mID; 11110 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 11111 @Override 11112 public boolean test(View t) { 11113 return t.mNextFocusForwardId == id; 11114 } 11115 }); 11116 } 11117 } 11118 return null; 11119 } 11120 11121 /** 11122 * If a user manually specified the next keyboard-navigation cluster for a particular direction, 11123 * use the root to look up the view. 11124 * 11125 * @param root the root view of the hierarchy containing this view 11126 * @param direction {@link #FOCUS_FORWARD} or {@link #FOCUS_BACKWARD} 11127 * @return the user-specified next cluster, or {@code null} if there is none 11128 */ 11129 View findUserSetNextKeyboardNavigationCluster(View root, @FocusDirection int direction) { 11130 switch (direction) { 11131 case FOCUS_FORWARD: 11132 if (mNextClusterForwardId == View.NO_ID) return null; 11133 return findViewInsideOutShouldExist(root, mNextClusterForwardId); 11134 case FOCUS_BACKWARD: { 11135 if (mID == View.NO_ID) return null; 11136 final int id = mID; 11137 return root.findViewByPredicateInsideOut(this, 11138 (Predicate<View>) t -> t.mNextClusterForwardId == id); 11139 } 11140 } 11141 return null; 11142 } 11143 11144 private View findViewInsideOutShouldExist(View root, int id) { 11145 if (mMatchIdPredicate == null) { 11146 mMatchIdPredicate = new MatchIdPredicate(); 11147 } 11148 mMatchIdPredicate.mId = id; 11149 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 11150 if (result == null) { 11151 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 11152 } 11153 return result; 11154 } 11155 11156 /** 11157 * Find and return all focusable views that are descendants of this view, 11158 * possibly including this view if it is focusable itself. 11159 * 11160 * @param direction The direction of the focus 11161 * @return A list of focusable views 11162 */ 11163 public ArrayList<View> getFocusables(@FocusDirection int direction) { 11164 ArrayList<View> result = new ArrayList<View>(24); 11165 addFocusables(result, direction); 11166 return result; 11167 } 11168 11169 /** 11170 * Add any focusable views that are descendants of this view (possibly 11171 * including this view if it is focusable itself) to views. If we are in touch mode, 11172 * only add views that are also focusable in touch mode. 11173 * 11174 * @param views Focusable views found so far 11175 * @param direction The direction of the focus 11176 */ 11177 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) { 11178 addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL); 11179 } 11180 11181 /** 11182 * Adds any focusable views that are descendants of this view (possibly 11183 * including this view if it is focusable itself) to views. This method 11184 * adds all focusable views regardless if we are in touch mode or 11185 * only views focusable in touch mode if we are in touch mode or 11186 * only views that can take accessibility focus if accessibility is enabled 11187 * depending on the focusable mode parameter. 11188 * 11189 * @param views Focusable views found so far or null if all we are interested is 11190 * the number of focusables. 11191 * @param direction The direction of the focus. 11192 * @param focusableMode The type of focusables to be added. 11193 * 11194 * @see #FOCUSABLES_ALL 11195 * @see #FOCUSABLES_TOUCH_MODE 11196 */ 11197 public void addFocusables(ArrayList<View> views, @FocusDirection int direction, 11198 @FocusableMode int focusableMode) { 11199 if (views == null) { 11200 return; 11201 } 11202 if (!canTakeFocus()) { 11203 return; 11204 } 11205 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 11206 && !isFocusableInTouchMode()) { 11207 return; 11208 } 11209 views.add(this); 11210 } 11211 11212 /** 11213 * Adds any keyboard navigation cluster roots that are descendants of this view (possibly 11214 * including this view if it is a cluster root itself) to views. 11215 * 11216 * @param views Keyboard navigation cluster roots found so far 11217 * @param direction Direction to look 11218 */ 11219 public void addKeyboardNavigationClusters( 11220 @NonNull Collection<View> views, 11221 int direction) { 11222 if (!isKeyboardNavigationCluster()) { 11223 return; 11224 } 11225 if (!hasFocusable()) { 11226 return; 11227 } 11228 views.add(this); 11229 } 11230 11231 /** 11232 * Finds the Views that contain given text. The containment is case insensitive. 11233 * The search is performed by either the text that the View renders or the content 11234 * description that describes the view for accessibility purposes and the view does 11235 * not render or both. Clients can specify how the search is to be performed via 11236 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 11237 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 11238 * 11239 * @param outViews The output list of matching Views. 11240 * @param searched The text to match against. 11241 * 11242 * @see #FIND_VIEWS_WITH_TEXT 11243 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 11244 * @see #setContentDescription(CharSequence) 11245 */ 11246 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, 11247 @FindViewFlags int flags) { 11248 if (getAccessibilityNodeProvider() != null) { 11249 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 11250 outViews.add(this); 11251 } 11252 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 11253 && (searched != null && searched.length() > 0) 11254 && (mContentDescription != null && mContentDescription.length() > 0)) { 11255 String searchedLowerCase = searched.toString().toLowerCase(); 11256 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 11257 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 11258 outViews.add(this); 11259 } 11260 } 11261 } 11262 11263 /** 11264 * Find and return all touchable views that are descendants of this view, 11265 * possibly including this view if it is touchable itself. 11266 * 11267 * @return A list of touchable views 11268 */ 11269 public ArrayList<View> getTouchables() { 11270 ArrayList<View> result = new ArrayList<View>(); 11271 addTouchables(result); 11272 return result; 11273 } 11274 11275 /** 11276 * Add any touchable views that are descendants of this view (possibly 11277 * including this view if it is touchable itself) to views. 11278 * 11279 * @param views Touchable views found so far 11280 */ 11281 public void addTouchables(ArrayList<View> views) { 11282 final int viewFlags = mViewFlags; 11283 11284 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 11285 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) 11286 && (viewFlags & ENABLED_MASK) == ENABLED) { 11287 views.add(this); 11288 } 11289 } 11290 11291 /** 11292 * Returns whether this View is accessibility focused. 11293 * 11294 * @return True if this View is accessibility focused. 11295 */ 11296 public boolean isAccessibilityFocused() { 11297 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 11298 } 11299 11300 /** 11301 * Call this to try to give accessibility focus to this view. 11302 * 11303 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 11304 * returns false or the view is no visible or the view already has accessibility 11305 * focus. 11306 * 11307 * See also {@link #focusSearch(int)}, which is what you call to say that you 11308 * have focus, and you want your parent to look for the next one. 11309 * 11310 * @return Whether this view actually took accessibility focus. 11311 * 11312 * @hide 11313 */ 11314 public boolean requestAccessibilityFocus() { 11315 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 11316 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 11317 return false; 11318 } 11319 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 11320 return false; 11321 } 11322 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 11323 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 11324 ViewRootImpl viewRootImpl = getViewRootImpl(); 11325 if (viewRootImpl != null) { 11326 viewRootImpl.setAccessibilityFocus(this, null); 11327 } 11328 invalidate(); 11329 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 11330 return true; 11331 } 11332 return false; 11333 } 11334 11335 /** 11336 * Call this to try to clear accessibility focus of this view. 11337 * 11338 * See also {@link #focusSearch(int)}, which is what you call to say that you 11339 * have focus, and you want your parent to look for the next one. 11340 * 11341 * @hide 11342 */ 11343 public void clearAccessibilityFocus() { 11344 clearAccessibilityFocusNoCallbacks(0); 11345 11346 // Clear the global reference of accessibility focus if this view or 11347 // any of its descendants had accessibility focus. This will NOT send 11348 // an event or update internal state if focus is cleared from a 11349 // descendant view, which may leave views in inconsistent states. 11350 final ViewRootImpl viewRootImpl = getViewRootImpl(); 11351 if (viewRootImpl != null) { 11352 final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 11353 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 11354 viewRootImpl.setAccessibilityFocus(null, null); 11355 } 11356 } 11357 } 11358 11359 private void sendAccessibilityHoverEvent(int eventType) { 11360 // Since we are not delivering to a client accessibility events from not 11361 // important views (unless the clinet request that) we need to fire the 11362 // event from the deepest view exposed to the client. As a consequence if 11363 // the user crosses a not exposed view the client will see enter and exit 11364 // of the exposed predecessor followed by and enter and exit of that same 11365 // predecessor when entering and exiting the not exposed descendant. This 11366 // is fine since the client has a clear idea which view is hovered at the 11367 // price of a couple more events being sent. This is a simple and 11368 // working solution. 11369 View source = this; 11370 while (true) { 11371 if (source.includeForAccessibility()) { 11372 source.sendAccessibilityEvent(eventType); 11373 return; 11374 } 11375 ViewParent parent = source.getParent(); 11376 if (parent instanceof View) { 11377 source = (View) parent; 11378 } else { 11379 return; 11380 } 11381 } 11382 } 11383 11384 /** 11385 * Clears accessibility focus without calling any callback methods 11386 * normally invoked in {@link #clearAccessibilityFocus()}. This method 11387 * is used separately from that one for clearing accessibility focus when 11388 * giving this focus to another view. 11389 * 11390 * @param action The action, if any, that led to focus being cleared. Set to 11391 * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within 11392 * the window. 11393 */ 11394 void clearAccessibilityFocusNoCallbacks(int action) { 11395 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 11396 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 11397 invalidate(); 11398 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 11399 AccessibilityEvent event = AccessibilityEvent.obtain( 11400 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 11401 event.setAction(action); 11402 if (mAccessibilityDelegate != null) { 11403 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 11404 } else { 11405 sendAccessibilityEventUnchecked(event); 11406 } 11407 } 11408 } 11409 } 11410 11411 /** 11412 * Call this to try to give focus to a specific view or to one of its 11413 * descendants. 11414 * 11415 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 11416 * false), or if it can't be focused due to other conditions (not focusable in touch mode 11417 * ({@link #isFocusableInTouchMode}) while the device is in touch mode, not visible, not 11418 * enabled, or has no size). 11419 * 11420 * See also {@link #focusSearch(int)}, which is what you call to say that you 11421 * have focus, and you want your parent to look for the next one. 11422 * 11423 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 11424 * {@link #FOCUS_DOWN} and <code>null</code>. 11425 * 11426 * @return Whether this view or one of its descendants actually took focus. 11427 */ 11428 public final boolean requestFocus() { 11429 return requestFocus(View.FOCUS_DOWN); 11430 } 11431 11432 /** 11433 * This will request focus for whichever View was last focused within this 11434 * cluster before a focus-jump out of it. 11435 * 11436 * @hide 11437 */ 11438 @TestApi 11439 public boolean restoreFocusInCluster(@FocusRealDirection int direction) { 11440 // Prioritize focusableByDefault over algorithmic focus selection. 11441 if (restoreDefaultFocus()) { 11442 return true; 11443 } 11444 return requestFocus(direction); 11445 } 11446 11447 /** 11448 * This will request focus for whichever View not in a cluster was last focused before a 11449 * focus-jump to a cluster. If no non-cluster View has previously had focus, this will focus 11450 * the "first" focusable view it finds. 11451 * 11452 * @hide 11453 */ 11454 @TestApi 11455 public boolean restoreFocusNotInCluster() { 11456 return requestFocus(View.FOCUS_DOWN); 11457 } 11458 11459 /** 11460 * Gives focus to the default-focus view in the view hierarchy that has this view as a root. 11461 * If the default-focus view cannot be found, falls back to calling {@link #requestFocus(int)}. 11462 * 11463 * @return Whether this view or one of its descendants actually took focus 11464 */ 11465 public boolean restoreDefaultFocus() { 11466 return requestFocus(View.FOCUS_DOWN); 11467 } 11468 11469 /** 11470 * Call this to try to give focus to a specific view or to one of its 11471 * descendants and give it a hint about what direction focus is heading. 11472 * 11473 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 11474 * false), or if it is focusable and it is not focusable in touch mode 11475 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 11476 * 11477 * See also {@link #focusSearch(int)}, which is what you call to say that you 11478 * have focus, and you want your parent to look for the next one. 11479 * 11480 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 11481 * <code>null</code> set for the previously focused rectangle. 11482 * 11483 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 11484 * @return Whether this view or one of its descendants actually took focus. 11485 */ 11486 public final boolean requestFocus(int direction) { 11487 return requestFocus(direction, null); 11488 } 11489 11490 /** 11491 * Call this to try to give focus to a specific view or to one of its descendants 11492 * and give it hints about the direction and a specific rectangle that the focus 11493 * is coming from. The rectangle can help give larger views a finer grained hint 11494 * about where focus is coming from, and therefore, where to show selection, or 11495 * forward focus change internally. 11496 * 11497 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 11498 * false), or if it is focusable and it is not focusable in touch mode 11499 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 11500 * 11501 * A View will not take focus if it is not visible. 11502 * 11503 * A View will not take focus if one of its parents has 11504 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 11505 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 11506 * 11507 * See also {@link #focusSearch(int)}, which is what you call to say that you 11508 * have focus, and you want your parent to look for the next one. 11509 * 11510 * You may wish to override this method if your custom {@link View} has an internal 11511 * {@link View} that it wishes to forward the request to. 11512 * 11513 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 11514 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 11515 * to give a finer grained hint about where focus is coming from. May be null 11516 * if there is no hint. 11517 * @return Whether this view or one of its descendants actually took focus. 11518 */ 11519 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 11520 return requestFocusNoSearch(direction, previouslyFocusedRect); 11521 } 11522 11523 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 11524 // need to be focusable 11525 if (!canTakeFocus()) { 11526 return false; 11527 } 11528 11529 // need to be focusable in touch mode if in touch mode 11530 if (isInTouchMode() && 11531 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 11532 return false; 11533 } 11534 11535 // need to not have any parents blocking us 11536 if (hasAncestorThatBlocksDescendantFocus()) { 11537 return false; 11538 } 11539 11540 if (!isLayoutValid()) { 11541 mPrivateFlags |= PFLAG_WANTS_FOCUS; 11542 } else { 11543 clearParentsWantFocus(); 11544 } 11545 11546 handleFocusGainInternal(direction, previouslyFocusedRect); 11547 return true; 11548 } 11549 11550 void clearParentsWantFocus() { 11551 if (mParent instanceof View) { 11552 ((View) mParent).mPrivateFlags &= ~PFLAG_WANTS_FOCUS; 11553 ((View) mParent).clearParentsWantFocus(); 11554 } 11555 } 11556 11557 /** 11558 * Call this to try to give focus to a specific view or to one of its descendants. This is a 11559 * special variant of {@link #requestFocus() } that will allow views that are not focusable in 11560 * touch mode to request focus when they are touched. 11561 * 11562 * @return Whether this view or one of its descendants actually took focus. 11563 * 11564 * @see #isInTouchMode() 11565 * 11566 */ 11567 public final boolean requestFocusFromTouch() { 11568 // Leave touch mode if we need to 11569 if (isInTouchMode()) { 11570 ViewRootImpl viewRoot = getViewRootImpl(); 11571 if (viewRoot != null) { 11572 viewRoot.ensureTouchMode(false); 11573 } 11574 } 11575 return requestFocus(View.FOCUS_DOWN); 11576 } 11577 11578 /** 11579 * @return Whether any ancestor of this view blocks descendant focus. 11580 */ 11581 private boolean hasAncestorThatBlocksDescendantFocus() { 11582 final boolean focusableInTouchMode = isFocusableInTouchMode(); 11583 ViewParent ancestor = mParent; 11584 while (ancestor instanceof ViewGroup) { 11585 final ViewGroup vgAncestor = (ViewGroup) ancestor; 11586 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS 11587 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) { 11588 return true; 11589 } else { 11590 ancestor = vgAncestor.getParent(); 11591 } 11592 } 11593 return false; 11594 } 11595 11596 /** 11597 * Gets the mode for determining whether this View is important for accessibility. 11598 * A view is important for accessibility if it fires accessibility events and if it 11599 * is reported to accessibility services that query the screen. 11600 * 11601 * @return The mode for determining whether a view is important for accessibility, one 11602 * of {@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, {@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, 11603 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO}, or 11604 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}. 11605 * 11606 * @attr ref android.R.styleable#View_importantForAccessibility 11607 * 11608 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 11609 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 11610 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 11611 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 11612 */ 11613 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 11614 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 11615 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 11616 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 11617 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 11618 to = "noHideDescendants") 11619 }) 11620 public int getImportantForAccessibility() { 11621 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 11622 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 11623 } 11624 11625 /** 11626 * Sets the live region mode for this view. This indicates to accessibility 11627 * services whether they should automatically notify the user about changes 11628 * to the view's content description or text, or to the content descriptions 11629 * or text of the view's children (where applicable). 11630 * <p> 11631 * For example, in a login screen with a TextView that displays an "incorrect 11632 * password" notification, that view should be marked as a live region with 11633 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 11634 * <p> 11635 * To disable change notifications for this view, use 11636 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 11637 * mode for most views. 11638 * <p> 11639 * To indicate that the user should be notified of changes, use 11640 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 11641 * <p> 11642 * If the view's changes should interrupt ongoing speech and notify the user 11643 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 11644 * 11645 * @param mode The live region mode for this view, one of: 11646 * <ul> 11647 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 11648 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 11649 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 11650 * </ul> 11651 * @attr ref android.R.styleable#View_accessibilityLiveRegion 11652 */ 11653 public void setAccessibilityLiveRegion(int mode) { 11654 if (mode != getAccessibilityLiveRegion()) { 11655 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 11656 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 11657 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 11658 notifyViewAccessibilityStateChangedIfNeeded( 11659 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11660 } 11661 } 11662 11663 /** 11664 * Gets the live region mode for this View. 11665 * 11666 * @return The live region mode for the view. 11667 * 11668 * @attr ref android.R.styleable#View_accessibilityLiveRegion 11669 * 11670 * @see #setAccessibilityLiveRegion(int) 11671 */ 11672 public int getAccessibilityLiveRegion() { 11673 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 11674 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 11675 } 11676 11677 /** 11678 * Sets how to determine whether this view is important for accessibility 11679 * which is if it fires accessibility events and if it is reported to 11680 * accessibility services that query the screen. 11681 * 11682 * @param mode How to determine whether this view is important for accessibility. 11683 * 11684 * @attr ref android.R.styleable#View_importantForAccessibility 11685 * 11686 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 11687 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 11688 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 11689 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 11690 */ 11691 public void setImportantForAccessibility(int mode) { 11692 final int oldMode = getImportantForAccessibility(); 11693 if (mode != oldMode) { 11694 final boolean hideDescendants = 11695 mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; 11696 11697 // If this node or its descendants are no longer important, try to 11698 // clear accessibility focus. 11699 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) { 11700 final View focusHost = findAccessibilityFocusHost(hideDescendants); 11701 if (focusHost != null) { 11702 focusHost.clearAccessibilityFocus(); 11703 } 11704 } 11705 11706 // If we're moving between AUTO and another state, we might not need 11707 // to send a subtree changed notification. We'll store the computed 11708 // importance, since we'll need to check it later to make sure. 11709 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 11710 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 11711 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 11712 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 11713 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 11714 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 11715 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 11716 notifySubtreeAccessibilityStateChangedIfNeeded(); 11717 } else { 11718 notifyViewAccessibilityStateChangedIfNeeded( 11719 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11720 } 11721 } 11722 } 11723 11724 /** 11725 * Returns the view within this view's hierarchy that is hosting 11726 * accessibility focus. 11727 * 11728 * @param searchDescendants whether to search for focus in descendant views 11729 * @return the view hosting accessibility focus, or {@code null} 11730 */ 11731 private View findAccessibilityFocusHost(boolean searchDescendants) { 11732 if (isAccessibilityFocusedViewOrHost()) { 11733 return this; 11734 } 11735 11736 if (searchDescendants) { 11737 final ViewRootImpl viewRoot = getViewRootImpl(); 11738 if (viewRoot != null) { 11739 final View focusHost = viewRoot.getAccessibilityFocusedHost(); 11740 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 11741 return focusHost; 11742 } 11743 } 11744 } 11745 11746 return null; 11747 } 11748 11749 /** 11750 * Computes whether this view should be exposed for accessibility. In 11751 * general, views that are interactive or provide information are exposed 11752 * while views that serve only as containers are hidden. 11753 * <p> 11754 * If an ancestor of this view has importance 11755 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method 11756 * returns <code>false</code>. 11757 * <p> 11758 * Otherwise, the value is computed according to the view's 11759 * {@link #getImportantForAccessibility()} value: 11760 * <ol> 11761 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or 11762 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false 11763 * </code> 11764 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code> 11765 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if 11766 * view satisfies any of the following: 11767 * <ul> 11768 * <li>Is actionable, e.g. {@link #isClickable()}, 11769 * {@link #isLongClickable()}, or {@link #isFocusable()} 11770 * <li>Has an {@link AccessibilityDelegate} 11771 * <li>Has an interaction listener, e.g. {@link OnTouchListener}, 11772 * {@link OnKeyListener}, etc. 11773 * <li>Is an accessibility live region, e.g. 11774 * {@link #getAccessibilityLiveRegion()} is not 11775 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. 11776 * </ul> 11777 * <li>Has an accessibility pane title, see {@link #setAccessibilityPaneTitle}</li> 11778 * </ol> 11779 * 11780 * @return Whether the view is exposed for accessibility. 11781 * @see #setImportantForAccessibility(int) 11782 * @see #getImportantForAccessibility() 11783 */ 11784 public boolean isImportantForAccessibility() { 11785 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 11786 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 11787 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 11788 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 11789 return false; 11790 } 11791 11792 // Check parent mode to ensure we're not hidden. 11793 ViewParent parent = mParent; 11794 while (parent instanceof View) { 11795 if (((View) parent).getImportantForAccessibility() 11796 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 11797 return false; 11798 } 11799 parent = parent.getParent(); 11800 } 11801 11802 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 11803 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 11804 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE 11805 || isAccessibilityPane(); 11806 } 11807 11808 /** 11809 * Gets the parent for accessibility purposes. Note that the parent for 11810 * accessibility is not necessary the immediate parent. It is the first 11811 * predecessor that is important for accessibility. 11812 * 11813 * @return The parent for accessibility purposes. 11814 */ 11815 public ViewParent getParentForAccessibility() { 11816 if (mParent instanceof View) { 11817 View parentView = (View) mParent; 11818 if (parentView.includeForAccessibility()) { 11819 return mParent; 11820 } else { 11821 return mParent.getParentForAccessibility(); 11822 } 11823 } 11824 return null; 11825 } 11826 11827 /** @hide */ 11828 View getSelfOrParentImportantForA11y() { 11829 if (isImportantForAccessibility()) return this; 11830 ViewParent parent = getParentForAccessibility(); 11831 if (parent instanceof View) return (View) parent; 11832 return null; 11833 } 11834 11835 /** 11836 * Adds the children of this View relevant for accessibility to the given list 11837 * as output. Since some Views are not important for accessibility the added 11838 * child views are not necessarily direct children of this view, rather they are 11839 * the first level of descendants important for accessibility. 11840 * 11841 * @param outChildren The output list that will receive children for accessibility. 11842 */ 11843 public void addChildrenForAccessibility(ArrayList<View> outChildren) { 11844 11845 } 11846 11847 /** 11848 * Whether to regard this view for accessibility. A view is regarded for 11849 * accessibility if it is important for accessibility or the querying 11850 * accessibility service has explicitly requested that view not 11851 * important for accessibility are regarded. 11852 * 11853 * @return Whether to regard the view for accessibility. 11854 * 11855 * @hide 11856 */ 11857 public boolean includeForAccessibility() { 11858 if (mAttachInfo != null) { 11859 return (mAttachInfo.mAccessibilityFetchFlags 11860 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 11861 || isImportantForAccessibility(); 11862 } 11863 return false; 11864 } 11865 11866 /** 11867 * Returns whether the View is considered actionable from 11868 * accessibility perspective. Such view are important for 11869 * accessibility. 11870 * 11871 * @return True if the view is actionable for accessibility. 11872 * 11873 * @hide 11874 */ 11875 public boolean isActionableForAccessibility() { 11876 return (isClickable() || isLongClickable() || isFocusable()); 11877 } 11878 11879 /** 11880 * Returns whether the View has registered callbacks which makes it 11881 * important for accessibility. 11882 * 11883 * @return True if the view is actionable for accessibility. 11884 */ 11885 private boolean hasListenersForAccessibility() { 11886 ListenerInfo info = getListenerInfo(); 11887 return mTouchDelegate != null || info.mOnKeyListener != null 11888 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 11889 || info.mOnHoverListener != null || info.mOnDragListener != null; 11890 } 11891 11892 /** 11893 * Notifies that the accessibility state of this view changed. The change 11894 * is local to this view and does not represent structural changes such 11895 * as children and parent. For example, the view became focusable. The 11896 * notification is at at most once every 11897 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 11898 * to avoid unnecessary load to the system. Also once a view has a pending 11899 * notification this method is a NOP until the notification has been sent. 11900 * 11901 * @hide 11902 */ 11903 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 11904 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 11905 return; 11906 } 11907 11908 // Changes to views with a pane title count as window state changes, as the pane title 11909 // marks them as significant parts of the UI. 11910 if ((changeType != AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE) 11911 && isAccessibilityPane()) { 11912 // If the pane isn't visible, content changed events are sufficient unless we're 11913 // reporting that the view just disappeared 11914 if ((getVisibility() == VISIBLE) 11915 || (changeType == AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED)) { 11916 final AccessibilityEvent event = AccessibilityEvent.obtain(); 11917 event.setEventType(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 11918 event.setContentChangeTypes(changeType); 11919 event.setSource(this); 11920 onPopulateAccessibilityEvent(event); 11921 if (mParent != null) { 11922 try { 11923 mParent.requestSendAccessibilityEvent(this, event); 11924 } catch (AbstractMethodError e) { 11925 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() 11926 + " does not fully implement ViewParent", e); 11927 } 11928 } 11929 return; 11930 } 11931 } 11932 11933 // If this is a live region, we should send a subtree change event 11934 // from this view immediately. Otherwise, we can let it propagate up. 11935 if (getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE) { 11936 final AccessibilityEvent event = AccessibilityEvent.obtain(); 11937 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 11938 event.setContentChangeTypes(changeType); 11939 sendAccessibilityEventUnchecked(event); 11940 } else if (mParent != null) { 11941 try { 11942 mParent.notifySubtreeAccessibilityStateChanged(this, this, changeType); 11943 } catch (AbstractMethodError e) { 11944 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 11945 " does not fully implement ViewParent", e); 11946 } 11947 } 11948 } 11949 11950 /** 11951 * Notifies that the accessibility state of this view changed. The change 11952 * is *not* local to this view and does represent structural changes such 11953 * as children and parent. For example, the view size changed. The 11954 * notification is at at most once every 11955 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 11956 * to avoid unnecessary load to the system. Also once a view has a pending 11957 * notification this method is a NOP until the notification has been sent. 11958 * 11959 * @hide 11960 */ 11961 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 11962 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 11963 return; 11964 } 11965 11966 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 11967 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 11968 if (mParent != null) { 11969 try { 11970 mParent.notifySubtreeAccessibilityStateChanged( 11971 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 11972 } catch (AbstractMethodError e) { 11973 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 11974 " does not fully implement ViewParent", e); 11975 } 11976 } 11977 } 11978 } 11979 11980 /** 11981 * Change the visibility of the View without triggering any other changes. This is 11982 * important for transitions, where visibility changes should not adjust focus or 11983 * trigger a new layout. This is only used when the visibility has already been changed 11984 * and we need a transient value during an animation. When the animation completes, 11985 * the original visibility value is always restored. 11986 * 11987 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 11988 * @hide 11989 */ 11990 public void setTransitionVisibility(@Visibility int visibility) { 11991 mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility; 11992 } 11993 11994 /** 11995 * Reset the flag indicating the accessibility state of the subtree rooted 11996 * at this view changed. 11997 */ 11998 void resetSubtreeAccessibilityStateChanged() { 11999 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 12000 } 12001 12002 /** 12003 * Report an accessibility action to this view's parents for delegated processing. 12004 * 12005 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally 12006 * call this method to delegate an accessibility action to a supporting parent. If the parent 12007 * returns true from its 12008 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} 12009 * method this method will return true to signify that the action was consumed.</p> 12010 * 12011 * <p>This method is useful for implementing nested scrolling child views. If 12012 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action 12013 * a custom view implementation may invoke this method to allow a parent to consume the 12014 * scroll first. If this method returns true the custom view should skip its own scrolling 12015 * behavior.</p> 12016 * 12017 * @param action Accessibility action to delegate 12018 * @param arguments Optional action arguments 12019 * @return true if the action was consumed by a parent 12020 */ 12021 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) { 12022 for (ViewParent p = getParent(); p != null; p = p.getParent()) { 12023 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) { 12024 return true; 12025 } 12026 } 12027 return false; 12028 } 12029 12030 /** 12031 * Performs the specified accessibility action on the view. For 12032 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 12033 * <p> 12034 * If an {@link AccessibilityDelegate} has been specified via calling 12035 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 12036 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 12037 * is responsible for handling this call. 12038 * </p> 12039 * 12040 * <p>The default implementation will delegate 12041 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and 12042 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if 12043 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p> 12044 * 12045 * @param action The action to perform. 12046 * @param arguments Optional action arguments. 12047 * @return Whether the action was performed. 12048 */ 12049 public boolean performAccessibilityAction(int action, Bundle arguments) { 12050 if (mAccessibilityDelegate != null) { 12051 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 12052 } else { 12053 return performAccessibilityActionInternal(action, arguments); 12054 } 12055 } 12056 12057 /** 12058 * @see #performAccessibilityAction(int, Bundle) 12059 * 12060 * Note: Called from the default {@link AccessibilityDelegate}. 12061 * 12062 * @hide 12063 */ 12064 public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 12065 if (isNestedScrollingEnabled() 12066 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD 12067 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD 12068 || action == R.id.accessibilityActionScrollUp 12069 || action == R.id.accessibilityActionScrollLeft 12070 || action == R.id.accessibilityActionScrollDown 12071 || action == R.id.accessibilityActionScrollRight)) { 12072 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { 12073 return true; 12074 } 12075 } 12076 12077 switch (action) { 12078 case AccessibilityNodeInfo.ACTION_CLICK: { 12079 if (isClickable()) { 12080 performClickInternal(); 12081 return true; 12082 } 12083 } break; 12084 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 12085 if (isLongClickable()) { 12086 performLongClick(); 12087 return true; 12088 } 12089 } break; 12090 case AccessibilityNodeInfo.ACTION_FOCUS: { 12091 if (!hasFocus()) { 12092 // Get out of touch mode since accessibility 12093 // wants to move focus around. 12094 getViewRootImpl().ensureTouchMode(false); 12095 return requestFocus(); 12096 } 12097 } break; 12098 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 12099 if (hasFocus()) { 12100 clearFocus(); 12101 return !isFocused(); 12102 } 12103 } break; 12104 case AccessibilityNodeInfo.ACTION_SELECT: { 12105 if (!isSelected()) { 12106 setSelected(true); 12107 return isSelected(); 12108 } 12109 } break; 12110 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 12111 if (isSelected()) { 12112 setSelected(false); 12113 return !isSelected(); 12114 } 12115 } break; 12116 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 12117 if (!isAccessibilityFocused()) { 12118 return requestAccessibilityFocus(); 12119 } 12120 } break; 12121 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 12122 if (isAccessibilityFocused()) { 12123 clearAccessibilityFocus(); 12124 return true; 12125 } 12126 } break; 12127 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 12128 if (arguments != null) { 12129 final int granularity = arguments.getInt( 12130 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 12131 final boolean extendSelection = arguments.getBoolean( 12132 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 12133 return traverseAtGranularity(granularity, true, extendSelection); 12134 } 12135 } break; 12136 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 12137 if (arguments != null) { 12138 final int granularity = arguments.getInt( 12139 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 12140 final boolean extendSelection = arguments.getBoolean( 12141 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 12142 return traverseAtGranularity(granularity, false, extendSelection); 12143 } 12144 } break; 12145 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 12146 CharSequence text = getIterableTextForAccessibility(); 12147 if (text == null) { 12148 return false; 12149 } 12150 final int start = (arguments != null) ? arguments.getInt( 12151 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 12152 final int end = (arguments != null) ? arguments.getInt( 12153 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 12154 // Only cursor position can be specified (selection length == 0) 12155 if ((getAccessibilitySelectionStart() != start 12156 || getAccessibilitySelectionEnd() != end) 12157 && (start == end)) { 12158 setAccessibilitySelection(start, end); 12159 notifyViewAccessibilityStateChangedIfNeeded( 12160 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 12161 return true; 12162 } 12163 } break; 12164 case R.id.accessibilityActionShowOnScreen: { 12165 if (mAttachInfo != null) { 12166 final Rect r = mAttachInfo.mTmpInvalRect; 12167 getDrawingRect(r); 12168 return requestRectangleOnScreen(r, true); 12169 } 12170 } break; 12171 case R.id.accessibilityActionContextClick: { 12172 if (isContextClickable()) { 12173 performContextClick(); 12174 return true; 12175 } 12176 } break; 12177 case R.id.accessibilityActionShowTooltip: { 12178 if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) { 12179 // Tooltip already showing 12180 return false; 12181 } 12182 return showLongClickTooltip(0, 0); 12183 } 12184 case R.id.accessibilityActionHideTooltip: { 12185 if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) { 12186 // No tooltip showing 12187 return false; 12188 } 12189 hideTooltip(); 12190 return true; 12191 } 12192 } 12193 return false; 12194 } 12195 12196 private boolean traverseAtGranularity(int granularity, boolean forward, 12197 boolean extendSelection) { 12198 CharSequence text = getIterableTextForAccessibility(); 12199 if (text == null || text.length() == 0) { 12200 return false; 12201 } 12202 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 12203 if (iterator == null) { 12204 return false; 12205 } 12206 int current = getAccessibilitySelectionEnd(); 12207 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 12208 current = forward ? 0 : text.length(); 12209 } 12210 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 12211 if (range == null) { 12212 return false; 12213 } 12214 final int segmentStart = range[0]; 12215 final int segmentEnd = range[1]; 12216 int selectionStart; 12217 int selectionEnd; 12218 if (extendSelection && isAccessibilitySelectionExtendable()) { 12219 selectionStart = getAccessibilitySelectionStart(); 12220 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 12221 selectionStart = forward ? segmentStart : segmentEnd; 12222 } 12223 selectionEnd = forward ? segmentEnd : segmentStart; 12224 } else { 12225 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 12226 } 12227 setAccessibilitySelection(selectionStart, selectionEnd); 12228 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 12229 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 12230 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 12231 return true; 12232 } 12233 12234 /** 12235 * Gets the text reported for accessibility purposes. 12236 * 12237 * @return The accessibility text. 12238 * 12239 * @hide 12240 */ 12241 public CharSequence getIterableTextForAccessibility() { 12242 return getContentDescription(); 12243 } 12244 12245 /** 12246 * Gets whether accessibility selection can be extended. 12247 * 12248 * @return If selection is extensible. 12249 * 12250 * @hide 12251 */ 12252 public boolean isAccessibilitySelectionExtendable() { 12253 return false; 12254 } 12255 12256 /** 12257 * @hide 12258 */ 12259 public int getAccessibilitySelectionStart() { 12260 return mAccessibilityCursorPosition; 12261 } 12262 12263 /** 12264 * @hide 12265 */ 12266 public int getAccessibilitySelectionEnd() { 12267 return getAccessibilitySelectionStart(); 12268 } 12269 12270 /** 12271 * @hide 12272 */ 12273 public void setAccessibilitySelection(int start, int end) { 12274 if (start == end && end == mAccessibilityCursorPosition) { 12275 return; 12276 } 12277 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 12278 mAccessibilityCursorPosition = start; 12279 } else { 12280 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 12281 } 12282 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 12283 } 12284 12285 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 12286 int fromIndex, int toIndex) { 12287 if (mParent == null) { 12288 return; 12289 } 12290 AccessibilityEvent event = AccessibilityEvent.obtain( 12291 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 12292 onInitializeAccessibilityEvent(event); 12293 onPopulateAccessibilityEvent(event); 12294 event.setFromIndex(fromIndex); 12295 event.setToIndex(toIndex); 12296 event.setAction(action); 12297 event.setMovementGranularity(granularity); 12298 mParent.requestSendAccessibilityEvent(this, event); 12299 } 12300 12301 /** 12302 * @hide 12303 */ 12304 public TextSegmentIterator getIteratorForGranularity(int granularity) { 12305 switch (granularity) { 12306 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 12307 CharSequence text = getIterableTextForAccessibility(); 12308 if (text != null && text.length() > 0) { 12309 CharacterTextSegmentIterator iterator = 12310 CharacterTextSegmentIterator.getInstance( 12311 mContext.getResources().getConfiguration().locale); 12312 iterator.initialize(text.toString()); 12313 return iterator; 12314 } 12315 } break; 12316 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 12317 CharSequence text = getIterableTextForAccessibility(); 12318 if (text != null && text.length() > 0) { 12319 WordTextSegmentIterator iterator = 12320 WordTextSegmentIterator.getInstance( 12321 mContext.getResources().getConfiguration().locale); 12322 iterator.initialize(text.toString()); 12323 return iterator; 12324 } 12325 } break; 12326 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 12327 CharSequence text = getIterableTextForAccessibility(); 12328 if (text != null && text.length() > 0) { 12329 ParagraphTextSegmentIterator iterator = 12330 ParagraphTextSegmentIterator.getInstance(); 12331 iterator.initialize(text.toString()); 12332 return iterator; 12333 } 12334 } break; 12335 } 12336 return null; 12337 } 12338 12339 /** 12340 * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()} 12341 * and {@link #onFinishTemporaryDetach()}. 12342 * 12343 * <p>This method always returns {@code true} when called directly or indirectly from 12344 * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from 12345 * {@link #onFinishTemporaryDetach()}, however, depends on the OS version. 12346 * <ul> 12347 * <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li> 12348 * <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li> 12349 * </ul> 12350 * </p> 12351 * 12352 * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()} 12353 * and {@link #onFinishTemporaryDetach()}. 12354 */ isTemporarilyDetached()12355 public final boolean isTemporarilyDetached() { 12356 return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0; 12357 } 12358 12359 /** 12360 * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is 12361 * a container View. 12362 */ 12363 @CallSuper dispatchStartTemporaryDetach()12364 public void dispatchStartTemporaryDetach() { 12365 mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH; 12366 notifyEnterOrExitForAutoFillIfNeeded(false); 12367 onStartTemporaryDetach(); 12368 } 12369 12370 /** 12371 * This is called when a container is going to temporarily detach a child, with 12372 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 12373 * It will either be followed by {@link #onFinishTemporaryDetach()} or 12374 * {@link #onDetachedFromWindow()} when the container is done. 12375 */ onStartTemporaryDetach()12376 public void onStartTemporaryDetach() { 12377 removeUnsetPressCallback(); 12378 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 12379 } 12380 12381 /** 12382 * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is 12383 * a container View. 12384 */ 12385 @CallSuper dispatchFinishTemporaryDetach()12386 public void dispatchFinishTemporaryDetach() { 12387 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 12388 onFinishTemporaryDetach(); 12389 if (hasWindowFocus() && hasFocus()) { 12390 InputMethodManager.getInstance().focusIn(this); 12391 } 12392 notifyEnterOrExitForAutoFillIfNeeded(true); 12393 } 12394 12395 /** 12396 * Called after {@link #onStartTemporaryDetach} when the container is done 12397 * changing the view. 12398 */ onFinishTemporaryDetach()12399 public void onFinishTemporaryDetach() { 12400 } 12401 12402 /** 12403 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 12404 * for this view's window. Returns null if the view is not currently attached 12405 * to the window. Normally you will not need to use this directly, but 12406 * just use the standard high-level event callbacks like 12407 * {@link #onKeyDown(int, KeyEvent)}. 12408 */ getKeyDispatcherState()12409 public KeyEvent.DispatcherState getKeyDispatcherState() { 12410 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 12411 } 12412 12413 /** 12414 * Dispatch a key event before it is processed by any input method 12415 * associated with the view hierarchy. This can be used to intercept 12416 * key events in special situations before the IME consumes them; a 12417 * typical example would be handling the BACK key to update the application's 12418 * UI instead of allowing the IME to see it and close itself. 12419 * 12420 * @param event The key event to be dispatched. 12421 * @return True if the event was handled, false otherwise. 12422 */ dispatchKeyEventPreIme(KeyEvent event)12423 public boolean dispatchKeyEventPreIme(KeyEvent event) { 12424 return onKeyPreIme(event.getKeyCode(), event); 12425 } 12426 12427 /** 12428 * Dispatch a key event to the next view on the focus path. This path runs 12429 * from the top of the view tree down to the currently focused view. If this 12430 * view has focus, it will dispatch to itself. Otherwise it will dispatch 12431 * the next node down the focus path. This method also fires any key 12432 * listeners. 12433 * 12434 * @param event The key event to be dispatched. 12435 * @return True if the event was handled, false otherwise. 12436 */ dispatchKeyEvent(KeyEvent event)12437 public boolean dispatchKeyEvent(KeyEvent event) { 12438 if (mInputEventConsistencyVerifier != null) { 12439 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 12440 } 12441 12442 // Give any attached key listener a first crack at the event. 12443 //noinspection SimplifiableIfStatement 12444 ListenerInfo li = mListenerInfo; 12445 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 12446 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 12447 return true; 12448 } 12449 12450 if (event.dispatch(this, mAttachInfo != null 12451 ? mAttachInfo.mKeyDispatchState : null, this)) { 12452 return true; 12453 } 12454 12455 if (mInputEventConsistencyVerifier != null) { 12456 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 12457 } 12458 return false; 12459 } 12460 12461 /** 12462 * Dispatches a key shortcut event. 12463 * 12464 * @param event The key event to be dispatched. 12465 * @return True if the event was handled by the view, false otherwise. 12466 */ dispatchKeyShortcutEvent(KeyEvent event)12467 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 12468 return onKeyShortcut(event.getKeyCode(), event); 12469 } 12470 12471 /** 12472 * Pass the touch screen motion event down to the target view, or this 12473 * view if it is the target. 12474 * 12475 * @param event The motion event to be dispatched. 12476 * @return True if the event was handled by the view, false otherwise. 12477 */ dispatchTouchEvent(MotionEvent event)12478 public boolean dispatchTouchEvent(MotionEvent event) { 12479 // If the event should be handled by accessibility focus first. 12480 if (event.isTargetAccessibilityFocus()) { 12481 // We don't have focus or no virtual descendant has it, do not handle the event. 12482 if (!isAccessibilityFocusedViewOrHost()) { 12483 return false; 12484 } 12485 // We have focus and got the event, then use normal event dispatch. 12486 event.setTargetAccessibilityFocus(false); 12487 } 12488 12489 boolean result = false; 12490 12491 if (mInputEventConsistencyVerifier != null) { 12492 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 12493 } 12494 12495 final int actionMasked = event.getActionMasked(); 12496 if (actionMasked == MotionEvent.ACTION_DOWN) { 12497 // Defensive cleanup for new gesture 12498 stopNestedScroll(); 12499 } 12500 12501 if (onFilterTouchEventForSecurity(event)) { 12502 if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { 12503 result = true; 12504 } 12505 //noinspection SimplifiableIfStatement 12506 ListenerInfo li = mListenerInfo; 12507 if (li != null && li.mOnTouchListener != null 12508 && (mViewFlags & ENABLED_MASK) == ENABLED 12509 && li.mOnTouchListener.onTouch(this, event)) { 12510 result = true; 12511 } 12512 12513 if (!result && onTouchEvent(event)) { 12514 result = true; 12515 } 12516 } 12517 12518 if (!result && mInputEventConsistencyVerifier != null) { 12519 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 12520 } 12521 12522 // Clean up after nested scrolls if this is the end of a gesture; 12523 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest 12524 // of the gesture. 12525 if (actionMasked == MotionEvent.ACTION_UP || 12526 actionMasked == MotionEvent.ACTION_CANCEL || 12527 (actionMasked == MotionEvent.ACTION_DOWN && !result)) { 12528 stopNestedScroll(); 12529 } 12530 12531 return result; 12532 } 12533 isAccessibilityFocusedViewOrHost()12534 boolean isAccessibilityFocusedViewOrHost() { 12535 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl() 12536 .getAccessibilityFocusedHost() == this); 12537 } 12538 12539 /** 12540 * Filter the touch event to apply security policies. 12541 * 12542 * @param event The motion event to be filtered. 12543 * @return True if the event should be dispatched, false if the event should be dropped. 12544 * 12545 * @see #getFilterTouchesWhenObscured 12546 */ onFilterTouchEventForSecurity(MotionEvent event)12547 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 12548 //noinspection RedundantIfStatement 12549 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 12550 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 12551 // Window is obscured, drop this touch. 12552 return false; 12553 } 12554 return true; 12555 } 12556 12557 /** 12558 * Pass a trackball motion event down to the focused view. 12559 * 12560 * @param event The motion event to be dispatched. 12561 * @return True if the event was handled by the view, false otherwise. 12562 */ dispatchTrackballEvent(MotionEvent event)12563 public boolean dispatchTrackballEvent(MotionEvent event) { 12564 if (mInputEventConsistencyVerifier != null) { 12565 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 12566 } 12567 12568 return onTrackballEvent(event); 12569 } 12570 12571 /** 12572 * Pass a captured pointer event down to the focused view. 12573 * 12574 * @param event The motion event to be dispatched. 12575 * @return True if the event was handled by the view, false otherwise. 12576 */ dispatchCapturedPointerEvent(MotionEvent event)12577 public boolean dispatchCapturedPointerEvent(MotionEvent event) { 12578 if (!hasPointerCapture()) { 12579 return false; 12580 } 12581 //noinspection SimplifiableIfStatement 12582 ListenerInfo li = mListenerInfo; 12583 if (li != null && li.mOnCapturedPointerListener != null 12584 && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) { 12585 return true; 12586 } 12587 return onCapturedPointerEvent(event); 12588 } 12589 12590 /** 12591 * Dispatch a generic motion event. 12592 * <p> 12593 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 12594 * are delivered to the view under the pointer. All other generic motion events are 12595 * delivered to the focused view. Hover events are handled specially and are delivered 12596 * to {@link #onHoverEvent(MotionEvent)}. 12597 * </p> 12598 * 12599 * @param event The motion event to be dispatched. 12600 * @return True if the event was handled by the view, false otherwise. 12601 */ dispatchGenericMotionEvent(MotionEvent event)12602 public boolean dispatchGenericMotionEvent(MotionEvent event) { 12603 if (mInputEventConsistencyVerifier != null) { 12604 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 12605 } 12606 12607 final int source = event.getSource(); 12608 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 12609 final int action = event.getAction(); 12610 if (action == MotionEvent.ACTION_HOVER_ENTER 12611 || action == MotionEvent.ACTION_HOVER_MOVE 12612 || action == MotionEvent.ACTION_HOVER_EXIT) { 12613 if (dispatchHoverEvent(event)) { 12614 return true; 12615 } 12616 } else if (dispatchGenericPointerEvent(event)) { 12617 return true; 12618 } 12619 } else if (dispatchGenericFocusedEvent(event)) { 12620 return true; 12621 } 12622 12623 if (dispatchGenericMotionEventInternal(event)) { 12624 return true; 12625 } 12626 12627 if (mInputEventConsistencyVerifier != null) { 12628 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 12629 } 12630 return false; 12631 } 12632 dispatchGenericMotionEventInternal(MotionEvent event)12633 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 12634 //noinspection SimplifiableIfStatement 12635 ListenerInfo li = mListenerInfo; 12636 if (li != null && li.mOnGenericMotionListener != null 12637 && (mViewFlags & ENABLED_MASK) == ENABLED 12638 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 12639 return true; 12640 } 12641 12642 if (onGenericMotionEvent(event)) { 12643 return true; 12644 } 12645 12646 final int actionButton = event.getActionButton(); 12647 switch (event.getActionMasked()) { 12648 case MotionEvent.ACTION_BUTTON_PRESS: 12649 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress 12650 && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 12651 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 12652 if (performContextClick(event.getX(), event.getY())) { 12653 mInContextButtonPress = true; 12654 setPressed(true, event.getX(), event.getY()); 12655 removeTapCallback(); 12656 removeLongPressCallback(); 12657 return true; 12658 } 12659 } 12660 break; 12661 12662 case MotionEvent.ACTION_BUTTON_RELEASE: 12663 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 12664 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 12665 mInContextButtonPress = false; 12666 mIgnoreNextUpEvent = true; 12667 } 12668 break; 12669 } 12670 12671 if (mInputEventConsistencyVerifier != null) { 12672 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 12673 } 12674 return false; 12675 } 12676 12677 /** 12678 * Dispatch a hover event. 12679 * <p> 12680 * Do not call this method directly. 12681 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 12682 * </p> 12683 * 12684 * @param event The motion event to be dispatched. 12685 * @return True if the event was handled by the view, false otherwise. 12686 */ dispatchHoverEvent(MotionEvent event)12687 protected boolean dispatchHoverEvent(MotionEvent event) { 12688 ListenerInfo li = mListenerInfo; 12689 //noinspection SimplifiableIfStatement 12690 if (li != null && li.mOnHoverListener != null 12691 && (mViewFlags & ENABLED_MASK) == ENABLED 12692 && li.mOnHoverListener.onHover(this, event)) { 12693 return true; 12694 } 12695 12696 return onHoverEvent(event); 12697 } 12698 12699 /** 12700 * Returns true if the view has a child to which it has recently sent 12701 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 12702 * it does not have a hovered child, then it must be the innermost hovered view. 12703 * @hide 12704 */ hasHoveredChild()12705 protected boolean hasHoveredChild() { 12706 return false; 12707 } 12708 12709 /** 12710 * Dispatch a generic motion event to the view under the first pointer. 12711 * <p> 12712 * Do not call this method directly. 12713 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 12714 * </p> 12715 * 12716 * @param event The motion event to be dispatched. 12717 * @return True if the event was handled by the view, false otherwise. 12718 */ dispatchGenericPointerEvent(MotionEvent event)12719 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 12720 return false; 12721 } 12722 12723 /** 12724 * Dispatch a generic motion event to the currently focused view. 12725 * <p> 12726 * Do not call this method directly. 12727 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 12728 * </p> 12729 * 12730 * @param event The motion event to be dispatched. 12731 * @return True if the event was handled by the view, false otherwise. 12732 */ dispatchGenericFocusedEvent(MotionEvent event)12733 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 12734 return false; 12735 } 12736 12737 /** 12738 * Dispatch a pointer event. 12739 * <p> 12740 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 12741 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 12742 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 12743 * and should not be expected to handle other pointing device features. 12744 * </p> 12745 * 12746 * @param event The motion event to be dispatched. 12747 * @return True if the event was handled by the view, false otherwise. 12748 * @hide 12749 */ dispatchPointerEvent(MotionEvent event)12750 public final boolean dispatchPointerEvent(MotionEvent event) { 12751 if (event.isTouchEvent()) { 12752 return dispatchTouchEvent(event); 12753 } else { 12754 return dispatchGenericMotionEvent(event); 12755 } 12756 } 12757 12758 /** 12759 * Called when the window containing this view gains or loses window focus. 12760 * ViewGroups should override to route to their children. 12761 * 12762 * @param hasFocus True if the window containing this view now has focus, 12763 * false otherwise. 12764 */ dispatchWindowFocusChanged(boolean hasFocus)12765 public void dispatchWindowFocusChanged(boolean hasFocus) { 12766 onWindowFocusChanged(hasFocus); 12767 } 12768 12769 /** 12770 * Called when the window containing this view gains or loses focus. Note 12771 * that this is separate from view focus: to receive key events, both 12772 * your view and its window must have focus. If a window is displayed 12773 * on top of yours that takes input focus, then your own window will lose 12774 * focus but the view focus will remain unchanged. 12775 * 12776 * @param hasWindowFocus True if the window containing this view now has 12777 * focus, false otherwise. 12778 */ onWindowFocusChanged(boolean hasWindowFocus)12779 public void onWindowFocusChanged(boolean hasWindowFocus) { 12780 InputMethodManager imm = InputMethodManager.peekInstance(); 12781 if (!hasWindowFocus) { 12782 if (isPressed()) { 12783 setPressed(false); 12784 } 12785 mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; 12786 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 12787 imm.focusOut(this); 12788 } 12789 removeLongPressCallback(); 12790 removeTapCallback(); 12791 onFocusLost(); 12792 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 12793 imm.focusIn(this); 12794 } 12795 12796 refreshDrawableState(); 12797 } 12798 12799 /** 12800 * Returns true if this view is in a window that currently has window focus. 12801 * Note that this is not the same as the view itself having focus. 12802 * 12803 * @return True if this view is in a window that currently has window focus. 12804 */ hasWindowFocus()12805 public boolean hasWindowFocus() { 12806 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 12807 } 12808 12809 /** 12810 * Dispatch a view visibility change down the view hierarchy. 12811 * ViewGroups should override to route to their children. 12812 * @param changedView The view whose visibility changed. Could be 'this' or 12813 * an ancestor view. 12814 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 12815 * {@link #INVISIBLE} or {@link #GONE}. 12816 */ dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)12817 protected void dispatchVisibilityChanged(@NonNull View changedView, 12818 @Visibility int visibility) { 12819 onVisibilityChanged(changedView, visibility); 12820 } 12821 12822 /** 12823 * Called when the visibility of the view or an ancestor of the view has 12824 * changed. 12825 * 12826 * @param changedView The view whose visibility changed. May be 12827 * {@code this} or an ancestor view. 12828 * @param visibility The new visibility, one of {@link #VISIBLE}, 12829 * {@link #INVISIBLE} or {@link #GONE}. 12830 */ onVisibilityChanged(@onNull View changedView, @Visibility int visibility)12831 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { 12832 } 12833 12834 /** 12835 * Dispatch a hint about whether this view is displayed. For instance, when 12836 * a View moves out of the screen, it might receives a display hint indicating 12837 * the view is not displayed. Applications should not <em>rely</em> on this hint 12838 * as there is no guarantee that they will receive one. 12839 * 12840 * @param hint A hint about whether or not this view is displayed: 12841 * {@link #VISIBLE} or {@link #INVISIBLE}. 12842 */ dispatchDisplayHint(@isibility int hint)12843 public void dispatchDisplayHint(@Visibility int hint) { 12844 onDisplayHint(hint); 12845 } 12846 12847 /** 12848 * Gives this view a hint about whether is displayed or not. For instance, when 12849 * a View moves out of the screen, it might receives a display hint indicating 12850 * the view is not displayed. Applications should not <em>rely</em> on this hint 12851 * as there is no guarantee that they will receive one. 12852 * 12853 * @param hint A hint about whether or not this view is displayed: 12854 * {@link #VISIBLE} or {@link #INVISIBLE}. 12855 */ onDisplayHint(@isibility int hint)12856 protected void onDisplayHint(@Visibility int hint) { 12857 } 12858 12859 /** 12860 * Dispatch a window visibility change down the view hierarchy. 12861 * ViewGroups should override to route to their children. 12862 * 12863 * @param visibility The new visibility of the window. 12864 * 12865 * @see #onWindowVisibilityChanged(int) 12866 */ dispatchWindowVisibilityChanged(@isibility int visibility)12867 public void dispatchWindowVisibilityChanged(@Visibility int visibility) { 12868 onWindowVisibilityChanged(visibility); 12869 } 12870 12871 /** 12872 * Called when the window containing has change its visibility 12873 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 12874 * that this tells you whether or not your window is being made visible 12875 * to the window manager; this does <em>not</em> tell you whether or not 12876 * your window is obscured by other windows on the screen, even if it 12877 * is itself visible. 12878 * 12879 * @param visibility The new visibility of the window. 12880 */ onWindowVisibilityChanged(@isibility int visibility)12881 protected void onWindowVisibilityChanged(@Visibility int visibility) { 12882 if (visibility == VISIBLE) { 12883 initialAwakenScrollBars(); 12884 } 12885 } 12886 12887 /** 12888 * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by 12889 * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, 12890 * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}. 12891 * 12892 * @param isVisible true if this view's visibility to the user is uninterrupted by its 12893 * ancestors or by window visibility 12894 * @return true if this view is visible to the user, not counting clipping or overlapping 12895 */ dispatchVisibilityAggregated(boolean isVisible)12896 boolean dispatchVisibilityAggregated(boolean isVisible) { 12897 final boolean thisVisible = getVisibility() == VISIBLE; 12898 // If we're not visible but something is telling us we are, ignore it. 12899 if (thisVisible || !isVisible) { 12900 onVisibilityAggregated(isVisible); 12901 } 12902 return thisVisible && isVisible; 12903 } 12904 12905 /** 12906 * Called when the user-visibility of this View is potentially affected by a change 12907 * to this view itself, an ancestor view or the window this view is attached to. 12908 * 12909 * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE} 12910 * and this view's window is also visible 12911 */ 12912 @CallSuper onVisibilityAggregated(boolean isVisible)12913 public void onVisibilityAggregated(boolean isVisible) { 12914 // Update our internal visibility tracking so we can detect changes 12915 boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0; 12916 mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE) 12917 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE); 12918 if (isVisible && mAttachInfo != null) { 12919 initialAwakenScrollBars(); 12920 } 12921 12922 final Drawable dr = mBackground; 12923 if (dr != null && isVisible != dr.isVisible()) { 12924 dr.setVisible(isVisible, false); 12925 } 12926 final Drawable hl = mDefaultFocusHighlight; 12927 if (hl != null && isVisible != hl.isVisible()) { 12928 hl.setVisible(isVisible, false); 12929 } 12930 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 12931 if (fg != null && isVisible != fg.isVisible()) { 12932 fg.setVisible(isVisible, false); 12933 } 12934 12935 if (isAutofillable()) { 12936 AutofillManager afm = getAutofillManager(); 12937 12938 if (afm != null && getAutofillViewId() > LAST_APP_AUTOFILL_ID) { 12939 if (mVisibilityChangeForAutofillHandler != null) { 12940 mVisibilityChangeForAutofillHandler.removeMessages(0); 12941 } 12942 12943 // If the view is in the background but still part of the hierarchy this is called 12944 // with isVisible=false. Hence visibility==false requires further checks 12945 if (isVisible) { 12946 afm.notifyViewVisibilityChanged(this, true); 12947 } else { 12948 if (mVisibilityChangeForAutofillHandler == null) { 12949 mVisibilityChangeForAutofillHandler = 12950 new VisibilityChangeForAutofillHandler(afm, this); 12951 } 12952 // Let current operation (e.g. removal of the view from the hierarchy) 12953 // finish before checking state 12954 mVisibilityChangeForAutofillHandler.obtainMessage(0, this).sendToTarget(); 12955 } 12956 } 12957 } 12958 if (!TextUtils.isEmpty(getAccessibilityPaneTitle())) { 12959 if (isVisible != oldVisible) { 12960 notifyViewAccessibilityStateChangedIfNeeded(isVisible 12961 ? AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_APPEARED 12962 : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED); 12963 } 12964 } 12965 } 12966 12967 /** 12968 * Returns the current visibility of the window this view is attached to 12969 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 12970 * 12971 * @return Returns the current visibility of the view's window. 12972 */ 12973 @Visibility getWindowVisibility()12974 public int getWindowVisibility() { 12975 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 12976 } 12977 12978 /** 12979 * Retrieve the overall visible display size in which the window this view is 12980 * attached to has been positioned in. This takes into account screen 12981 * decorations above the window, for both cases where the window itself 12982 * is being position inside of them or the window is being placed under 12983 * then and covered insets are used for the window to position its content 12984 * inside. In effect, this tells you the available area where content can 12985 * be placed and remain visible to users. 12986 * 12987 * <p>This function requires an IPC back to the window manager to retrieve 12988 * the requested information, so should not be used in performance critical 12989 * code like drawing. 12990 * 12991 * @param outRect Filled in with the visible display frame. If the view 12992 * is not attached to a window, this is simply the raw display size. 12993 */ getWindowVisibleDisplayFrame(Rect outRect)12994 public void getWindowVisibleDisplayFrame(Rect outRect) { 12995 if (mAttachInfo != null) { 12996 try { 12997 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 12998 } catch (RemoteException e) { 12999 return; 13000 } 13001 // XXX This is really broken, and probably all needs to be done 13002 // in the window manager, and we need to know more about whether 13003 // we want the area behind or in front of the IME. 13004 final Rect insets = mAttachInfo.mVisibleInsets; 13005 outRect.left += insets.left; 13006 outRect.top += insets.top; 13007 outRect.right -= insets.right; 13008 outRect.bottom -= insets.bottom; 13009 return; 13010 } 13011 // The view is not attached to a display so we don't have a context. 13012 // Make a best guess about the display size. 13013 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 13014 d.getRectSize(outRect); 13015 } 13016 13017 /** 13018 * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window 13019 * is currently in without any insets. 13020 * 13021 * @hide 13022 */ getWindowDisplayFrame(Rect outRect)13023 public void getWindowDisplayFrame(Rect outRect) { 13024 if (mAttachInfo != null) { 13025 try { 13026 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 13027 } catch (RemoteException e) { 13028 return; 13029 } 13030 return; 13031 } 13032 // The view is not attached to a display so we don't have a context. 13033 // Make a best guess about the display size. 13034 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 13035 d.getRectSize(outRect); 13036 } 13037 13038 /** 13039 * Dispatch a notification about a resource configuration change down 13040 * the view hierarchy. 13041 * ViewGroups should override to route to their children. 13042 * 13043 * @param newConfig The new resource configuration. 13044 * 13045 * @see #onConfigurationChanged(android.content.res.Configuration) 13046 */ dispatchConfigurationChanged(Configuration newConfig)13047 public void dispatchConfigurationChanged(Configuration newConfig) { 13048 onConfigurationChanged(newConfig); 13049 } 13050 13051 /** 13052 * Called when the current configuration of the resources being used 13053 * by the application have changed. You can use this to decide when 13054 * to reload resources that can changed based on orientation and other 13055 * configuration characteristics. You only need to use this if you are 13056 * not relying on the normal {@link android.app.Activity} mechanism of 13057 * recreating the activity instance upon a configuration change. 13058 * 13059 * @param newConfig The new resource configuration. 13060 */ onConfigurationChanged(Configuration newConfig)13061 protected void onConfigurationChanged(Configuration newConfig) { 13062 } 13063 13064 /** 13065 * Private function to aggregate all per-view attributes in to the view 13066 * root. 13067 */ dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)13068 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 13069 performCollectViewAttributes(attachInfo, visibility); 13070 } 13071 performCollectViewAttributes(AttachInfo attachInfo, int visibility)13072 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 13073 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 13074 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 13075 attachInfo.mKeepScreenOn = true; 13076 } 13077 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 13078 ListenerInfo li = mListenerInfo; 13079 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 13080 attachInfo.mHasSystemUiListeners = true; 13081 } 13082 } 13083 } 13084 needGlobalAttributesUpdate(boolean force)13085 void needGlobalAttributesUpdate(boolean force) { 13086 final AttachInfo ai = mAttachInfo; 13087 if (ai != null && !ai.mRecomputeGlobalAttributes) { 13088 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 13089 || ai.mHasSystemUiListeners) { 13090 ai.mRecomputeGlobalAttributes = true; 13091 } 13092 } 13093 } 13094 13095 /** 13096 * Returns whether the device is currently in touch mode. Touch mode is entered 13097 * once the user begins interacting with the device by touch, and affects various 13098 * things like whether focus is always visible to the user. 13099 * 13100 * @return Whether the device is in touch mode. 13101 */ 13102 @ViewDebug.ExportedProperty isInTouchMode()13103 public boolean isInTouchMode() { 13104 if (mAttachInfo != null) { 13105 return mAttachInfo.mInTouchMode; 13106 } else { 13107 return ViewRootImpl.isInTouchMode(); 13108 } 13109 } 13110 13111 /** 13112 * Returns the context the view is running in, through which it can 13113 * access the current theme, resources, etc. 13114 * 13115 * @return The view's Context. 13116 */ 13117 @ViewDebug.CapturedViewProperty getContext()13118 public final Context getContext() { 13119 return mContext; 13120 } 13121 13122 /** 13123 * Handle a key event before it is processed by any input method 13124 * associated with the view hierarchy. This can be used to intercept 13125 * key events in special situations before the IME consumes them; a 13126 * typical example would be handling the BACK key to update the application's 13127 * UI instead of allowing the IME to see it and close itself. 13128 * 13129 * @param keyCode The value in event.getKeyCode(). 13130 * @param event Description of the key event. 13131 * @return If you handled the event, return true. If you want to allow the 13132 * event to be handled by the next receiver, return false. 13133 */ onKeyPreIme(int keyCode, KeyEvent event)13134 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 13135 return false; 13136 } 13137 13138 /** 13139 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 13140 * KeyEvent.Callback.onKeyDown()}: perform press of the view 13141 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 13142 * is released, if the view is enabled and clickable. 13143 * <p> 13144 * Key presses in software keyboards will generally NOT trigger this 13145 * listener, although some may elect to do so in some situations. Do not 13146 * rely on this to catch software key presses. 13147 * 13148 * @param keyCode a key code that represents the button pressed, from 13149 * {@link android.view.KeyEvent} 13150 * @param event the KeyEvent object that defines the button action 13151 */ onKeyDown(int keyCode, KeyEvent event)13152 public boolean onKeyDown(int keyCode, KeyEvent event) { 13153 if (KeyEvent.isConfirmKey(keyCode)) { 13154 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 13155 return true; 13156 } 13157 13158 if (event.getRepeatCount() == 0) { 13159 // Long clickable items don't necessarily have to be clickable. 13160 final boolean clickable = (mViewFlags & CLICKABLE) == CLICKABLE 13161 || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 13162 if (clickable || (mViewFlags & TOOLTIP) == TOOLTIP) { 13163 // For the purposes of menu anchoring and drawable hotspots, 13164 // key events are considered to be at the center of the view. 13165 final float x = getWidth() / 2f; 13166 final float y = getHeight() / 2f; 13167 if (clickable) { 13168 setPressed(true, x, y); 13169 } 13170 checkForLongClick(0, x, y); 13171 return true; 13172 } 13173 } 13174 } 13175 13176 return false; 13177 } 13178 13179 /** 13180 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 13181 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 13182 * the event). 13183 * <p>Key presses in software keyboards will generally NOT trigger this listener, 13184 * although some may elect to do so in some situations. Do not rely on this to 13185 * catch software key presses. 13186 */ onKeyLongPress(int keyCode, KeyEvent event)13187 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 13188 return false; 13189 } 13190 13191 /** 13192 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 13193 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 13194 * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER} 13195 * or {@link KeyEvent#KEYCODE_SPACE} is released. 13196 * <p>Key presses in software keyboards will generally NOT trigger this listener, 13197 * although some may elect to do so in some situations. Do not rely on this to 13198 * catch software key presses. 13199 * 13200 * @param keyCode A key code that represents the button pressed, from 13201 * {@link android.view.KeyEvent}. 13202 * @param event The KeyEvent object that defines the button action. 13203 */ onKeyUp(int keyCode, KeyEvent event)13204 public boolean onKeyUp(int keyCode, KeyEvent event) { 13205 if (KeyEvent.isConfirmKey(keyCode)) { 13206 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 13207 return true; 13208 } 13209 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 13210 setPressed(false); 13211 13212 if (!mHasPerformedLongPress) { 13213 // This is a tap, so remove the longpress check 13214 removeLongPressCallback(); 13215 if (!event.isCanceled()) { 13216 return performClickInternal(); 13217 } 13218 } 13219 } 13220 } 13221 return false; 13222 } 13223 13224 /** 13225 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 13226 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 13227 * the event). 13228 * <p>Key presses in software keyboards will generally NOT trigger this listener, 13229 * although some may elect to do so in some situations. Do not rely on this to 13230 * catch software key presses. 13231 * 13232 * @param keyCode A key code that represents the button pressed, from 13233 * {@link android.view.KeyEvent}. 13234 * @param repeatCount The number of times the action was made. 13235 * @param event The KeyEvent object that defines the button action. 13236 */ onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)13237 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 13238 return false; 13239 } 13240 13241 /** 13242 * Called on the focused view when a key shortcut event is not handled. 13243 * Override this method to implement local key shortcuts for the View. 13244 * Key shortcuts can also be implemented by setting the 13245 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 13246 * 13247 * @param keyCode The value in event.getKeyCode(). 13248 * @param event Description of the key event. 13249 * @return If you handled the event, return true. If you want to allow the 13250 * event to be handled by the next receiver, return false. 13251 */ onKeyShortcut(int keyCode, KeyEvent event)13252 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 13253 return false; 13254 } 13255 13256 /** 13257 * Check whether the called view is a text editor, in which case it 13258 * would make sense to automatically display a soft input window for 13259 * it. Subclasses should override this if they implement 13260 * {@link #onCreateInputConnection(EditorInfo)} to return true if 13261 * a call on that method would return a non-null InputConnection, and 13262 * they are really a first-class editor that the user would normally 13263 * start typing on when the go into a window containing your view. 13264 * 13265 * <p>The default implementation always returns false. This does 13266 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 13267 * will not be called or the user can not otherwise perform edits on your 13268 * view; it is just a hint to the system that this is not the primary 13269 * purpose of this view. 13270 * 13271 * @return Returns true if this view is a text editor, else false. 13272 */ onCheckIsTextEditor()13273 public boolean onCheckIsTextEditor() { 13274 return false; 13275 } 13276 13277 /** 13278 * Create a new InputConnection for an InputMethod to interact 13279 * with the view. The default implementation returns null, since it doesn't 13280 * support input methods. You can override this to implement such support. 13281 * This is only needed for views that take focus and text input. 13282 * 13283 * <p>When implementing this, you probably also want to implement 13284 * {@link #onCheckIsTextEditor()} to indicate you will return a 13285 * non-null InputConnection.</p> 13286 * 13287 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo} 13288 * object correctly and in its entirety, so that the connected IME can rely 13289 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart} 13290 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members 13291 * must be filled in with the correct cursor position for IMEs to work correctly 13292 * with your application.</p> 13293 * 13294 * @param outAttrs Fill in with attribute information about the connection. 13295 */ onCreateInputConnection(EditorInfo outAttrs)13296 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 13297 return null; 13298 } 13299 13300 /** 13301 * Called by the {@link android.view.inputmethod.InputMethodManager} 13302 * when a view who is not the current 13303 * input connection target is trying to make a call on the manager. The 13304 * default implementation returns false; you can override this to return 13305 * true for certain views if you are performing InputConnection proxying 13306 * to them. 13307 * @param view The View that is making the InputMethodManager call. 13308 * @return Return true to allow the call, false to reject. 13309 */ checkInputConnectionProxy(View view)13310 public boolean checkInputConnectionProxy(View view) { 13311 return false; 13312 } 13313 13314 /** 13315 * Show the context menu for this view. It is not safe to hold on to the 13316 * menu after returning from this method. 13317 * 13318 * You should normally not overload this method. Overload 13319 * {@link #onCreateContextMenu(ContextMenu)} or define an 13320 * {@link OnCreateContextMenuListener} to add items to the context menu. 13321 * 13322 * @param menu The context menu to populate 13323 */ createContextMenu(ContextMenu menu)13324 public void createContextMenu(ContextMenu menu) { 13325 ContextMenuInfo menuInfo = getContextMenuInfo(); 13326 13327 // Sets the current menu info so all items added to menu will have 13328 // my extra info set. 13329 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 13330 13331 onCreateContextMenu(menu); 13332 ListenerInfo li = mListenerInfo; 13333 if (li != null && li.mOnCreateContextMenuListener != null) { 13334 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 13335 } 13336 13337 // Clear the extra information so subsequent items that aren't mine don't 13338 // have my extra info. 13339 ((MenuBuilder)menu).setCurrentMenuInfo(null); 13340 13341 if (mParent != null) { 13342 mParent.createContextMenu(menu); 13343 } 13344 } 13345 13346 /** 13347 * Views should implement this if they have extra information to associate 13348 * with the context menu. The return result is supplied as a parameter to 13349 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 13350 * callback. 13351 * 13352 * @return Extra information about the item for which the context menu 13353 * should be shown. This information will vary across different 13354 * subclasses of View. 13355 */ getContextMenuInfo()13356 protected ContextMenuInfo getContextMenuInfo() { 13357 return null; 13358 } 13359 13360 /** 13361 * Views should implement this if the view itself is going to add items to 13362 * the context menu. 13363 * 13364 * @param menu the context menu to populate 13365 */ onCreateContextMenu(ContextMenu menu)13366 protected void onCreateContextMenu(ContextMenu menu) { 13367 } 13368 13369 /** 13370 * Implement this method to handle trackball motion events. The 13371 * <em>relative</em> movement of the trackball since the last event 13372 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 13373 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 13374 * that a movement of 1 corresponds to the user pressing one DPAD key (so 13375 * they will often be fractional values, representing the more fine-grained 13376 * movement information available from a trackball). 13377 * 13378 * @param event The motion event. 13379 * @return True if the event was handled, false otherwise. 13380 */ onTrackballEvent(MotionEvent event)13381 public boolean onTrackballEvent(MotionEvent event) { 13382 return false; 13383 } 13384 13385 /** 13386 * Implement this method to handle generic motion events. 13387 * <p> 13388 * Generic motion events describe joystick movements, mouse hovers, track pad 13389 * touches, scroll wheel movements and other input events. The 13390 * {@link MotionEvent#getSource() source} of the motion event specifies 13391 * the class of input that was received. Implementations of this method 13392 * must examine the bits in the source before processing the event. 13393 * The following code example shows how this is done. 13394 * </p><p> 13395 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 13396 * are delivered to the view under the pointer. All other generic motion events are 13397 * delivered to the focused view. 13398 * </p> 13399 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 13400 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 13401 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 13402 * // process the joystick movement... 13403 * return true; 13404 * } 13405 * } 13406 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 13407 * switch (event.getAction()) { 13408 * case MotionEvent.ACTION_HOVER_MOVE: 13409 * // process the mouse hover movement... 13410 * return true; 13411 * case MotionEvent.ACTION_SCROLL: 13412 * // process the scroll wheel movement... 13413 * return true; 13414 * } 13415 * } 13416 * return super.onGenericMotionEvent(event); 13417 * }</pre> 13418 * 13419 * @param event The generic motion event being processed. 13420 * @return True if the event was handled, false otherwise. 13421 */ onGenericMotionEvent(MotionEvent event)13422 public boolean onGenericMotionEvent(MotionEvent event) { 13423 return false; 13424 } 13425 13426 /** 13427 * Implement this method to handle hover events. 13428 * <p> 13429 * This method is called whenever a pointer is hovering into, over, or out of the 13430 * bounds of a view and the view is not currently being touched. 13431 * Hover events are represented as pointer events with action 13432 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 13433 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 13434 * </p> 13435 * <ul> 13436 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 13437 * when the pointer enters the bounds of the view.</li> 13438 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 13439 * when the pointer has already entered the bounds of the view and has moved.</li> 13440 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 13441 * when the pointer has exited the bounds of the view or when the pointer is 13442 * about to go down due to a button click, tap, or similar user action that 13443 * causes the view to be touched.</li> 13444 * </ul> 13445 * <p> 13446 * The view should implement this method to return true to indicate that it is 13447 * handling the hover event, such as by changing its drawable state. 13448 * </p><p> 13449 * The default implementation calls {@link #setHovered} to update the hovered state 13450 * of the view when a hover enter or hover exit event is received, if the view 13451 * is enabled and is clickable. The default implementation also sends hover 13452 * accessibility events. 13453 * </p> 13454 * 13455 * @param event The motion event that describes the hover. 13456 * @return True if the view handled the hover event. 13457 * 13458 * @see #isHovered 13459 * @see #setHovered 13460 * @see #onHoverChanged 13461 */ onHoverEvent(MotionEvent event)13462 public boolean onHoverEvent(MotionEvent event) { 13463 // The root view may receive hover (or touch) events that are outside the bounds of 13464 // the window. This code ensures that we only send accessibility events for 13465 // hovers that are actually within the bounds of the root view. 13466 final int action = event.getActionMasked(); 13467 if (!mSendingHoverAccessibilityEvents) { 13468 if ((action == MotionEvent.ACTION_HOVER_ENTER 13469 || action == MotionEvent.ACTION_HOVER_MOVE) 13470 && !hasHoveredChild() 13471 && pointInView(event.getX(), event.getY())) { 13472 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 13473 mSendingHoverAccessibilityEvents = true; 13474 } 13475 } else { 13476 if (action == MotionEvent.ACTION_HOVER_EXIT 13477 || (action == MotionEvent.ACTION_MOVE 13478 && !pointInView(event.getX(), event.getY()))) { 13479 mSendingHoverAccessibilityEvents = false; 13480 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 13481 } 13482 } 13483 13484 if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE) 13485 && event.isFromSource(InputDevice.SOURCE_MOUSE) 13486 && isOnScrollbar(event.getX(), event.getY())) { 13487 awakenScrollBars(); 13488 } 13489 13490 // If we consider ourself hoverable, or if we we're already hovered, 13491 // handle changing state in response to ENTER and EXIT events. 13492 if (isHoverable() || isHovered()) { 13493 switch (action) { 13494 case MotionEvent.ACTION_HOVER_ENTER: 13495 setHovered(true); 13496 break; 13497 case MotionEvent.ACTION_HOVER_EXIT: 13498 setHovered(false); 13499 break; 13500 } 13501 13502 // Dispatch the event to onGenericMotionEvent before returning true. 13503 // This is to provide compatibility with existing applications that 13504 // handled HOVER_MOVE events in onGenericMotionEvent and that would 13505 // break because of the new default handling for hoverable views 13506 // in onHoverEvent. 13507 // Note that onGenericMotionEvent will be called by default when 13508 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 13509 dispatchGenericMotionEventInternal(event); 13510 // The event was already handled by calling setHovered(), so always 13511 // return true. 13512 return true; 13513 } 13514 13515 return false; 13516 } 13517 13518 /** 13519 * Returns true if the view should handle {@link #onHoverEvent} 13520 * by calling {@link #setHovered} to change its hovered state. 13521 * 13522 * @return True if the view is hoverable. 13523 */ isHoverable()13524 private boolean isHoverable() { 13525 final int viewFlags = mViewFlags; 13526 if ((viewFlags & ENABLED_MASK) == DISABLED) { 13527 return false; 13528 } 13529 13530 return (viewFlags & CLICKABLE) == CLICKABLE 13531 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 13532 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 13533 } 13534 13535 /** 13536 * Returns true if the view is currently hovered. 13537 * 13538 * @return True if the view is currently hovered. 13539 * 13540 * @see #setHovered 13541 * @see #onHoverChanged 13542 */ 13543 @ViewDebug.ExportedProperty isHovered()13544 public boolean isHovered() { 13545 return (mPrivateFlags & PFLAG_HOVERED) != 0; 13546 } 13547 13548 /** 13549 * Sets whether the view is currently hovered. 13550 * <p> 13551 * Calling this method also changes the drawable state of the view. This 13552 * enables the view to react to hover by using different drawable resources 13553 * to change its appearance. 13554 * </p><p> 13555 * The {@link #onHoverChanged} method is called when the hovered state changes. 13556 * </p> 13557 * 13558 * @param hovered True if the view is hovered. 13559 * 13560 * @see #isHovered 13561 * @see #onHoverChanged 13562 */ setHovered(boolean hovered)13563 public void setHovered(boolean hovered) { 13564 if (hovered) { 13565 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 13566 mPrivateFlags |= PFLAG_HOVERED; 13567 refreshDrawableState(); 13568 onHoverChanged(true); 13569 } 13570 } else { 13571 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 13572 mPrivateFlags &= ~PFLAG_HOVERED; 13573 refreshDrawableState(); 13574 onHoverChanged(false); 13575 } 13576 } 13577 } 13578 13579 /** 13580 * Implement this method to handle hover state changes. 13581 * <p> 13582 * This method is called whenever the hover state changes as a result of a 13583 * call to {@link #setHovered}. 13584 * </p> 13585 * 13586 * @param hovered The current hover state, as returned by {@link #isHovered}. 13587 * 13588 * @see #isHovered 13589 * @see #setHovered 13590 */ onHoverChanged(boolean hovered)13591 public void onHoverChanged(boolean hovered) { 13592 } 13593 13594 /** 13595 * Handles scroll bar dragging by mouse input. 13596 * 13597 * @hide 13598 * @param event The motion event. 13599 * 13600 * @return true if the event was handled as a scroll bar dragging, false otherwise. 13601 */ handleScrollBarDragging(MotionEvent event)13602 protected boolean handleScrollBarDragging(MotionEvent event) { 13603 if (mScrollCache == null) { 13604 return false; 13605 } 13606 final float x = event.getX(); 13607 final float y = event.getY(); 13608 final int action = event.getAction(); 13609 if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING 13610 && action != MotionEvent.ACTION_DOWN) 13611 || !event.isFromSource(InputDevice.SOURCE_MOUSE) 13612 || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 13613 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 13614 return false; 13615 } 13616 13617 switch (action) { 13618 case MotionEvent.ACTION_MOVE: 13619 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) { 13620 return false; 13621 } 13622 if (mScrollCache.mScrollBarDraggingState 13623 == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) { 13624 final Rect bounds = mScrollCache.mScrollBarBounds; 13625 getVerticalScrollBarBounds(bounds, null); 13626 final int range = computeVerticalScrollRange(); 13627 final int offset = computeVerticalScrollOffset(); 13628 final int extent = computeVerticalScrollExtent(); 13629 13630 final int thumbLength = ScrollBarUtils.getThumbLength( 13631 bounds.height(), bounds.width(), extent, range); 13632 final int thumbOffset = ScrollBarUtils.getThumbOffset( 13633 bounds.height(), thumbLength, extent, range, offset); 13634 13635 final float diff = y - mScrollCache.mScrollBarDraggingPos; 13636 final float maxThumbOffset = bounds.height() - thumbLength; 13637 final float newThumbOffset = 13638 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 13639 final int height = getHeight(); 13640 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 13641 && height > 0 && extent > 0) { 13642 final int newY = Math.round((range - extent) 13643 / ((float)extent / height) * (newThumbOffset / maxThumbOffset)); 13644 if (newY != getScrollY()) { 13645 mScrollCache.mScrollBarDraggingPos = y; 13646 setScrollY(newY); 13647 } 13648 } 13649 return true; 13650 } 13651 if (mScrollCache.mScrollBarDraggingState 13652 == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) { 13653 final Rect bounds = mScrollCache.mScrollBarBounds; 13654 getHorizontalScrollBarBounds(bounds, null); 13655 final int range = computeHorizontalScrollRange(); 13656 final int offset = computeHorizontalScrollOffset(); 13657 final int extent = computeHorizontalScrollExtent(); 13658 13659 final int thumbLength = ScrollBarUtils.getThumbLength( 13660 bounds.width(), bounds.height(), extent, range); 13661 final int thumbOffset = ScrollBarUtils.getThumbOffset( 13662 bounds.width(), thumbLength, extent, range, offset); 13663 13664 final float diff = x - mScrollCache.mScrollBarDraggingPos; 13665 final float maxThumbOffset = bounds.width() - thumbLength; 13666 final float newThumbOffset = 13667 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 13668 final int width = getWidth(); 13669 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 13670 && width > 0 && extent > 0) { 13671 final int newX = Math.round((range - extent) 13672 / ((float)extent / width) * (newThumbOffset / maxThumbOffset)); 13673 if (newX != getScrollX()) { 13674 mScrollCache.mScrollBarDraggingPos = x; 13675 setScrollX(newX); 13676 } 13677 } 13678 return true; 13679 } 13680 case MotionEvent.ACTION_DOWN: 13681 if (mScrollCache.state == ScrollabilityCache.OFF) { 13682 return false; 13683 } 13684 if (isOnVerticalScrollbarThumb(x, y)) { 13685 mScrollCache.mScrollBarDraggingState = 13686 ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR; 13687 mScrollCache.mScrollBarDraggingPos = y; 13688 return true; 13689 } 13690 if (isOnHorizontalScrollbarThumb(x, y)) { 13691 mScrollCache.mScrollBarDraggingState = 13692 ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR; 13693 mScrollCache.mScrollBarDraggingPos = x; 13694 return true; 13695 } 13696 } 13697 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 13698 return false; 13699 } 13700 13701 /** 13702 * Implement this method to handle touch screen motion events. 13703 * <p> 13704 * If this method is used to detect click actions, it is recommended that 13705 * the actions be performed by implementing and calling 13706 * {@link #performClick()}. This will ensure consistent system behavior, 13707 * including: 13708 * <ul> 13709 * <li>obeying click sound preferences 13710 * <li>dispatching OnClickListener calls 13711 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 13712 * accessibility features are enabled 13713 * </ul> 13714 * 13715 * @param event The motion event. 13716 * @return True if the event was handled, false otherwise. 13717 */ onTouchEvent(MotionEvent event)13718 public boolean onTouchEvent(MotionEvent event) { 13719 final float x = event.getX(); 13720 final float y = event.getY(); 13721 final int viewFlags = mViewFlags; 13722 final int action = event.getAction(); 13723 13724 final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE 13725 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 13726 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 13727 13728 if ((viewFlags & ENABLED_MASK) == DISABLED) { 13729 if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 13730 setPressed(false); 13731 } 13732 mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; 13733 // A disabled view that is clickable still consumes the touch 13734 // events, it just doesn't respond to them. 13735 return clickable; 13736 } 13737 if (mTouchDelegate != null) { 13738 if (mTouchDelegate.onTouchEvent(event)) { 13739 return true; 13740 } 13741 } 13742 13743 if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) { 13744 switch (action) { 13745 case MotionEvent.ACTION_UP: 13746 mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; 13747 if ((viewFlags & TOOLTIP) == TOOLTIP) { 13748 handleTooltipUp(); 13749 } 13750 if (!clickable) { 13751 removeTapCallback(); 13752 removeLongPressCallback(); 13753 mInContextButtonPress = false; 13754 mHasPerformedLongPress = false; 13755 mIgnoreNextUpEvent = false; 13756 break; 13757 } 13758 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 13759 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 13760 // take focus if we don't have it already and we should in 13761 // touch mode. 13762 boolean focusTaken = false; 13763 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 13764 focusTaken = requestFocus(); 13765 } 13766 13767 if (prepressed) { 13768 // The button is being released before we actually 13769 // showed it as pressed. Make it show the pressed 13770 // state now (before scheduling the click) to ensure 13771 // the user sees it. 13772 setPressed(true, x, y); 13773 } 13774 13775 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { 13776 // This is a tap, so remove the longpress check 13777 removeLongPressCallback(); 13778 13779 // Only perform take click actions if we were in the pressed state 13780 if (!focusTaken) { 13781 // Use a Runnable and post this rather than calling 13782 // performClick directly. This lets other visual state 13783 // of the view update before click actions start. 13784 if (mPerformClick == null) { 13785 mPerformClick = new PerformClick(); 13786 } 13787 if (!post(mPerformClick)) { 13788 performClickInternal(); 13789 } 13790 } 13791 } 13792 13793 if (mUnsetPressedState == null) { 13794 mUnsetPressedState = new UnsetPressedState(); 13795 } 13796 13797 if (prepressed) { 13798 postDelayed(mUnsetPressedState, 13799 ViewConfiguration.getPressedStateDuration()); 13800 } else if (!post(mUnsetPressedState)) { 13801 // If the post failed, unpress right now 13802 mUnsetPressedState.run(); 13803 } 13804 13805 removeTapCallback(); 13806 } 13807 mIgnoreNextUpEvent = false; 13808 break; 13809 13810 case MotionEvent.ACTION_DOWN: 13811 if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) { 13812 mPrivateFlags3 |= PFLAG3_FINGER_DOWN; 13813 } 13814 mHasPerformedLongPress = false; 13815 13816 if (!clickable) { 13817 checkForLongClick(0, x, y); 13818 break; 13819 } 13820 13821 if (performButtonActionOnTouchDown(event)) { 13822 break; 13823 } 13824 13825 // Walk up the hierarchy to determine if we're inside a scrolling container. 13826 boolean isInScrollingContainer = isInScrollingContainer(); 13827 13828 // For views inside a scrolling container, delay the pressed feedback for 13829 // a short period in case this is a scroll. 13830 if (isInScrollingContainer) { 13831 mPrivateFlags |= PFLAG_PREPRESSED; 13832 if (mPendingCheckForTap == null) { 13833 mPendingCheckForTap = new CheckForTap(); 13834 } 13835 mPendingCheckForTap.x = event.getX(); 13836 mPendingCheckForTap.y = event.getY(); 13837 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 13838 } else { 13839 // Not inside a scrolling container, so show the feedback right away 13840 setPressed(true, x, y); 13841 checkForLongClick(0, x, y); 13842 } 13843 break; 13844 13845 case MotionEvent.ACTION_CANCEL: 13846 if (clickable) { 13847 setPressed(false); 13848 } 13849 removeTapCallback(); 13850 removeLongPressCallback(); 13851 mInContextButtonPress = false; 13852 mHasPerformedLongPress = false; 13853 mIgnoreNextUpEvent = false; 13854 mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; 13855 break; 13856 13857 case MotionEvent.ACTION_MOVE: 13858 if (clickable) { 13859 drawableHotspotChanged(x, y); 13860 } 13861 13862 // Be lenient about moving outside of buttons 13863 if (!pointInView(x, y, mTouchSlop)) { 13864 // Outside button 13865 // Remove any future long press/tap checks 13866 removeTapCallback(); 13867 removeLongPressCallback(); 13868 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 13869 setPressed(false); 13870 } 13871 mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN; 13872 } 13873 break; 13874 } 13875 13876 return true; 13877 } 13878 13879 return false; 13880 } 13881 13882 /** 13883 * @hide 13884 */ isInScrollingContainer()13885 public boolean isInScrollingContainer() { 13886 ViewParent p = getParent(); 13887 while (p != null && p instanceof ViewGroup) { 13888 if (((ViewGroup) p).shouldDelayChildPressedState()) { 13889 return true; 13890 } 13891 p = p.getParent(); 13892 } 13893 return false; 13894 } 13895 13896 /** 13897 * Remove the longpress detection timer. 13898 */ removeLongPressCallback()13899 private void removeLongPressCallback() { 13900 if (mPendingCheckForLongPress != null) { 13901 removeCallbacks(mPendingCheckForLongPress); 13902 } 13903 } 13904 13905 /** 13906 * Remove the pending click action 13907 */ removePerformClickCallback()13908 private void removePerformClickCallback() { 13909 if (mPerformClick != null) { 13910 removeCallbacks(mPerformClick); 13911 } 13912 } 13913 13914 /** 13915 * Remove the prepress detection timer. 13916 */ removeUnsetPressCallback()13917 private void removeUnsetPressCallback() { 13918 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 13919 setPressed(false); 13920 removeCallbacks(mUnsetPressedState); 13921 } 13922 } 13923 13924 /** 13925 * Remove the tap detection timer. 13926 */ removeTapCallback()13927 private void removeTapCallback() { 13928 if (mPendingCheckForTap != null) { 13929 mPrivateFlags &= ~PFLAG_PREPRESSED; 13930 removeCallbacks(mPendingCheckForTap); 13931 } 13932 } 13933 13934 /** 13935 * Cancels a pending long press. Your subclass can use this if you 13936 * want the context menu to come up if the user presses and holds 13937 * at the same place, but you don't want it to come up if they press 13938 * and then move around enough to cause scrolling. 13939 */ cancelLongPress()13940 public void cancelLongPress() { 13941 removeLongPressCallback(); 13942 13943 /* 13944 * The prepressed state handled by the tap callback is a display 13945 * construct, but the tap callback will post a long press callback 13946 * less its own timeout. Remove it here. 13947 */ 13948 removeTapCallback(); 13949 } 13950 13951 /** 13952 * Sets the TouchDelegate for this View. 13953 */ setTouchDelegate(TouchDelegate delegate)13954 public void setTouchDelegate(TouchDelegate delegate) { 13955 mTouchDelegate = delegate; 13956 } 13957 13958 /** 13959 * Gets the TouchDelegate for this View. 13960 */ getTouchDelegate()13961 public TouchDelegate getTouchDelegate() { 13962 return mTouchDelegate; 13963 } 13964 13965 /** 13966 * Request unbuffered dispatch of the given stream of MotionEvents to this View. 13967 * 13968 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input 13969 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're 13970 * available. This method should only be called for touch events. 13971 * 13972 * <p class="note">This api is not intended for most applications. Buffered dispatch 13973 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent 13974 * streams will not improve your input latency. Side effects include: increased latency, 13975 * jittery scrolls and inability to take advantage of system resampling. Talk to your input 13976 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for 13977 * you.</p> 13978 */ requestUnbufferedDispatch(MotionEvent event)13979 public final void requestUnbufferedDispatch(MotionEvent event) { 13980 final int action = event.getAction(); 13981 if (mAttachInfo == null 13982 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE 13983 || !event.isTouchEvent()) { 13984 return; 13985 } 13986 mAttachInfo.mUnbufferedDispatchRequested = true; 13987 } 13988 hasSize()13989 private boolean hasSize() { 13990 return (mBottom > mTop) && (mRight > mLeft); 13991 } 13992 canTakeFocus()13993 private boolean canTakeFocus() { 13994 return ((mViewFlags & VISIBILITY_MASK) == VISIBLE) 13995 && ((mViewFlags & FOCUSABLE) == FOCUSABLE) 13996 && ((mViewFlags & ENABLED_MASK) == ENABLED) 13997 && (sCanFocusZeroSized || !isLayoutValid() || hasSize()); 13998 } 13999 14000 /** 14001 * Set flags controlling behavior of this view. 14002 * 14003 * @param flags Constant indicating the value which should be set 14004 * @param mask Constant indicating the bit range that should be changed 14005 */ setFlags(int flags, int mask)14006 void setFlags(int flags, int mask) { 14007 final boolean accessibilityEnabled = 14008 AccessibilityManager.getInstance(mContext).isEnabled(); 14009 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 14010 14011 int old = mViewFlags; 14012 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 14013 14014 int changed = mViewFlags ^ old; 14015 if (changed == 0) { 14016 return; 14017 } 14018 int privateFlags = mPrivateFlags; 14019 boolean shouldNotifyFocusableAvailable = false; 14020 14021 // If focusable is auto, update the FOCUSABLE bit. 14022 int focusableChangedByAuto = 0; 14023 if (((mViewFlags & FOCUSABLE_AUTO) != 0) 14024 && (changed & (FOCUSABLE_MASK | CLICKABLE)) != 0) { 14025 // Heuristic only takes into account whether view is clickable. 14026 final int newFocus; 14027 if ((mViewFlags & CLICKABLE) != 0) { 14028 newFocus = FOCUSABLE; 14029 } else { 14030 newFocus = NOT_FOCUSABLE; 14031 } 14032 mViewFlags = (mViewFlags & ~FOCUSABLE) | newFocus; 14033 focusableChangedByAuto = (old & FOCUSABLE) ^ (newFocus & FOCUSABLE); 14034 changed = (changed & ~FOCUSABLE) | focusableChangedByAuto; 14035 } 14036 14037 /* Check if the FOCUSABLE bit has changed */ 14038 if (((changed & FOCUSABLE) != 0) && ((privateFlags & PFLAG_HAS_BOUNDS) != 0)) { 14039 if (((old & FOCUSABLE) == FOCUSABLE) 14040 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 14041 /* Give up focus if we are no longer focusable */ 14042 clearFocus(); 14043 if (mParent instanceof ViewGroup) { 14044 ((ViewGroup) mParent).clearFocusedInCluster(); 14045 } 14046 } else if (((old & FOCUSABLE) == NOT_FOCUSABLE) 14047 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 14048 /* 14049 * Tell the view system that we are now available to take focus 14050 * if no one else already has it. 14051 */ 14052 if (mParent != null) { 14053 ViewRootImpl viewRootImpl = getViewRootImpl(); 14054 if (!sAutoFocusableOffUIThreadWontNotifyParents 14055 || focusableChangedByAuto == 0 14056 || viewRootImpl == null 14057 || viewRootImpl.mThread == Thread.currentThread()) { 14058 shouldNotifyFocusableAvailable = canTakeFocus(); 14059 } 14060 } 14061 } 14062 } 14063 14064 final int newVisibility = flags & VISIBILITY_MASK; 14065 if (newVisibility == VISIBLE) { 14066 if ((changed & VISIBILITY_MASK) != 0) { 14067 /* 14068 * If this view is becoming visible, invalidate it in case it changed while 14069 * it was not visible. Marking it drawn ensures that the invalidation will 14070 * go through. 14071 */ 14072 mPrivateFlags |= PFLAG_DRAWN; 14073 invalidate(true); 14074 14075 needGlobalAttributesUpdate(true); 14076 14077 // a view becoming visible is worth notifying the parent about in case nothing has 14078 // focus. Even if this specific view isn't focusable, it may contain something that 14079 // is, so let the root view try to give this focus if nothing else does. 14080 shouldNotifyFocusableAvailable = hasSize(); 14081 } 14082 } 14083 14084 if ((changed & ENABLED_MASK) != 0) { 14085 if ((mViewFlags & ENABLED_MASK) == ENABLED) { 14086 // a view becoming enabled should notify the parent as long as the view is also 14087 // visible and the parent wasn't already notified by becoming visible during this 14088 // setFlags invocation. 14089 shouldNotifyFocusableAvailable = canTakeFocus(); 14090 } else { 14091 if (isFocused()) clearFocus(); 14092 } 14093 } 14094 14095 if (shouldNotifyFocusableAvailable && mParent != null) { 14096 mParent.focusableViewAvailable(this); 14097 } 14098 14099 /* Check if the GONE bit has changed */ 14100 if ((changed & GONE) != 0) { 14101 needGlobalAttributesUpdate(false); 14102 requestLayout(); 14103 14104 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 14105 if (hasFocus()) { 14106 clearFocus(); 14107 if (mParent instanceof ViewGroup) { 14108 ((ViewGroup) mParent).clearFocusedInCluster(); 14109 } 14110 } 14111 clearAccessibilityFocus(); 14112 destroyDrawingCache(); 14113 if (mParent instanceof View) { 14114 // GONE views noop invalidation, so invalidate the parent 14115 ((View) mParent).invalidate(true); 14116 } 14117 // Mark the view drawn to ensure that it gets invalidated properly the next 14118 // time it is visible and gets invalidated 14119 mPrivateFlags |= PFLAG_DRAWN; 14120 } 14121 if (mAttachInfo != null) { 14122 mAttachInfo.mViewVisibilityChanged = true; 14123 } 14124 } 14125 14126 /* Check if the VISIBLE bit has changed */ 14127 if ((changed & INVISIBLE) != 0) { 14128 needGlobalAttributesUpdate(false); 14129 /* 14130 * If this view is becoming invisible, set the DRAWN flag so that 14131 * the next invalidate() will not be skipped. 14132 */ 14133 mPrivateFlags |= PFLAG_DRAWN; 14134 14135 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 14136 // root view becoming invisible shouldn't clear focus and accessibility focus 14137 if (getRootView() != this) { 14138 if (hasFocus()) { 14139 clearFocus(); 14140 if (mParent instanceof ViewGroup) { 14141 ((ViewGroup) mParent).clearFocusedInCluster(); 14142 } 14143 } 14144 clearAccessibilityFocus(); 14145 } 14146 } 14147 if (mAttachInfo != null) { 14148 mAttachInfo.mViewVisibilityChanged = true; 14149 } 14150 } 14151 14152 if ((changed & VISIBILITY_MASK) != 0) { 14153 // If the view is invisible, cleanup its display list to free up resources 14154 if (newVisibility != VISIBLE && mAttachInfo != null) { 14155 cleanupDraw(); 14156 } 14157 14158 if (mParent instanceof ViewGroup) { 14159 ((ViewGroup) mParent).onChildVisibilityChanged(this, 14160 (changed & VISIBILITY_MASK), newVisibility); 14161 ((View) mParent).invalidate(true); 14162 } else if (mParent != null) { 14163 mParent.invalidateChild(this, null); 14164 } 14165 14166 if (mAttachInfo != null) { 14167 dispatchVisibilityChanged(this, newVisibility); 14168 14169 // Aggregated visibility changes are dispatched to attached views 14170 // in visible windows where the parent is currently shown/drawn 14171 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot), 14172 // discounting clipping or overlapping. This makes it a good place 14173 // to change animation states. 14174 if (mParent != null && getWindowVisibility() == VISIBLE && 14175 ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { 14176 dispatchVisibilityAggregated(newVisibility == VISIBLE); 14177 } 14178 notifySubtreeAccessibilityStateChangedIfNeeded(); 14179 } 14180 } 14181 14182 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 14183 destroyDrawingCache(); 14184 } 14185 14186 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 14187 destroyDrawingCache(); 14188 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 14189 invalidateParentCaches(); 14190 } 14191 14192 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 14193 destroyDrawingCache(); 14194 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 14195 } 14196 14197 if ((changed & DRAW_MASK) != 0) { 14198 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 14199 if (mBackground != null 14200 || mDefaultFocusHighlight != null 14201 || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) { 14202 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 14203 } else { 14204 mPrivateFlags |= PFLAG_SKIP_DRAW; 14205 } 14206 } else { 14207 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 14208 } 14209 requestLayout(); 14210 invalidate(true); 14211 } 14212 14213 if ((changed & KEEP_SCREEN_ON) != 0) { 14214 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 14215 mParent.recomputeViewAttributes(this); 14216 } 14217 } 14218 14219 if (accessibilityEnabled) { 14220 // If we're an accessibility pane and the visibility changed, we already have sent 14221 // a state change, so we really don't need to report other changes. 14222 if (isAccessibilityPane()) { 14223 changed &= ~VISIBILITY_MASK; 14224 } 14225 if ((changed & FOCUSABLE) != 0 || (changed & VISIBILITY_MASK) != 0 14226 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0 14227 || (changed & CONTEXT_CLICKABLE) != 0) { 14228 if (oldIncludeForAccessibility != includeForAccessibility()) { 14229 notifySubtreeAccessibilityStateChangedIfNeeded(); 14230 } else { 14231 notifyViewAccessibilityStateChangedIfNeeded( 14232 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 14233 } 14234 } else if ((changed & ENABLED_MASK) != 0) { 14235 notifyViewAccessibilityStateChangedIfNeeded( 14236 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 14237 } 14238 } 14239 } 14240 14241 /** 14242 * Change the view's z order in the tree, so it's on top of other sibling 14243 * views. This ordering change may affect layout, if the parent container 14244 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 14245 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 14246 * method should be followed by calls to {@link #requestLayout()} and 14247 * {@link View#invalidate()} on the view's parent to force the parent to redraw 14248 * with the new child ordering. 14249 * 14250 * @see ViewGroup#bringChildToFront(View) 14251 */ bringToFront()14252 public void bringToFront() { 14253 if (mParent != null) { 14254 mParent.bringChildToFront(this); 14255 } 14256 } 14257 14258 /** 14259 * This is called in response to an internal scroll in this view (i.e., the 14260 * view scrolled its own contents). This is typically as a result of 14261 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 14262 * called. 14263 * 14264 * @param l Current horizontal scroll origin. 14265 * @param t Current vertical scroll origin. 14266 * @param oldl Previous horizontal scroll origin. 14267 * @param oldt Previous vertical scroll origin. 14268 */ onScrollChanged(int l, int t, int oldl, int oldt)14269 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 14270 notifySubtreeAccessibilityStateChangedIfNeeded(); 14271 14272 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 14273 postSendViewScrolledAccessibilityEventCallback(l - oldl, t - oldt); 14274 } 14275 14276 mBackgroundSizeChanged = true; 14277 mDefaultFocusHighlightSizeChanged = true; 14278 if (mForegroundInfo != null) { 14279 mForegroundInfo.mBoundsChanged = true; 14280 } 14281 14282 final AttachInfo ai = mAttachInfo; 14283 if (ai != null) { 14284 ai.mViewScrollChanged = true; 14285 } 14286 14287 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) { 14288 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); 14289 } 14290 } 14291 14292 /** 14293 * Interface definition for a callback to be invoked when the scroll 14294 * X or Y positions of a view change. 14295 * <p> 14296 * <b>Note:</b> Some views handle scrolling independently from View and may 14297 * have their own separate listeners for scroll-type events. For example, 14298 * {@link android.widget.ListView ListView} allows clients to register an 14299 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 14300 * to listen for changes in list scroll position. 14301 * 14302 * @see #setOnScrollChangeListener(View.OnScrollChangeListener) 14303 */ 14304 public interface OnScrollChangeListener { 14305 /** 14306 * Called when the scroll position of a view changes. 14307 * 14308 * @param v The view whose scroll position has changed. 14309 * @param scrollX Current horizontal scroll origin. 14310 * @param scrollY Current vertical scroll origin. 14311 * @param oldScrollX Previous horizontal scroll origin. 14312 * @param oldScrollY Previous vertical scroll origin. 14313 */ onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)14314 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); 14315 } 14316 14317 /** 14318 * Interface definition for a callback to be invoked when the layout bounds of a view 14319 * changes due to layout processing. 14320 */ 14321 public interface OnLayoutChangeListener { 14322 /** 14323 * Called when the layout bounds of a view changes due to layout processing. 14324 * 14325 * @param v The view whose bounds have changed. 14326 * @param left The new value of the view's left property. 14327 * @param top The new value of the view's top property. 14328 * @param right The new value of the view's right property. 14329 * @param bottom The new value of the view's bottom property. 14330 * @param oldLeft The previous value of the view's left property. 14331 * @param oldTop The previous value of the view's top property. 14332 * @param oldRight The previous value of the view's right property. 14333 * @param oldBottom The previous value of the view's bottom property. 14334 */ onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)14335 void onLayoutChange(View v, int left, int top, int right, int bottom, 14336 int oldLeft, int oldTop, int oldRight, int oldBottom); 14337 } 14338 14339 /** 14340 * This is called during layout when the size of this view has changed. If 14341 * you were just added to the view hierarchy, you're called with the old 14342 * values of 0. 14343 * 14344 * @param w Current width of this view. 14345 * @param h Current height of this view. 14346 * @param oldw Old width of this view. 14347 * @param oldh Old height of this view. 14348 */ onSizeChanged(int w, int h, int oldw, int oldh)14349 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 14350 } 14351 14352 /** 14353 * Called by draw to draw the child views. This may be overridden 14354 * by derived classes to gain control just before its children are drawn 14355 * (but after its own view has been drawn). 14356 * @param canvas the canvas on which to draw the view 14357 */ dispatchDraw(Canvas canvas)14358 protected void dispatchDraw(Canvas canvas) { 14359 14360 } 14361 14362 /** 14363 * Gets the parent of this view. Note that the parent is a 14364 * ViewParent and not necessarily a View. 14365 * 14366 * @return Parent of this view. 14367 */ getParent()14368 public final ViewParent getParent() { 14369 return mParent; 14370 } 14371 14372 /** 14373 * Set the horizontal scrolled position of your view. This will cause a call to 14374 * {@link #onScrollChanged(int, int, int, int)} and the view will be 14375 * invalidated. 14376 * @param value the x position to scroll to 14377 */ setScrollX(int value)14378 public void setScrollX(int value) { 14379 scrollTo(value, mScrollY); 14380 } 14381 14382 /** 14383 * Set the vertical scrolled position of your view. This will cause a call to 14384 * {@link #onScrollChanged(int, int, int, int)} and the view will be 14385 * invalidated. 14386 * @param value the y position to scroll to 14387 */ setScrollY(int value)14388 public void setScrollY(int value) { 14389 scrollTo(mScrollX, value); 14390 } 14391 14392 /** 14393 * Return the scrolled left position of this view. This is the left edge of 14394 * the displayed part of your view. You do not need to draw any pixels 14395 * farther left, since those are outside of the frame of your view on 14396 * screen. 14397 * 14398 * @return The left edge of the displayed part of your view, in pixels. 14399 */ getScrollX()14400 public final int getScrollX() { 14401 return mScrollX; 14402 } 14403 14404 /** 14405 * Return the scrolled top position of this view. This is the top edge of 14406 * the displayed part of your view. You do not need to draw any pixels above 14407 * it, since those are outside of the frame of your view on screen. 14408 * 14409 * @return The top edge of the displayed part of your view, in pixels. 14410 */ getScrollY()14411 public final int getScrollY() { 14412 return mScrollY; 14413 } 14414 14415 /** 14416 * Return the width of your view. 14417 * 14418 * @return The width of your view, in pixels. 14419 */ 14420 @ViewDebug.ExportedProperty(category = "layout") getWidth()14421 public final int getWidth() { 14422 return mRight - mLeft; 14423 } 14424 14425 /** 14426 * Return the height of your view. 14427 * 14428 * @return The height of your view, in pixels. 14429 */ 14430 @ViewDebug.ExportedProperty(category = "layout") getHeight()14431 public final int getHeight() { 14432 return mBottom - mTop; 14433 } 14434 14435 /** 14436 * Return the visible drawing bounds of your view. Fills in the output 14437 * rectangle with the values from getScrollX(), getScrollY(), 14438 * getWidth(), and getHeight(). These bounds do not account for any 14439 * transformation properties currently set on the view, such as 14440 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 14441 * 14442 * @param outRect The (scrolled) drawing bounds of the view. 14443 */ getDrawingRect(Rect outRect)14444 public void getDrawingRect(Rect outRect) { 14445 outRect.left = mScrollX; 14446 outRect.top = mScrollY; 14447 outRect.right = mScrollX + (mRight - mLeft); 14448 outRect.bottom = mScrollY + (mBottom - mTop); 14449 } 14450 14451 /** 14452 * Like {@link #getMeasuredWidthAndState()}, but only returns the 14453 * raw width component (that is the result is masked by 14454 * {@link #MEASURED_SIZE_MASK}). 14455 * 14456 * @return The raw measured width of this view. 14457 */ getMeasuredWidth()14458 public final int getMeasuredWidth() { 14459 return mMeasuredWidth & MEASURED_SIZE_MASK; 14460 } 14461 14462 /** 14463 * Return the full width measurement information for this view as computed 14464 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 14465 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 14466 * This should be used during measurement and layout calculations only. Use 14467 * {@link #getWidth()} to see how wide a view is after layout. 14468 * 14469 * @return The measured width of this view as a bit mask. 14470 */ 14471 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 14472 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 14473 name = "MEASURED_STATE_TOO_SMALL"), 14474 }) getMeasuredWidthAndState()14475 public final int getMeasuredWidthAndState() { 14476 return mMeasuredWidth; 14477 } 14478 14479 /** 14480 * Like {@link #getMeasuredHeightAndState()}, but only returns the 14481 * raw height component (that is the result is masked by 14482 * {@link #MEASURED_SIZE_MASK}). 14483 * 14484 * @return The raw measured height of this view. 14485 */ getMeasuredHeight()14486 public final int getMeasuredHeight() { 14487 return mMeasuredHeight & MEASURED_SIZE_MASK; 14488 } 14489 14490 /** 14491 * Return the full height measurement information for this view as computed 14492 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 14493 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 14494 * This should be used during measurement and layout calculations only. Use 14495 * {@link #getHeight()} to see how wide a view is after layout. 14496 * 14497 * @return The measured height of this view as a bit mask. 14498 */ 14499 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 14500 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 14501 name = "MEASURED_STATE_TOO_SMALL"), 14502 }) getMeasuredHeightAndState()14503 public final int getMeasuredHeightAndState() { 14504 return mMeasuredHeight; 14505 } 14506 14507 /** 14508 * Return only the state bits of {@link #getMeasuredWidthAndState()} 14509 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 14510 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 14511 * and the height component is at the shifted bits 14512 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 14513 */ getMeasuredState()14514 public final int getMeasuredState() { 14515 return (mMeasuredWidth&MEASURED_STATE_MASK) 14516 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 14517 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 14518 } 14519 14520 /** 14521 * The transform matrix of this view, which is calculated based on the current 14522 * rotation, scale, and pivot properties. 14523 * 14524 * @see #getRotation() 14525 * @see #getScaleX() 14526 * @see #getScaleY() 14527 * @see #getPivotX() 14528 * @see #getPivotY() 14529 * @return The current transform matrix for the view 14530 */ getMatrix()14531 public Matrix getMatrix() { 14532 ensureTransformationInfo(); 14533 final Matrix matrix = mTransformationInfo.mMatrix; 14534 mRenderNode.getMatrix(matrix); 14535 return matrix; 14536 } 14537 14538 /** 14539 * Returns true if the transform matrix is the identity matrix. 14540 * Recomputes the matrix if necessary. 14541 * 14542 * @return True if the transform matrix is the identity matrix, false otherwise. 14543 */ hasIdentityMatrix()14544 final boolean hasIdentityMatrix() { 14545 return mRenderNode.hasIdentityMatrix(); 14546 } 14547 ensureTransformationInfo()14548 void ensureTransformationInfo() { 14549 if (mTransformationInfo == null) { 14550 mTransformationInfo = new TransformationInfo(); 14551 } 14552 } 14553 14554 /** 14555 * Utility method to retrieve the inverse of the current mMatrix property. 14556 * We cache the matrix to avoid recalculating it when transform properties 14557 * have not changed. 14558 * 14559 * @return The inverse of the current matrix of this view. 14560 * @hide 14561 */ getInverseMatrix()14562 public final Matrix getInverseMatrix() { 14563 ensureTransformationInfo(); 14564 if (mTransformationInfo.mInverseMatrix == null) { 14565 mTransformationInfo.mInverseMatrix = new Matrix(); 14566 } 14567 final Matrix matrix = mTransformationInfo.mInverseMatrix; 14568 mRenderNode.getInverseMatrix(matrix); 14569 return matrix; 14570 } 14571 14572 /** 14573 * Gets the distance along the Z axis from the camera to this view. 14574 * 14575 * @see #setCameraDistance(float) 14576 * 14577 * @return The distance along the Z axis. 14578 */ getCameraDistance()14579 public float getCameraDistance() { 14580 final float dpi = mResources.getDisplayMetrics().densityDpi; 14581 return -(mRenderNode.getCameraDistance() * dpi); 14582 } 14583 14584 /** 14585 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 14586 * views are drawn) from the camera to this view. The camera's distance 14587 * affects 3D transformations, for instance rotations around the X and Y 14588 * axis. If the rotationX or rotationY properties are changed and this view is 14589 * large (more than half the size of the screen), it is recommended to always 14590 * use a camera distance that's greater than the height (X axis rotation) or 14591 * the width (Y axis rotation) of this view.</p> 14592 * 14593 * <p>The distance of the camera from the view plane can have an affect on the 14594 * perspective distortion of the view when it is rotated around the x or y axis. 14595 * For example, a large distance will result in a large viewing angle, and there 14596 * will not be much perspective distortion of the view as it rotates. A short 14597 * distance may cause much more perspective distortion upon rotation, and can 14598 * also result in some drawing artifacts if the rotated view ends up partially 14599 * behind the camera (which is why the recommendation is to use a distance at 14600 * least as far as the size of the view, if the view is to be rotated.)</p> 14601 * 14602 * <p>The distance is expressed in "depth pixels." The default distance depends 14603 * on the screen density. For instance, on a medium density display, the 14604 * default distance is 1280. On a high density display, the default distance 14605 * is 1920.</p> 14606 * 14607 * <p>If you want to specify a distance that leads to visually consistent 14608 * results across various densities, use the following formula:</p> 14609 * <pre> 14610 * float scale = context.getResources().getDisplayMetrics().density; 14611 * view.setCameraDistance(distance * scale); 14612 * </pre> 14613 * 14614 * <p>The density scale factor of a high density display is 1.5, 14615 * and 1920 = 1280 * 1.5.</p> 14616 * 14617 * @param distance The distance in "depth pixels", if negative the opposite 14618 * value is used 14619 * 14620 * @see #setRotationX(float) 14621 * @see #setRotationY(float) 14622 */ setCameraDistance(float distance)14623 public void setCameraDistance(float distance) { 14624 final float dpi = mResources.getDisplayMetrics().densityDpi; 14625 14626 invalidateViewProperty(true, false); 14627 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); 14628 invalidateViewProperty(false, false); 14629 14630 invalidateParentIfNeededAndWasQuickRejected(); 14631 } 14632 14633 /** 14634 * The degrees that the view is rotated around the pivot point. 14635 * 14636 * @see #setRotation(float) 14637 * @see #getPivotX() 14638 * @see #getPivotY() 14639 * 14640 * @return The degrees of rotation. 14641 */ 14642 @ViewDebug.ExportedProperty(category = "drawing") getRotation()14643 public float getRotation() { 14644 return mRenderNode.getRotation(); 14645 } 14646 14647 /** 14648 * Sets the degrees that the view is rotated around the pivot point. Increasing values 14649 * result in clockwise rotation. 14650 * 14651 * @param rotation The degrees of rotation. 14652 * 14653 * @see #getRotation() 14654 * @see #getPivotX() 14655 * @see #getPivotY() 14656 * @see #setRotationX(float) 14657 * @see #setRotationY(float) 14658 * 14659 * @attr ref android.R.styleable#View_rotation 14660 */ setRotation(float rotation)14661 public void setRotation(float rotation) { 14662 if (rotation != getRotation()) { 14663 // Double-invalidation is necessary to capture view's old and new areas 14664 invalidateViewProperty(true, false); 14665 mRenderNode.setRotation(rotation); 14666 invalidateViewProperty(false, true); 14667 14668 invalidateParentIfNeededAndWasQuickRejected(); 14669 notifySubtreeAccessibilityStateChangedIfNeeded(); 14670 } 14671 } 14672 14673 /** 14674 * The degrees that the view is rotated around the vertical axis through the pivot point. 14675 * 14676 * @see #getPivotX() 14677 * @see #getPivotY() 14678 * @see #setRotationY(float) 14679 * 14680 * @return The degrees of Y rotation. 14681 */ 14682 @ViewDebug.ExportedProperty(category = "drawing") getRotationY()14683 public float getRotationY() { 14684 return mRenderNode.getRotationY(); 14685 } 14686 14687 /** 14688 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 14689 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 14690 * down the y axis. 14691 * 14692 * When rotating large views, it is recommended to adjust the camera distance 14693 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 14694 * 14695 * @param rotationY The degrees of Y rotation. 14696 * 14697 * @see #getRotationY() 14698 * @see #getPivotX() 14699 * @see #getPivotY() 14700 * @see #setRotation(float) 14701 * @see #setRotationX(float) 14702 * @see #setCameraDistance(float) 14703 * 14704 * @attr ref android.R.styleable#View_rotationY 14705 */ setRotationY(float rotationY)14706 public void setRotationY(float rotationY) { 14707 if (rotationY != getRotationY()) { 14708 invalidateViewProperty(true, false); 14709 mRenderNode.setRotationY(rotationY); 14710 invalidateViewProperty(false, true); 14711 14712 invalidateParentIfNeededAndWasQuickRejected(); 14713 notifySubtreeAccessibilityStateChangedIfNeeded(); 14714 } 14715 } 14716 14717 /** 14718 * The degrees that the view is rotated around the horizontal axis through the pivot point. 14719 * 14720 * @see #getPivotX() 14721 * @see #getPivotY() 14722 * @see #setRotationX(float) 14723 * 14724 * @return The degrees of X rotation. 14725 */ 14726 @ViewDebug.ExportedProperty(category = "drawing") getRotationX()14727 public float getRotationX() { 14728 return mRenderNode.getRotationX(); 14729 } 14730 14731 /** 14732 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 14733 * Increasing values result in clockwise rotation from the viewpoint of looking down the 14734 * x axis. 14735 * 14736 * When rotating large views, it is recommended to adjust the camera distance 14737 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 14738 * 14739 * @param rotationX The degrees of X rotation. 14740 * 14741 * @see #getRotationX() 14742 * @see #getPivotX() 14743 * @see #getPivotY() 14744 * @see #setRotation(float) 14745 * @see #setRotationY(float) 14746 * @see #setCameraDistance(float) 14747 * 14748 * @attr ref android.R.styleable#View_rotationX 14749 */ setRotationX(float rotationX)14750 public void setRotationX(float rotationX) { 14751 if (rotationX != getRotationX()) { 14752 invalidateViewProperty(true, false); 14753 mRenderNode.setRotationX(rotationX); 14754 invalidateViewProperty(false, true); 14755 14756 invalidateParentIfNeededAndWasQuickRejected(); 14757 notifySubtreeAccessibilityStateChangedIfNeeded(); 14758 } 14759 } 14760 14761 /** 14762 * The amount that the view is scaled in x around the pivot point, as a proportion of 14763 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 14764 * 14765 * <p>By default, this is 1.0f. 14766 * 14767 * @see #getPivotX() 14768 * @see #getPivotY() 14769 * @return The scaling factor. 14770 */ 14771 @ViewDebug.ExportedProperty(category = "drawing") getScaleX()14772 public float getScaleX() { 14773 return mRenderNode.getScaleX(); 14774 } 14775 14776 /** 14777 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 14778 * the view's unscaled width. A value of 1 means that no scaling is applied. 14779 * 14780 * @param scaleX The scaling factor. 14781 * @see #getPivotX() 14782 * @see #getPivotY() 14783 * 14784 * @attr ref android.R.styleable#View_scaleX 14785 */ setScaleX(float scaleX)14786 public void setScaleX(float scaleX) { 14787 if (scaleX != getScaleX()) { 14788 scaleX = sanitizeFloatPropertyValue(scaleX, "scaleX"); 14789 invalidateViewProperty(true, false); 14790 mRenderNode.setScaleX(scaleX); 14791 invalidateViewProperty(false, true); 14792 14793 invalidateParentIfNeededAndWasQuickRejected(); 14794 notifySubtreeAccessibilityStateChangedIfNeeded(); 14795 } 14796 } 14797 14798 /** 14799 * The amount that the view is scaled in y around the pivot point, as a proportion of 14800 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 14801 * 14802 * <p>By default, this is 1.0f. 14803 * 14804 * @see #getPivotX() 14805 * @see #getPivotY() 14806 * @return The scaling factor. 14807 */ 14808 @ViewDebug.ExportedProperty(category = "drawing") getScaleY()14809 public float getScaleY() { 14810 return mRenderNode.getScaleY(); 14811 } 14812 14813 /** 14814 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 14815 * the view's unscaled width. A value of 1 means that no scaling is applied. 14816 * 14817 * @param scaleY The scaling factor. 14818 * @see #getPivotX() 14819 * @see #getPivotY() 14820 * 14821 * @attr ref android.R.styleable#View_scaleY 14822 */ setScaleY(float scaleY)14823 public void setScaleY(float scaleY) { 14824 if (scaleY != getScaleY()) { 14825 scaleY = sanitizeFloatPropertyValue(scaleY, "scaleY"); 14826 invalidateViewProperty(true, false); 14827 mRenderNode.setScaleY(scaleY); 14828 invalidateViewProperty(false, true); 14829 14830 invalidateParentIfNeededAndWasQuickRejected(); 14831 notifySubtreeAccessibilityStateChangedIfNeeded(); 14832 } 14833 } 14834 14835 /** 14836 * The x location of the point around which the view is {@link #setRotation(float) rotated} 14837 * and {@link #setScaleX(float) scaled}. 14838 * 14839 * @see #getRotation() 14840 * @see #getScaleX() 14841 * @see #getScaleY() 14842 * @see #getPivotY() 14843 * @return The x location of the pivot point. 14844 * 14845 * @attr ref android.R.styleable#View_transformPivotX 14846 */ 14847 @ViewDebug.ExportedProperty(category = "drawing") getPivotX()14848 public float getPivotX() { 14849 return mRenderNode.getPivotX(); 14850 } 14851 14852 /** 14853 * Sets the x location of the point around which the view is 14854 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 14855 * By default, the pivot point is centered on the object. 14856 * Setting this property disables this behavior and causes the view to use only the 14857 * explicitly set pivotX and pivotY values. 14858 * 14859 * @param pivotX The x location of the pivot point. 14860 * @see #getRotation() 14861 * @see #getScaleX() 14862 * @see #getScaleY() 14863 * @see #getPivotY() 14864 * 14865 * @attr ref android.R.styleable#View_transformPivotX 14866 */ setPivotX(float pivotX)14867 public void setPivotX(float pivotX) { 14868 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { 14869 invalidateViewProperty(true, false); 14870 mRenderNode.setPivotX(pivotX); 14871 invalidateViewProperty(false, true); 14872 14873 invalidateParentIfNeededAndWasQuickRejected(); 14874 } 14875 } 14876 14877 /** 14878 * The y location of the point around which the view is {@link #setRotation(float) rotated} 14879 * and {@link #setScaleY(float) scaled}. 14880 * 14881 * @see #getRotation() 14882 * @see #getScaleX() 14883 * @see #getScaleY() 14884 * @see #getPivotY() 14885 * @return The y location of the pivot point. 14886 * 14887 * @attr ref android.R.styleable#View_transformPivotY 14888 */ 14889 @ViewDebug.ExportedProperty(category = "drawing") getPivotY()14890 public float getPivotY() { 14891 return mRenderNode.getPivotY(); 14892 } 14893 14894 /** 14895 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 14896 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 14897 * Setting this property disables this behavior and causes the view to use only the 14898 * explicitly set pivotX and pivotY values. 14899 * 14900 * @param pivotY The y location of the pivot point. 14901 * @see #getRotation() 14902 * @see #getScaleX() 14903 * @see #getScaleY() 14904 * @see #getPivotY() 14905 * 14906 * @attr ref android.R.styleable#View_transformPivotY 14907 */ setPivotY(float pivotY)14908 public void setPivotY(float pivotY) { 14909 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { 14910 invalidateViewProperty(true, false); 14911 mRenderNode.setPivotY(pivotY); 14912 invalidateViewProperty(false, true); 14913 14914 invalidateParentIfNeededAndWasQuickRejected(); 14915 } 14916 } 14917 14918 /** 14919 * Returns whether or not a pivot has been set by a call to {@link #setPivotX(float)} or 14920 * {@link #setPivotY(float)}. If no pivot has been set then the pivot will be the center 14921 * of the view. 14922 * 14923 * @return True if a pivot has been set, false if the default pivot is being used 14924 */ isPivotSet()14925 public boolean isPivotSet() { 14926 return mRenderNode.isPivotExplicitlySet(); 14927 } 14928 14929 /** 14930 * Clears any pivot previously set by a call to {@link #setPivotX(float)} or 14931 * {@link #setPivotY(float)}. After calling this {@link #isPivotSet()} will be false 14932 * and the pivot used for rotation will return to default of being centered on the view. 14933 */ resetPivot()14934 public void resetPivot() { 14935 if (mRenderNode.resetPivot()) { 14936 invalidateViewProperty(false, false); 14937 } 14938 } 14939 14940 /** 14941 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 14942 * completely transparent and 1 means the view is completely opaque. 14943 * 14944 * <p>By default this is 1.0f. 14945 * @return The opacity of the view. 14946 */ 14947 @ViewDebug.ExportedProperty(category = "drawing") getAlpha()14948 public float getAlpha() { 14949 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 14950 } 14951 14952 /** 14953 * Sets the behavior for overlapping rendering for this view (see {@link 14954 * #hasOverlappingRendering()} for more details on this behavior). Calling this method 14955 * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass, 14956 * providing the value which is then used internally. That is, when {@link 14957 * #forceHasOverlappingRendering(boolean)} is called, the value of {@link 14958 * #hasOverlappingRendering()} is ignored and the value passed into this method is used 14959 * instead. 14960 * 14961 * @param hasOverlappingRendering The value for overlapping rendering to be used internally 14962 * instead of that returned by {@link #hasOverlappingRendering()}. 14963 * 14964 * @attr ref android.R.styleable#View_forceHasOverlappingRendering 14965 */ forceHasOverlappingRendering(boolean hasOverlappingRendering)14966 public void forceHasOverlappingRendering(boolean hasOverlappingRendering) { 14967 mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED; 14968 if (hasOverlappingRendering) { 14969 mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 14970 } else { 14971 mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 14972 } 14973 } 14974 14975 /** 14976 * Returns the value for overlapping rendering that is used internally. This is either 14977 * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or 14978 * the return value of {@link #hasOverlappingRendering()}, otherwise. 14979 * 14980 * @return The value for overlapping rendering being used internally. 14981 */ getHasOverlappingRendering()14982 public final boolean getHasOverlappingRendering() { 14983 return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ? 14984 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 : 14985 hasOverlappingRendering(); 14986 } 14987 14988 /** 14989 * Returns whether this View has content which overlaps. 14990 * 14991 * <p>This function, intended to be overridden by specific View types, is an optimization when 14992 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 14993 * an offscreen buffer and then composited into place, which can be expensive. If the view has 14994 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 14995 * directly. An example of overlapping rendering is a TextView with a background image, such as 14996 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 14997 * ImageView with only the foreground image. The default implementation returns true; subclasses 14998 * should override if they have cases which can be optimized.</p> 14999 * 15000 * <p><strong>Note:</strong> The return value of this method is ignored if {@link 15001 * #forceHasOverlappingRendering(boolean)} has been called on this view.</p> 15002 * 15003 * @return true if the content in this view might overlap, false otherwise. 15004 */ 15005 @ViewDebug.ExportedProperty(category = "drawing") hasOverlappingRendering()15006 public boolean hasOverlappingRendering() { 15007 return true; 15008 } 15009 15010 /** 15011 * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is 15012 * completely transparent and 1 means the view is completely opaque. 15013 * 15014 * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1) 15015 * can have significant performance implications, especially for large views. It is best to use 15016 * the alpha property sparingly and transiently, as in the case of fading animations.</p> 15017 * 15018 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 15019 * strongly recommended for performance reasons to either override 15020 * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a 15021 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration 15022 * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below, 15023 * the default path for rendering an unlayered View with alpha could add multiple milliseconds 15024 * of rendering cost, even for simple or small views. Starting with 15025 * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically 15026 * applied to the view at the rendering level.</p> 15027 * 15028 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 15029 * responsible for applying the opacity itself.</p> 15030 * 15031 * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if 15032 * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is 15033 * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an 15034 * alpha value less than 1.0 will supersede the alpha of the layer paint.</p> 15035 * 15036 * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha 15037 * value will clip a View to its bounds, unless the View returns <code>false</code> from 15038 * {@link #hasOverlappingRendering}.</p> 15039 * 15040 * @param alpha The opacity of the view. 15041 * 15042 * @see #hasOverlappingRendering() 15043 * @see #setLayerType(int, android.graphics.Paint) 15044 * 15045 * @attr ref android.R.styleable#View_alpha 15046 */ setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)15047 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) { 15048 ensureTransformationInfo(); 15049 if (mTransformationInfo.mAlpha != alpha) { 15050 setAlphaInternal(alpha); 15051 if (onSetAlpha((int) (alpha * 255))) { 15052 mPrivateFlags |= PFLAG_ALPHA_SET; 15053 // subclass is handling alpha - don't optimize rendering cache invalidation 15054 invalidateParentCaches(); 15055 invalidate(true); 15056 } else { 15057 mPrivateFlags &= ~PFLAG_ALPHA_SET; 15058 invalidateViewProperty(true, false); 15059 mRenderNode.setAlpha(getFinalAlpha()); 15060 } 15061 } 15062 } 15063 15064 /** 15065 * Faster version of setAlpha() which performs the same steps except there are 15066 * no calls to invalidate(). The caller of this function should perform proper invalidation 15067 * on the parent and this object. The return value indicates whether the subclass handles 15068 * alpha (the return value for onSetAlpha()). 15069 * 15070 * @param alpha The new value for the alpha property 15071 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 15072 * the new value for the alpha property is different from the old value 15073 */ setAlphaNoInvalidation(float alpha)15074 boolean setAlphaNoInvalidation(float alpha) { 15075 ensureTransformationInfo(); 15076 if (mTransformationInfo.mAlpha != alpha) { 15077 setAlphaInternal(alpha); 15078 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 15079 if (subclassHandlesAlpha) { 15080 mPrivateFlags |= PFLAG_ALPHA_SET; 15081 return true; 15082 } else { 15083 mPrivateFlags &= ~PFLAG_ALPHA_SET; 15084 mRenderNode.setAlpha(getFinalAlpha()); 15085 } 15086 } 15087 return false; 15088 } 15089 setAlphaInternal(float alpha)15090 private void setAlphaInternal(float alpha) { 15091 float oldAlpha = mTransformationInfo.mAlpha; 15092 mTransformationInfo.mAlpha = alpha; 15093 // Report visibility changes, which can affect children, to accessibility 15094 if ((alpha == 0) ^ (oldAlpha == 0)) { 15095 notifySubtreeAccessibilityStateChangedIfNeeded(); 15096 } 15097 } 15098 15099 /** 15100 * This property is hidden and intended only for use by the Fade transition, which 15101 * animates it to produce a visual translucency that does not side-effect (or get 15102 * affected by) the real alpha property. This value is composited with the other 15103 * alpha value (and the AlphaAnimation value, when that is present) to produce 15104 * a final visual translucency result, which is what is passed into the DisplayList. 15105 * 15106 * @hide 15107 */ setTransitionAlpha(float alpha)15108 public void setTransitionAlpha(float alpha) { 15109 ensureTransformationInfo(); 15110 if (mTransformationInfo.mTransitionAlpha != alpha) { 15111 mTransformationInfo.mTransitionAlpha = alpha; 15112 mPrivateFlags &= ~PFLAG_ALPHA_SET; 15113 invalidateViewProperty(true, false); 15114 mRenderNode.setAlpha(getFinalAlpha()); 15115 } 15116 } 15117 15118 /** 15119 * Calculates the visual alpha of this view, which is a combination of the actual 15120 * alpha value and the transitionAlpha value (if set). 15121 */ getFinalAlpha()15122 private float getFinalAlpha() { 15123 if (mTransformationInfo != null) { 15124 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 15125 } 15126 return 1; 15127 } 15128 15129 /** 15130 * This property is hidden and intended only for use by the Fade transition, which 15131 * animates it to produce a visual translucency that does not side-effect (or get 15132 * affected by) the real alpha property. This value is composited with the other 15133 * alpha value (and the AlphaAnimation value, when that is present) to produce 15134 * a final visual translucency result, which is what is passed into the DisplayList. 15135 * 15136 * @hide 15137 */ 15138 @ViewDebug.ExportedProperty(category = "drawing") getTransitionAlpha()15139 public float getTransitionAlpha() { 15140 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 15141 } 15142 15143 /** 15144 * Top position of this view relative to its parent. 15145 * 15146 * @return The top of this view, in pixels. 15147 */ 15148 @ViewDebug.CapturedViewProperty getTop()15149 public final int getTop() { 15150 return mTop; 15151 } 15152 15153 /** 15154 * Sets the top position of this view relative to its parent. This method is meant to be called 15155 * by the layout system and should not generally be called otherwise, because the property 15156 * may be changed at any time by the layout. 15157 * 15158 * @param top The top of this view, in pixels. 15159 */ setTop(int top)15160 public final void setTop(int top) { 15161 if (top != mTop) { 15162 final boolean matrixIsIdentity = hasIdentityMatrix(); 15163 if (matrixIsIdentity) { 15164 if (mAttachInfo != null) { 15165 int minTop; 15166 int yLoc; 15167 if (top < mTop) { 15168 minTop = top; 15169 yLoc = top - mTop; 15170 } else { 15171 minTop = mTop; 15172 yLoc = 0; 15173 } 15174 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 15175 } 15176 } else { 15177 // Double-invalidation is necessary to capture view's old and new areas 15178 invalidate(true); 15179 } 15180 15181 int width = mRight - mLeft; 15182 int oldHeight = mBottom - mTop; 15183 15184 mTop = top; 15185 mRenderNode.setTop(mTop); 15186 15187 sizeChange(width, mBottom - mTop, width, oldHeight); 15188 15189 if (!matrixIsIdentity) { 15190 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 15191 invalidate(true); 15192 } 15193 mBackgroundSizeChanged = true; 15194 mDefaultFocusHighlightSizeChanged = true; 15195 if (mForegroundInfo != null) { 15196 mForegroundInfo.mBoundsChanged = true; 15197 } 15198 invalidateParentIfNeeded(); 15199 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 15200 // View was rejected last time it was drawn by its parent; this may have changed 15201 invalidateParentIfNeeded(); 15202 } 15203 } 15204 } 15205 15206 /** 15207 * Bottom position of this view relative to its parent. 15208 * 15209 * @return The bottom of this view, in pixels. 15210 */ 15211 @ViewDebug.CapturedViewProperty getBottom()15212 public final int getBottom() { 15213 return mBottom; 15214 } 15215 15216 /** 15217 * True if this view has changed since the last time being drawn. 15218 * 15219 * @return The dirty state of this view. 15220 */ isDirty()15221 public boolean isDirty() { 15222 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 15223 } 15224 15225 /** 15226 * Sets the bottom position of this view relative to its parent. This method is meant to be 15227 * called by the layout system and should not generally be called otherwise, because the 15228 * property may be changed at any time by the layout. 15229 * 15230 * @param bottom The bottom of this view, in pixels. 15231 */ setBottom(int bottom)15232 public final void setBottom(int bottom) { 15233 if (bottom != mBottom) { 15234 final boolean matrixIsIdentity = hasIdentityMatrix(); 15235 if (matrixIsIdentity) { 15236 if (mAttachInfo != null) { 15237 int maxBottom; 15238 if (bottom < mBottom) { 15239 maxBottom = mBottom; 15240 } else { 15241 maxBottom = bottom; 15242 } 15243 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 15244 } 15245 } else { 15246 // Double-invalidation is necessary to capture view's old and new areas 15247 invalidate(true); 15248 } 15249 15250 int width = mRight - mLeft; 15251 int oldHeight = mBottom - mTop; 15252 15253 mBottom = bottom; 15254 mRenderNode.setBottom(mBottom); 15255 15256 sizeChange(width, mBottom - mTop, width, oldHeight); 15257 15258 if (!matrixIsIdentity) { 15259 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 15260 invalidate(true); 15261 } 15262 mBackgroundSizeChanged = true; 15263 mDefaultFocusHighlightSizeChanged = true; 15264 if (mForegroundInfo != null) { 15265 mForegroundInfo.mBoundsChanged = true; 15266 } 15267 invalidateParentIfNeeded(); 15268 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 15269 // View was rejected last time it was drawn by its parent; this may have changed 15270 invalidateParentIfNeeded(); 15271 } 15272 } 15273 } 15274 15275 /** 15276 * Left position of this view relative to its parent. 15277 * 15278 * @return The left edge of this view, in pixels. 15279 */ 15280 @ViewDebug.CapturedViewProperty getLeft()15281 public final int getLeft() { 15282 return mLeft; 15283 } 15284 15285 /** 15286 * Sets the left position of this view relative to its parent. This method is meant to be called 15287 * by the layout system and should not generally be called otherwise, because the property 15288 * may be changed at any time by the layout. 15289 * 15290 * @param left The left of this view, in pixels. 15291 */ setLeft(int left)15292 public final void setLeft(int left) { 15293 if (left != mLeft) { 15294 final boolean matrixIsIdentity = hasIdentityMatrix(); 15295 if (matrixIsIdentity) { 15296 if (mAttachInfo != null) { 15297 int minLeft; 15298 int xLoc; 15299 if (left < mLeft) { 15300 minLeft = left; 15301 xLoc = left - mLeft; 15302 } else { 15303 minLeft = mLeft; 15304 xLoc = 0; 15305 } 15306 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 15307 } 15308 } else { 15309 // Double-invalidation is necessary to capture view's old and new areas 15310 invalidate(true); 15311 } 15312 15313 int oldWidth = mRight - mLeft; 15314 int height = mBottom - mTop; 15315 15316 mLeft = left; 15317 mRenderNode.setLeft(left); 15318 15319 sizeChange(mRight - mLeft, height, oldWidth, height); 15320 15321 if (!matrixIsIdentity) { 15322 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 15323 invalidate(true); 15324 } 15325 mBackgroundSizeChanged = true; 15326 mDefaultFocusHighlightSizeChanged = true; 15327 if (mForegroundInfo != null) { 15328 mForegroundInfo.mBoundsChanged = true; 15329 } 15330 invalidateParentIfNeeded(); 15331 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 15332 // View was rejected last time it was drawn by its parent; this may have changed 15333 invalidateParentIfNeeded(); 15334 } 15335 } 15336 } 15337 15338 /** 15339 * Right position of this view relative to its parent. 15340 * 15341 * @return The right edge of this view, in pixels. 15342 */ 15343 @ViewDebug.CapturedViewProperty getRight()15344 public final int getRight() { 15345 return mRight; 15346 } 15347 15348 /** 15349 * Sets the right position of this view relative to its parent. This method is meant to be called 15350 * by the layout system and should not generally be called otherwise, because the property 15351 * may be changed at any time by the layout. 15352 * 15353 * @param right The right of this view, in pixels. 15354 */ setRight(int right)15355 public final void setRight(int right) { 15356 if (right != mRight) { 15357 final boolean matrixIsIdentity = hasIdentityMatrix(); 15358 if (matrixIsIdentity) { 15359 if (mAttachInfo != null) { 15360 int maxRight; 15361 if (right < mRight) { 15362 maxRight = mRight; 15363 } else { 15364 maxRight = right; 15365 } 15366 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 15367 } 15368 } else { 15369 // Double-invalidation is necessary to capture view's old and new areas 15370 invalidate(true); 15371 } 15372 15373 int oldWidth = mRight - mLeft; 15374 int height = mBottom - mTop; 15375 15376 mRight = right; 15377 mRenderNode.setRight(mRight); 15378 15379 sizeChange(mRight - mLeft, height, oldWidth, height); 15380 15381 if (!matrixIsIdentity) { 15382 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 15383 invalidate(true); 15384 } 15385 mBackgroundSizeChanged = true; 15386 mDefaultFocusHighlightSizeChanged = true; 15387 if (mForegroundInfo != null) { 15388 mForegroundInfo.mBoundsChanged = true; 15389 } 15390 invalidateParentIfNeeded(); 15391 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 15392 // View was rejected last time it was drawn by its parent; this may have changed 15393 invalidateParentIfNeeded(); 15394 } 15395 } 15396 } 15397 sanitizeFloatPropertyValue(float value, String propertyName)15398 private static float sanitizeFloatPropertyValue(float value, String propertyName) { 15399 return sanitizeFloatPropertyValue(value, propertyName, -Float.MAX_VALUE, Float.MAX_VALUE); 15400 } 15401 sanitizeFloatPropertyValue(float value, String propertyName, float min, float max)15402 private static float sanitizeFloatPropertyValue(float value, String propertyName, 15403 float min, float max) { 15404 // The expected "nothing bad happened" path 15405 if (value >= min && value <= max) return value; 15406 15407 if (value < min || value == Float.NEGATIVE_INFINITY) { 15408 if (sThrowOnInvalidFloatProperties) { 15409 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to " 15410 + value + ", the value must be >= " + min); 15411 } 15412 return min; 15413 } 15414 15415 if (value > max || value == Float.POSITIVE_INFINITY) { 15416 if (sThrowOnInvalidFloatProperties) { 15417 throw new IllegalArgumentException("Cannot set '" + propertyName + "' to " 15418 + value + ", the value must be <= " + max); 15419 } 15420 return max; 15421 } 15422 15423 if (Float.isNaN(value)) { 15424 if (sThrowOnInvalidFloatProperties) { 15425 throw new IllegalArgumentException( 15426 "Cannot set '" + propertyName + "' to Float.NaN"); 15427 } 15428 return 0; // Unclear which direction this NaN went so... 0? 15429 } 15430 15431 // Shouldn't be possible to reach this. 15432 throw new IllegalStateException("How do you get here?? " + value); 15433 } 15434 15435 /** 15436 * The visual x position of this view, in pixels. This is equivalent to the 15437 * {@link #setTranslationX(float) translationX} property plus the current 15438 * {@link #getLeft() left} property. 15439 * 15440 * @return The visual x position of this view, in pixels. 15441 */ 15442 @ViewDebug.ExportedProperty(category = "drawing") getX()15443 public float getX() { 15444 return mLeft + getTranslationX(); 15445 } 15446 15447 /** 15448 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 15449 * {@link #setTranslationX(float) translationX} property to be the difference between 15450 * the x value passed in and the current {@link #getLeft() left} property. 15451 * 15452 * @param x The visual x position of this view, in pixels. 15453 */ setX(float x)15454 public void setX(float x) { 15455 setTranslationX(x - mLeft); 15456 } 15457 15458 /** 15459 * The visual y position of this view, in pixels. This is equivalent to the 15460 * {@link #setTranslationY(float) translationY} property plus the current 15461 * {@link #getTop() top} property. 15462 * 15463 * @return The visual y position of this view, in pixels. 15464 */ 15465 @ViewDebug.ExportedProperty(category = "drawing") getY()15466 public float getY() { 15467 return mTop + getTranslationY(); 15468 } 15469 15470 /** 15471 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 15472 * {@link #setTranslationY(float) translationY} property to be the difference between 15473 * the y value passed in and the current {@link #getTop() top} property. 15474 * 15475 * @param y The visual y position of this view, in pixels. 15476 */ setY(float y)15477 public void setY(float y) { 15478 setTranslationY(y - mTop); 15479 } 15480 15481 /** 15482 * The visual z position of this view, in pixels. This is equivalent to the 15483 * {@link #setTranslationZ(float) translationZ} property plus the current 15484 * {@link #getElevation() elevation} property. 15485 * 15486 * @return The visual z position of this view, in pixels. 15487 */ 15488 @ViewDebug.ExportedProperty(category = "drawing") getZ()15489 public float getZ() { 15490 return getElevation() + getTranslationZ(); 15491 } 15492 15493 /** 15494 * Sets the visual z position of this view, in pixels. This is equivalent to setting the 15495 * {@link #setTranslationZ(float) translationZ} property to be the difference between 15496 * the x value passed in and the current {@link #getElevation() elevation} property. 15497 * 15498 * @param z The visual z position of this view, in pixels. 15499 */ setZ(float z)15500 public void setZ(float z) { 15501 setTranslationZ(z - getElevation()); 15502 } 15503 15504 /** 15505 * The base elevation of this view relative to its parent, in pixels. 15506 * 15507 * @return The base depth position of the view, in pixels. 15508 */ 15509 @ViewDebug.ExportedProperty(category = "drawing") getElevation()15510 public float getElevation() { 15511 return mRenderNode.getElevation(); 15512 } 15513 15514 /** 15515 * Sets the base elevation of this view, in pixels. 15516 * 15517 * @attr ref android.R.styleable#View_elevation 15518 */ setElevation(float elevation)15519 public void setElevation(float elevation) { 15520 if (elevation != getElevation()) { 15521 elevation = sanitizeFloatPropertyValue(elevation, "elevation"); 15522 invalidateViewProperty(true, false); 15523 mRenderNode.setElevation(elevation); 15524 invalidateViewProperty(false, true); 15525 15526 invalidateParentIfNeededAndWasQuickRejected(); 15527 } 15528 } 15529 15530 /** 15531 * The horizontal location of this view relative to its {@link #getLeft() left} position. 15532 * This position is post-layout, in addition to wherever the object's 15533 * layout placed it. 15534 * 15535 * @return The horizontal position of this view relative to its left position, in pixels. 15536 */ 15537 @ViewDebug.ExportedProperty(category = "drawing") getTranslationX()15538 public float getTranslationX() { 15539 return mRenderNode.getTranslationX(); 15540 } 15541 15542 /** 15543 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 15544 * This effectively positions the object post-layout, in addition to wherever the object's 15545 * layout placed it. 15546 * 15547 * @param translationX The horizontal position of this view relative to its left position, 15548 * in pixels. 15549 * 15550 * @attr ref android.R.styleable#View_translationX 15551 */ setTranslationX(float translationX)15552 public void setTranslationX(float translationX) { 15553 if (translationX != getTranslationX()) { 15554 invalidateViewProperty(true, false); 15555 mRenderNode.setTranslationX(translationX); 15556 invalidateViewProperty(false, true); 15557 15558 invalidateParentIfNeededAndWasQuickRejected(); 15559 notifySubtreeAccessibilityStateChangedIfNeeded(); 15560 } 15561 } 15562 15563 /** 15564 * The vertical location of this view relative to its {@link #getTop() top} position. 15565 * This position is post-layout, in addition to wherever the object's 15566 * layout placed it. 15567 * 15568 * @return The vertical position of this view relative to its top position, 15569 * in pixels. 15570 */ 15571 @ViewDebug.ExportedProperty(category = "drawing") getTranslationY()15572 public float getTranslationY() { 15573 return mRenderNode.getTranslationY(); 15574 } 15575 15576 /** 15577 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 15578 * This effectively positions the object post-layout, in addition to wherever the object's 15579 * layout placed it. 15580 * 15581 * @param translationY The vertical position of this view relative to its top position, 15582 * in pixels. 15583 * 15584 * @attr ref android.R.styleable#View_translationY 15585 */ setTranslationY(float translationY)15586 public void setTranslationY(float translationY) { 15587 if (translationY != getTranslationY()) { 15588 invalidateViewProperty(true, false); 15589 mRenderNode.setTranslationY(translationY); 15590 invalidateViewProperty(false, true); 15591 15592 invalidateParentIfNeededAndWasQuickRejected(); 15593 notifySubtreeAccessibilityStateChangedIfNeeded(); 15594 } 15595 } 15596 15597 /** 15598 * The depth location of this view relative to its {@link #getElevation() elevation}. 15599 * 15600 * @return The depth of this view relative to its elevation. 15601 */ 15602 @ViewDebug.ExportedProperty(category = "drawing") getTranslationZ()15603 public float getTranslationZ() { 15604 return mRenderNode.getTranslationZ(); 15605 } 15606 15607 /** 15608 * Sets the depth location of this view relative to its {@link #getElevation() elevation}. 15609 * 15610 * @attr ref android.R.styleable#View_translationZ 15611 */ setTranslationZ(float translationZ)15612 public void setTranslationZ(float translationZ) { 15613 if (translationZ != getTranslationZ()) { 15614 translationZ = sanitizeFloatPropertyValue(translationZ, "translationZ"); 15615 invalidateViewProperty(true, false); 15616 mRenderNode.setTranslationZ(translationZ); 15617 invalidateViewProperty(false, true); 15618 15619 invalidateParentIfNeededAndWasQuickRejected(); 15620 } 15621 } 15622 15623 /** @hide */ setAnimationMatrix(Matrix matrix)15624 public void setAnimationMatrix(Matrix matrix) { 15625 invalidateViewProperty(true, false); 15626 mRenderNode.setAnimationMatrix(matrix); 15627 invalidateViewProperty(false, true); 15628 15629 invalidateParentIfNeededAndWasQuickRejected(); 15630 } 15631 15632 /** 15633 * Returns the current StateListAnimator if exists. 15634 * 15635 * @return StateListAnimator or null if it does not exists 15636 * @see #setStateListAnimator(android.animation.StateListAnimator) 15637 */ getStateListAnimator()15638 public StateListAnimator getStateListAnimator() { 15639 return mStateListAnimator; 15640 } 15641 15642 /** 15643 * Attaches the provided StateListAnimator to this View. 15644 * <p> 15645 * Any previously attached StateListAnimator will be detached. 15646 * 15647 * @param stateListAnimator The StateListAnimator to update the view 15648 * @see android.animation.StateListAnimator 15649 */ setStateListAnimator(StateListAnimator stateListAnimator)15650 public void setStateListAnimator(StateListAnimator stateListAnimator) { 15651 if (mStateListAnimator == stateListAnimator) { 15652 return; 15653 } 15654 if (mStateListAnimator != null) { 15655 mStateListAnimator.setTarget(null); 15656 } 15657 mStateListAnimator = stateListAnimator; 15658 if (stateListAnimator != null) { 15659 stateListAnimator.setTarget(this); 15660 if (isAttachedToWindow()) { 15661 stateListAnimator.setState(getDrawableState()); 15662 } 15663 } 15664 } 15665 15666 /** 15667 * Returns whether the Outline should be used to clip the contents of the View. 15668 * <p> 15669 * Note that this flag will only be respected if the View's Outline returns true from 15670 * {@link Outline#canClip()}. 15671 * 15672 * @see #setOutlineProvider(ViewOutlineProvider) 15673 * @see #setClipToOutline(boolean) 15674 */ getClipToOutline()15675 public final boolean getClipToOutline() { 15676 return mRenderNode.getClipToOutline(); 15677 } 15678 15679 /** 15680 * Sets whether the View's Outline should be used to clip the contents of the View. 15681 * <p> 15682 * Only a single non-rectangular clip can be applied on a View at any time. 15683 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float) 15684 * circular reveal} animation take priority over Outline clipping, and 15685 * child Outline clipping takes priority over Outline clipping done by a 15686 * parent. 15687 * <p> 15688 * Note that this flag will only be respected if the View's Outline returns true from 15689 * {@link Outline#canClip()}. 15690 * 15691 * @see #setOutlineProvider(ViewOutlineProvider) 15692 * @see #getClipToOutline() 15693 */ setClipToOutline(boolean clipToOutline)15694 public void setClipToOutline(boolean clipToOutline) { 15695 damageInParent(); 15696 if (getClipToOutline() != clipToOutline) { 15697 mRenderNode.setClipToOutline(clipToOutline); 15698 } 15699 } 15700 15701 // correspond to the enum values of View_outlineProvider 15702 private static final int PROVIDER_BACKGROUND = 0; 15703 private static final int PROVIDER_NONE = 1; 15704 private static final int PROVIDER_BOUNDS = 2; 15705 private static final int PROVIDER_PADDED_BOUNDS = 3; setOutlineProviderFromAttribute(int providerInt)15706 private void setOutlineProviderFromAttribute(int providerInt) { 15707 switch (providerInt) { 15708 case PROVIDER_BACKGROUND: 15709 setOutlineProvider(ViewOutlineProvider.BACKGROUND); 15710 break; 15711 case PROVIDER_NONE: 15712 setOutlineProvider(null); 15713 break; 15714 case PROVIDER_BOUNDS: 15715 setOutlineProvider(ViewOutlineProvider.BOUNDS); 15716 break; 15717 case PROVIDER_PADDED_BOUNDS: 15718 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS); 15719 break; 15720 } 15721 } 15722 15723 /** 15724 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines 15725 * the shape of the shadow it casts, and enables outline clipping. 15726 * <p> 15727 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline 15728 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the 15729 * outline provider with this method allows this behavior to be overridden. 15730 * <p> 15731 * If the ViewOutlineProvider is null, if querying it for an outline returns false, 15732 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast. 15733 * <p> 15734 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping. 15735 * 15736 * @see #setClipToOutline(boolean) 15737 * @see #getClipToOutline() 15738 * @see #getOutlineProvider() 15739 */ setOutlineProvider(ViewOutlineProvider provider)15740 public void setOutlineProvider(ViewOutlineProvider provider) { 15741 mOutlineProvider = provider; 15742 invalidateOutline(); 15743 } 15744 15745 /** 15746 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline 15747 * that defines the shape of the shadow it casts, and enables outline clipping. 15748 * 15749 * @see #setOutlineProvider(ViewOutlineProvider) 15750 */ getOutlineProvider()15751 public ViewOutlineProvider getOutlineProvider() { 15752 return mOutlineProvider; 15753 } 15754 15755 /** 15756 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider} 15757 * 15758 * @see #setOutlineProvider(ViewOutlineProvider) 15759 */ invalidateOutline()15760 public void invalidateOutline() { 15761 rebuildOutline(); 15762 15763 notifySubtreeAccessibilityStateChangedIfNeeded(); 15764 invalidateViewProperty(false, false); 15765 } 15766 15767 /** 15768 * Internal version of {@link #invalidateOutline()} which invalidates the 15769 * outline without invalidating the view itself. This is intended to be called from 15770 * within methods in the View class itself which are the result of the view being 15771 * invalidated already. For example, when we are drawing the background of a View, 15772 * we invalidate the outline in case it changed in the meantime, but we do not 15773 * need to invalidate the view because we're already drawing the background as part 15774 * of drawing the view in response to an earlier invalidation of the view. 15775 */ rebuildOutline()15776 private void rebuildOutline() { 15777 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow() 15778 if (mAttachInfo == null) return; 15779 15780 if (mOutlineProvider == null) { 15781 // no provider, remove outline 15782 mRenderNode.setOutline(null); 15783 } else { 15784 final Outline outline = mAttachInfo.mTmpOutline; 15785 outline.setEmpty(); 15786 outline.setAlpha(1.0f); 15787 15788 mOutlineProvider.getOutline(this, outline); 15789 mRenderNode.setOutline(outline); 15790 } 15791 } 15792 15793 /** 15794 * HierarchyViewer only 15795 * 15796 * @hide 15797 */ 15798 @ViewDebug.ExportedProperty(category = "drawing") hasShadow()15799 public boolean hasShadow() { 15800 return mRenderNode.hasShadow(); 15801 } 15802 15803 /** 15804 * Sets the color of the spot shadow that is drawn when the view has a positive Z or 15805 * elevation value. 15806 * <p> 15807 * By default the shadow color is black. Generally, this color will be opaque so the intensity 15808 * of the shadow is consistent between different views with different colors. 15809 * <p> 15810 * The opacity of the final spot shadow is a function of the shadow caster height, the 15811 * alpha channel of the outlineSpotShadowColor (typically opaque), and the 15812 * {@link android.R.attr#spotShadowAlpha} theme attribute. 15813 * 15814 * @attr ref android.R.styleable#View_outlineSpotShadowColor 15815 * @param color The color this View will cast for its elevation spot shadow. 15816 */ setOutlineSpotShadowColor(@olorInt int color)15817 public void setOutlineSpotShadowColor(@ColorInt int color) { 15818 if (mRenderNode.setSpotShadowColor(color)) { 15819 invalidateViewProperty(true, true); 15820 } 15821 } 15822 15823 /** 15824 * @return The shadow color set by {@link #setOutlineSpotShadowColor(int)}, or black if nothing 15825 * was set 15826 */ getOutlineSpotShadowColor()15827 public @ColorInt int getOutlineSpotShadowColor() { 15828 return mRenderNode.getSpotShadowColor(); 15829 } 15830 15831 /** 15832 * Sets the color of the ambient shadow that is drawn when the view has a positive Z or 15833 * elevation value. 15834 * <p> 15835 * By default the shadow color is black. Generally, this color will be opaque so the intensity 15836 * of the shadow is consistent between different views with different colors. 15837 * <p> 15838 * The opacity of the final ambient shadow is a function of the shadow caster height, the 15839 * alpha channel of the outlineAmbientShadowColor (typically opaque), and the 15840 * {@link android.R.attr#ambientShadowAlpha} theme attribute. 15841 * 15842 * @attr ref android.R.styleable#View_outlineAmbientShadowColor 15843 * @param color The color this View will cast for its elevation shadow. 15844 */ setOutlineAmbientShadowColor(@olorInt int color)15845 public void setOutlineAmbientShadowColor(@ColorInt int color) { 15846 if (mRenderNode.setAmbientShadowColor(color)) { 15847 invalidateViewProperty(true, true); 15848 } 15849 } 15850 15851 /** 15852 * @return The shadow color set by {@link #setOutlineAmbientShadowColor(int)}, or black if 15853 * nothing was set 15854 */ getOutlineAmbientShadowColor()15855 public @ColorInt int getOutlineAmbientShadowColor() { 15856 return mRenderNode.getAmbientShadowColor(); 15857 } 15858 15859 15860 /** @hide */ setRevealClip(boolean shouldClip, float x, float y, float radius)15861 public void setRevealClip(boolean shouldClip, float x, float y, float radius) { 15862 mRenderNode.setRevealClip(shouldClip, x, y, radius); 15863 invalidateViewProperty(false, false); 15864 } 15865 15866 /** 15867 * Hit rectangle in parent's coordinates 15868 * 15869 * @param outRect The hit rectangle of the view. 15870 */ getHitRect(Rect outRect)15871 public void getHitRect(Rect outRect) { 15872 if (hasIdentityMatrix() || mAttachInfo == null) { 15873 outRect.set(mLeft, mTop, mRight, mBottom); 15874 } else { 15875 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 15876 tmpRect.set(0, 0, getWidth(), getHeight()); 15877 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) 15878 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 15879 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 15880 } 15881 } 15882 15883 /** 15884 * Determines whether the given point, in local coordinates is inside the view. 15885 */ pointInView(float localX, float localY)15886 /*package*/ final boolean pointInView(float localX, float localY) { 15887 return pointInView(localX, localY, 0); 15888 } 15889 15890 /** 15891 * Utility method to determine whether the given point, in local coordinates, 15892 * is inside the view, where the area of the view is expanded by the slop factor. 15893 * This method is called while processing touch-move events to determine if the event 15894 * is still within the view. 15895 * 15896 * @hide 15897 */ pointInView(float localX, float localY, float slop)15898 public boolean pointInView(float localX, float localY, float slop) { 15899 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 15900 localY < ((mBottom - mTop) + slop); 15901 } 15902 15903 /** 15904 * When a view has focus and the user navigates away from it, the next view is searched for 15905 * starting from the rectangle filled in by this method. 15906 * 15907 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 15908 * of the view. However, if your view maintains some idea of internal selection, 15909 * such as a cursor, or a selected row or column, you should override this method and 15910 * fill in a more specific rectangle. 15911 * 15912 * @param r The rectangle to fill in, in this view's coordinates. 15913 */ getFocusedRect(Rect r)15914 public void getFocusedRect(Rect r) { 15915 getDrawingRect(r); 15916 } 15917 15918 /** 15919 * If some part of this view is not clipped by any of its parents, then 15920 * return that area in r in global (root) coordinates. To convert r to local 15921 * coordinates (without taking possible View rotations into account), offset 15922 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 15923 * If the view is completely clipped or translated out, return false. 15924 * 15925 * @param r If true is returned, r holds the global coordinates of the 15926 * visible portion of this view. 15927 * @param globalOffset If true is returned, globalOffset holds the dx,dy 15928 * between this view and its root. globalOffet may be null. 15929 * @return true if r is non-empty (i.e. part of the view is visible at the 15930 * root level. 15931 */ getGlobalVisibleRect(Rect r, Point globalOffset)15932 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 15933 int width = mRight - mLeft; 15934 int height = mBottom - mTop; 15935 if (width > 0 && height > 0) { 15936 r.set(0, 0, width, height); 15937 if (globalOffset != null) { 15938 globalOffset.set(-mScrollX, -mScrollY); 15939 } 15940 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 15941 } 15942 return false; 15943 } 15944 getGlobalVisibleRect(Rect r)15945 public final boolean getGlobalVisibleRect(Rect r) { 15946 return getGlobalVisibleRect(r, null); 15947 } 15948 getLocalVisibleRect(Rect r)15949 public final boolean getLocalVisibleRect(Rect r) { 15950 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 15951 if (getGlobalVisibleRect(r, offset)) { 15952 r.offset(-offset.x, -offset.y); // make r local 15953 return true; 15954 } 15955 return false; 15956 } 15957 15958 /** 15959 * Offset this view's vertical location by the specified number of pixels. 15960 * 15961 * @param offset the number of pixels to offset the view by 15962 */ offsetTopAndBottom(int offset)15963 public void offsetTopAndBottom(int offset) { 15964 if (offset != 0) { 15965 final boolean matrixIsIdentity = hasIdentityMatrix(); 15966 if (matrixIsIdentity) { 15967 if (isHardwareAccelerated()) { 15968 invalidateViewProperty(false, false); 15969 } else { 15970 final ViewParent p = mParent; 15971 if (p != null && mAttachInfo != null) { 15972 final Rect r = mAttachInfo.mTmpInvalRect; 15973 int minTop; 15974 int maxBottom; 15975 int yLoc; 15976 if (offset < 0) { 15977 minTop = mTop + offset; 15978 maxBottom = mBottom; 15979 yLoc = offset; 15980 } else { 15981 minTop = mTop; 15982 maxBottom = mBottom + offset; 15983 yLoc = 0; 15984 } 15985 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 15986 p.invalidateChild(this, r); 15987 } 15988 } 15989 } else { 15990 invalidateViewProperty(false, false); 15991 } 15992 15993 mTop += offset; 15994 mBottom += offset; 15995 mRenderNode.offsetTopAndBottom(offset); 15996 if (isHardwareAccelerated()) { 15997 invalidateViewProperty(false, false); 15998 invalidateParentIfNeededAndWasQuickRejected(); 15999 } else { 16000 if (!matrixIsIdentity) { 16001 invalidateViewProperty(false, true); 16002 } 16003 invalidateParentIfNeeded(); 16004 } 16005 notifySubtreeAccessibilityStateChangedIfNeeded(); 16006 } 16007 } 16008 16009 /** 16010 * Offset this view's horizontal location by the specified amount of pixels. 16011 * 16012 * @param offset the number of pixels to offset the view by 16013 */ offsetLeftAndRight(int offset)16014 public void offsetLeftAndRight(int offset) { 16015 if (offset != 0) { 16016 final boolean matrixIsIdentity = hasIdentityMatrix(); 16017 if (matrixIsIdentity) { 16018 if (isHardwareAccelerated()) { 16019 invalidateViewProperty(false, false); 16020 } else { 16021 final ViewParent p = mParent; 16022 if (p != null && mAttachInfo != null) { 16023 final Rect r = mAttachInfo.mTmpInvalRect; 16024 int minLeft; 16025 int maxRight; 16026 if (offset < 0) { 16027 minLeft = mLeft + offset; 16028 maxRight = mRight; 16029 } else { 16030 minLeft = mLeft; 16031 maxRight = mRight + offset; 16032 } 16033 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 16034 p.invalidateChild(this, r); 16035 } 16036 } 16037 } else { 16038 invalidateViewProperty(false, false); 16039 } 16040 16041 mLeft += offset; 16042 mRight += offset; 16043 mRenderNode.offsetLeftAndRight(offset); 16044 if (isHardwareAccelerated()) { 16045 invalidateViewProperty(false, false); 16046 invalidateParentIfNeededAndWasQuickRejected(); 16047 } else { 16048 if (!matrixIsIdentity) { 16049 invalidateViewProperty(false, true); 16050 } 16051 invalidateParentIfNeeded(); 16052 } 16053 notifySubtreeAccessibilityStateChangedIfNeeded(); 16054 } 16055 } 16056 16057 /** 16058 * Get the LayoutParams associated with this view. All views should have 16059 * layout parameters. These supply parameters to the <i>parent</i> of this 16060 * view specifying how it should be arranged. There are many subclasses of 16061 * ViewGroup.LayoutParams, and these correspond to the different subclasses 16062 * of ViewGroup that are responsible for arranging their children. 16063 * 16064 * This method may return null if this View is not attached to a parent 16065 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 16066 * was not invoked successfully. When a View is attached to a parent 16067 * ViewGroup, this method must not return null. 16068 * 16069 * @return The LayoutParams associated with this view, or null if no 16070 * parameters have been set yet 16071 */ 16072 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") getLayoutParams()16073 public ViewGroup.LayoutParams getLayoutParams() { 16074 return mLayoutParams; 16075 } 16076 16077 /** 16078 * Set the layout parameters associated with this view. These supply 16079 * parameters to the <i>parent</i> of this view specifying how it should be 16080 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 16081 * correspond to the different subclasses of ViewGroup that are responsible 16082 * for arranging their children. 16083 * 16084 * @param params The layout parameters for this view, cannot be null 16085 */ setLayoutParams(ViewGroup.LayoutParams params)16086 public void setLayoutParams(ViewGroup.LayoutParams params) { 16087 if (params == null) { 16088 throw new NullPointerException("Layout parameters cannot be null"); 16089 } 16090 mLayoutParams = params; 16091 resolveLayoutParams(); 16092 if (mParent instanceof ViewGroup) { 16093 ((ViewGroup) mParent).onSetLayoutParams(this, params); 16094 } 16095 requestLayout(); 16096 } 16097 16098 /** 16099 * Resolve the layout parameters depending on the resolved layout direction 16100 * 16101 * @hide 16102 */ resolveLayoutParams()16103 public void resolveLayoutParams() { 16104 if (mLayoutParams != null) { 16105 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 16106 } 16107 } 16108 16109 /** 16110 * Set the scrolled position of your view. This will cause a call to 16111 * {@link #onScrollChanged(int, int, int, int)} and the view will be 16112 * invalidated. 16113 * @param x the x position to scroll to 16114 * @param y the y position to scroll to 16115 */ scrollTo(int x, int y)16116 public void scrollTo(int x, int y) { 16117 if (mScrollX != x || mScrollY != y) { 16118 int oldX = mScrollX; 16119 int oldY = mScrollY; 16120 mScrollX = x; 16121 mScrollY = y; 16122 invalidateParentCaches(); 16123 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 16124 if (!awakenScrollBars()) { 16125 postInvalidateOnAnimation(); 16126 } 16127 } 16128 } 16129 16130 /** 16131 * Move the scrolled position of your view. This will cause a call to 16132 * {@link #onScrollChanged(int, int, int, int)} and the view will be 16133 * invalidated. 16134 * @param x the amount of pixels to scroll by horizontally 16135 * @param y the amount of pixels to scroll by vertically 16136 */ scrollBy(int x, int y)16137 public void scrollBy(int x, int y) { 16138 scrollTo(mScrollX + x, mScrollY + y); 16139 } 16140 16141 /** 16142 * <p>Trigger the scrollbars to draw. When invoked this method starts an 16143 * animation to fade the scrollbars out after a default delay. If a subclass 16144 * provides animated scrolling, the start delay should equal the duration 16145 * of the scrolling animation.</p> 16146 * 16147 * <p>The animation starts only if at least one of the scrollbars is 16148 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 16149 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 16150 * this method returns true, and false otherwise. If the animation is 16151 * started, this method calls {@link #invalidate()}; in that case the 16152 * caller should not call {@link #invalidate()}.</p> 16153 * 16154 * <p>This method should be invoked every time a subclass directly updates 16155 * the scroll parameters.</p> 16156 * 16157 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 16158 * and {@link #scrollTo(int, int)}.</p> 16159 * 16160 * @return true if the animation is played, false otherwise 16161 * 16162 * @see #awakenScrollBars(int) 16163 * @see #scrollBy(int, int) 16164 * @see #scrollTo(int, int) 16165 * @see #isHorizontalScrollBarEnabled() 16166 * @see #isVerticalScrollBarEnabled() 16167 * @see #setHorizontalScrollBarEnabled(boolean) 16168 * @see #setVerticalScrollBarEnabled(boolean) 16169 */ awakenScrollBars()16170 protected boolean awakenScrollBars() { 16171 return mScrollCache != null && 16172 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 16173 } 16174 16175 /** 16176 * Trigger the scrollbars to draw. 16177 * This method differs from awakenScrollBars() only in its default duration. 16178 * initialAwakenScrollBars() will show the scroll bars for longer than 16179 * usual to give the user more of a chance to notice them. 16180 * 16181 * @return true if the animation is played, false otherwise. 16182 */ initialAwakenScrollBars()16183 private boolean initialAwakenScrollBars() { 16184 return mScrollCache != null && 16185 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 16186 } 16187 16188 /** 16189 * <p> 16190 * Trigger the scrollbars to draw. When invoked this method starts an 16191 * animation to fade the scrollbars out after a fixed delay. If a subclass 16192 * provides animated scrolling, the start delay should equal the duration of 16193 * the scrolling animation. 16194 * </p> 16195 * 16196 * <p> 16197 * The animation starts only if at least one of the scrollbars is enabled, 16198 * as specified by {@link #isHorizontalScrollBarEnabled()} and 16199 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 16200 * this method returns true, and false otherwise. If the animation is 16201 * started, this method calls {@link #invalidate()}; in that case the caller 16202 * should not call {@link #invalidate()}. 16203 * </p> 16204 * 16205 * <p> 16206 * This method should be invoked every time a subclass directly updates the 16207 * scroll parameters. 16208 * </p> 16209 * 16210 * @param startDelay the delay, in milliseconds, after which the animation 16211 * should start; when the delay is 0, the animation starts 16212 * immediately 16213 * @return true if the animation is played, false otherwise 16214 * 16215 * @see #scrollBy(int, int) 16216 * @see #scrollTo(int, int) 16217 * @see #isHorizontalScrollBarEnabled() 16218 * @see #isVerticalScrollBarEnabled() 16219 * @see #setHorizontalScrollBarEnabled(boolean) 16220 * @see #setVerticalScrollBarEnabled(boolean) 16221 */ awakenScrollBars(int startDelay)16222 protected boolean awakenScrollBars(int startDelay) { 16223 return awakenScrollBars(startDelay, true); 16224 } 16225 16226 /** 16227 * <p> 16228 * Trigger the scrollbars to draw. When invoked this method starts an 16229 * animation to fade the scrollbars out after a fixed delay. If a subclass 16230 * provides animated scrolling, the start delay should equal the duration of 16231 * the scrolling animation. 16232 * </p> 16233 * 16234 * <p> 16235 * The animation starts only if at least one of the scrollbars is enabled, 16236 * as specified by {@link #isHorizontalScrollBarEnabled()} and 16237 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 16238 * this method returns true, and false otherwise. If the animation is 16239 * started, this method calls {@link #invalidate()} if the invalidate parameter 16240 * is set to true; in that case the caller 16241 * should not call {@link #invalidate()}. 16242 * </p> 16243 * 16244 * <p> 16245 * This method should be invoked every time a subclass directly updates the 16246 * scroll parameters. 16247 * </p> 16248 * 16249 * @param startDelay the delay, in milliseconds, after which the animation 16250 * should start; when the delay is 0, the animation starts 16251 * immediately 16252 * 16253 * @param invalidate Whether this method should call invalidate 16254 * 16255 * @return true if the animation is played, false otherwise 16256 * 16257 * @see #scrollBy(int, int) 16258 * @see #scrollTo(int, int) 16259 * @see #isHorizontalScrollBarEnabled() 16260 * @see #isVerticalScrollBarEnabled() 16261 * @see #setHorizontalScrollBarEnabled(boolean) 16262 * @see #setVerticalScrollBarEnabled(boolean) 16263 */ awakenScrollBars(int startDelay, boolean invalidate)16264 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 16265 final ScrollabilityCache scrollCache = mScrollCache; 16266 16267 if (scrollCache == null || !scrollCache.fadeScrollBars) { 16268 return false; 16269 } 16270 16271 if (scrollCache.scrollBar == null) { 16272 scrollCache.scrollBar = new ScrollBarDrawable(); 16273 scrollCache.scrollBar.setState(getDrawableState()); 16274 scrollCache.scrollBar.setCallback(this); 16275 } 16276 16277 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 16278 16279 if (invalidate) { 16280 // Invalidate to show the scrollbars 16281 postInvalidateOnAnimation(); 16282 } 16283 16284 if (scrollCache.state == ScrollabilityCache.OFF) { 16285 // FIXME: this is copied from WindowManagerService. 16286 // We should get this value from the system when it 16287 // is possible to do so. 16288 final int KEY_REPEAT_FIRST_DELAY = 750; 16289 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 16290 } 16291 16292 // Tell mScrollCache when we should start fading. This may 16293 // extend the fade start time if one was already scheduled 16294 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 16295 scrollCache.fadeStartTime = fadeStartTime; 16296 scrollCache.state = ScrollabilityCache.ON; 16297 16298 // Schedule our fader to run, unscheduling any old ones first 16299 if (mAttachInfo != null) { 16300 mAttachInfo.mHandler.removeCallbacks(scrollCache); 16301 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 16302 } 16303 16304 return true; 16305 } 16306 16307 return false; 16308 } 16309 16310 /** 16311 * Do not invalidate views which are not visible and which are not running an animation. They 16312 * will not get drawn and they should not set dirty flags as if they will be drawn 16313 */ skipInvalidate()16314 private boolean skipInvalidate() { 16315 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 16316 (!(mParent instanceof ViewGroup) || 16317 !((ViewGroup) mParent).isViewTransitioning(this)); 16318 } 16319 16320 /** 16321 * Mark the area defined by dirty as needing to be drawn. If the view is 16322 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 16323 * point in the future. 16324 * <p> 16325 * This must be called from a UI thread. To call from a non-UI thread, call 16326 * {@link #postInvalidate()}. 16327 * <p> 16328 * <b>WARNING:</b> In API 19 and below, this method may be destructive to 16329 * {@code dirty}. 16330 * 16331 * @param dirty the rectangle representing the bounds of the dirty region 16332 * 16333 * @deprecated The switch to hardware accelerated rendering in API 14 reduced 16334 * the importance of the dirty rectangle. In API 21 the given rectangle is 16335 * ignored entirely in favor of an internally-calculated area instead. 16336 * Because of this, clients are encouraged to just call {@link #invalidate()}. 16337 */ 16338 @Deprecated invalidate(Rect dirty)16339 public void invalidate(Rect dirty) { 16340 final int scrollX = mScrollX; 16341 final int scrollY = mScrollY; 16342 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, 16343 dirty.right - scrollX, dirty.bottom - scrollY, true, false); 16344 } 16345 16346 /** 16347 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The 16348 * coordinates of the dirty rect are relative to the view. If the view is 16349 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 16350 * point in the future. 16351 * <p> 16352 * This must be called from a UI thread. To call from a non-UI thread, call 16353 * {@link #postInvalidate()}. 16354 * 16355 * @param l the left position of the dirty region 16356 * @param t the top position of the dirty region 16357 * @param r the right position of the dirty region 16358 * @param b the bottom position of the dirty region 16359 * 16360 * @deprecated The switch to hardware accelerated rendering in API 14 reduced 16361 * the importance of the dirty rectangle. In API 21 the given rectangle is 16362 * ignored entirely in favor of an internally-calculated area instead. 16363 * Because of this, clients are encouraged to just call {@link #invalidate()}. 16364 */ 16365 @Deprecated invalidate(int l, int t, int r, int b)16366 public void invalidate(int l, int t, int r, int b) { 16367 final int scrollX = mScrollX; 16368 final int scrollY = mScrollY; 16369 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false); 16370 } 16371 16372 /** 16373 * Invalidate the whole view. If the view is visible, 16374 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 16375 * the future. 16376 * <p> 16377 * This must be called from a UI thread. To call from a non-UI thread, call 16378 * {@link #postInvalidate()}. 16379 */ invalidate()16380 public void invalidate() { 16381 invalidate(true); 16382 } 16383 16384 /** 16385 * This is where the invalidate() work actually happens. A full invalidate() 16386 * causes the drawing cache to be invalidated, but this function can be 16387 * called with invalidateCache set to false to skip that invalidation step 16388 * for cases that do not need it (for example, a component that remains at 16389 * the same dimensions with the same content). 16390 * 16391 * @param invalidateCache Whether the drawing cache for this view should be 16392 * invalidated as well. This is usually true for a full 16393 * invalidate, but may be set to false if the View's contents or 16394 * dimensions have not changed. 16395 * @hide 16396 */ invalidate(boolean invalidateCache)16397 public void invalidate(boolean invalidateCache) { 16398 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 16399 } 16400 invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)16401 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, 16402 boolean fullInvalidate) { 16403 if (mGhostView != null) { 16404 mGhostView.invalidate(true); 16405 return; 16406 } 16407 16408 if (skipInvalidate()) { 16409 return; 16410 } 16411 16412 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) 16413 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) 16414 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED 16415 || (fullInvalidate && isOpaque() != mLastIsOpaque)) { 16416 if (fullInvalidate) { 16417 mLastIsOpaque = isOpaque(); 16418 mPrivateFlags &= ~PFLAG_DRAWN; 16419 } 16420 16421 mPrivateFlags |= PFLAG_DIRTY; 16422 16423 if (invalidateCache) { 16424 mPrivateFlags |= PFLAG_INVALIDATED; 16425 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 16426 } 16427 16428 // Propagate the damage rectangle to the parent view. 16429 final AttachInfo ai = mAttachInfo; 16430 final ViewParent p = mParent; 16431 if (p != null && ai != null && l < r && t < b) { 16432 final Rect damage = ai.mTmpInvalRect; 16433 damage.set(l, t, r, b); 16434 p.invalidateChild(this, damage); 16435 } 16436 16437 // Damage the entire projection receiver, if necessary. 16438 if (mBackground != null && mBackground.isProjected()) { 16439 final View receiver = getProjectionReceiver(); 16440 if (receiver != null) { 16441 receiver.damageInParent(); 16442 } 16443 } 16444 } 16445 } 16446 16447 /** 16448 * @return this view's projection receiver, or {@code null} if none exists 16449 */ getProjectionReceiver()16450 private View getProjectionReceiver() { 16451 ViewParent p = getParent(); 16452 while (p != null && p instanceof View) { 16453 final View v = (View) p; 16454 if (v.isProjectionReceiver()) { 16455 return v; 16456 } 16457 p = p.getParent(); 16458 } 16459 16460 return null; 16461 } 16462 16463 /** 16464 * @return whether the view is a projection receiver 16465 */ isProjectionReceiver()16466 private boolean isProjectionReceiver() { 16467 return mBackground != null; 16468 } 16469 16470 /** 16471 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 16472 * set any flags or handle all of the cases handled by the default invalidation methods. 16473 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 16474 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 16475 * walk up the hierarchy, transforming the dirty rect as necessary. 16476 * 16477 * The method also handles normal invalidation logic if display list properties are not 16478 * being used in this view. The invalidateParent and forceRedraw flags are used by that 16479 * backup approach, to handle these cases used in the various property-setting methods. 16480 * 16481 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 16482 * are not being used in this view 16483 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 16484 * list properties are not being used in this view 16485 */ invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)16486 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 16487 if (!isHardwareAccelerated() 16488 || !mRenderNode.isValid() 16489 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { 16490 if (invalidateParent) { 16491 invalidateParentCaches(); 16492 } 16493 if (forceRedraw) { 16494 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 16495 } 16496 invalidate(false); 16497 } else { 16498 damageInParent(); 16499 } 16500 } 16501 16502 /** 16503 * Tells the parent view to damage this view's bounds. 16504 * 16505 * @hide 16506 */ damageInParent()16507 protected void damageInParent() { 16508 if (mParent != null && mAttachInfo != null) { 16509 mParent.onDescendantInvalidated(this, this); 16510 } 16511 } 16512 16513 /** 16514 * Utility method to transform a given Rect by the current matrix of this view. 16515 */ transformRect(final Rect rect)16516 void transformRect(final Rect rect) { 16517 if (!getMatrix().isIdentity()) { 16518 RectF boundingRect = mAttachInfo.mTmpTransformRect; 16519 boundingRect.set(rect); 16520 getMatrix().mapRect(boundingRect); 16521 rect.set((int) Math.floor(boundingRect.left), 16522 (int) Math.floor(boundingRect.top), 16523 (int) Math.ceil(boundingRect.right), 16524 (int) Math.ceil(boundingRect.bottom)); 16525 } 16526 } 16527 16528 /** 16529 * Used to indicate that the parent of this view should clear its caches. This functionality 16530 * is used to force the parent to rebuild its display list (when hardware-accelerated), 16531 * which is necessary when various parent-managed properties of the view change, such as 16532 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 16533 * clears the parent caches and does not causes an invalidate event. 16534 * 16535 * @hide 16536 */ invalidateParentCaches()16537 protected void invalidateParentCaches() { 16538 if (mParent instanceof View) { 16539 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 16540 } 16541 } 16542 16543 /** 16544 * Used to indicate that the parent of this view should be invalidated. This functionality 16545 * is used to force the parent to rebuild its display list (when hardware-accelerated), 16546 * which is necessary when various parent-managed properties of the view change, such as 16547 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 16548 * an invalidation event to the parent. 16549 * 16550 * @hide 16551 */ invalidateParentIfNeeded()16552 protected void invalidateParentIfNeeded() { 16553 if (isHardwareAccelerated() && mParent instanceof View) { 16554 ((View) mParent).invalidate(true); 16555 } 16556 } 16557 16558 /** 16559 * @hide 16560 */ invalidateParentIfNeededAndWasQuickRejected()16561 protected void invalidateParentIfNeededAndWasQuickRejected() { 16562 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { 16563 // View was rejected last time it was drawn by its parent; this may have changed 16564 invalidateParentIfNeeded(); 16565 } 16566 } 16567 16568 /** 16569 * Indicates whether this View is opaque. An opaque View guarantees that it will 16570 * draw all the pixels overlapping its bounds using a fully opaque color. 16571 * 16572 * Subclasses of View should override this method whenever possible to indicate 16573 * whether an instance is opaque. Opaque Views are treated in a special way by 16574 * the View hierarchy, possibly allowing it to perform optimizations during 16575 * invalidate/draw passes. 16576 * 16577 * @return True if this View is guaranteed to be fully opaque, false otherwise. 16578 */ 16579 @ViewDebug.ExportedProperty(category = "drawing") isOpaque()16580 public boolean isOpaque() { 16581 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 16582 getFinalAlpha() >= 1.0f; 16583 } 16584 16585 /** 16586 * @hide 16587 */ computeOpaqueFlags()16588 protected void computeOpaqueFlags() { 16589 // Opaque if: 16590 // - Has a background 16591 // - Background is opaque 16592 // - Doesn't have scrollbars or scrollbars overlay 16593 16594 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 16595 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 16596 } else { 16597 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 16598 } 16599 16600 final int flags = mViewFlags; 16601 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 16602 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 16603 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 16604 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 16605 } else { 16606 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 16607 } 16608 } 16609 16610 /** 16611 * @hide 16612 */ hasOpaqueScrollbars()16613 protected boolean hasOpaqueScrollbars() { 16614 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 16615 } 16616 16617 /** 16618 * @return A handler associated with the thread running the View. This 16619 * handler can be used to pump events in the UI events queue. 16620 */ getHandler()16621 public Handler getHandler() { 16622 final AttachInfo attachInfo = mAttachInfo; 16623 if (attachInfo != null) { 16624 return attachInfo.mHandler; 16625 } 16626 return null; 16627 } 16628 16629 /** 16630 * Returns the queue of runnable for this view. 16631 * 16632 * @return the queue of runnables for this view 16633 */ getRunQueue()16634 private HandlerActionQueue getRunQueue() { 16635 if (mRunQueue == null) { 16636 mRunQueue = new HandlerActionQueue(); 16637 } 16638 return mRunQueue; 16639 } 16640 16641 /** 16642 * Gets the view root associated with the View. 16643 * @return The view root, or null if none. 16644 * @hide 16645 */ getViewRootImpl()16646 public ViewRootImpl getViewRootImpl() { 16647 if (mAttachInfo != null) { 16648 return mAttachInfo.mViewRootImpl; 16649 } 16650 return null; 16651 } 16652 16653 /** 16654 * @hide 16655 */ getThreadedRenderer()16656 public ThreadedRenderer getThreadedRenderer() { 16657 return mAttachInfo != null ? mAttachInfo.mThreadedRenderer : null; 16658 } 16659 16660 /** 16661 * <p>Causes the Runnable to be added to the message queue. 16662 * The runnable will be run on the user interface thread.</p> 16663 * 16664 * @param action The Runnable that will be executed. 16665 * 16666 * @return Returns true if the Runnable was successfully placed in to the 16667 * message queue. Returns false on failure, usually because the 16668 * looper processing the message queue is exiting. 16669 * 16670 * @see #postDelayed 16671 * @see #removeCallbacks 16672 */ post(Runnable action)16673 public boolean post(Runnable action) { 16674 final AttachInfo attachInfo = mAttachInfo; 16675 if (attachInfo != null) { 16676 return attachInfo.mHandler.post(action); 16677 } 16678 16679 // Postpone the runnable until we know on which thread it needs to run. 16680 // Assume that the runnable will be successfully placed after attach. 16681 getRunQueue().post(action); 16682 return true; 16683 } 16684 16685 /** 16686 * <p>Causes the Runnable to be added to the message queue, to be run 16687 * after the specified amount of time elapses. 16688 * The runnable will be run on the user interface thread.</p> 16689 * 16690 * @param action The Runnable that will be executed. 16691 * @param delayMillis The delay (in milliseconds) until the Runnable 16692 * will be executed. 16693 * 16694 * @return true if the Runnable was successfully placed in to the 16695 * message queue. Returns false on failure, usually because the 16696 * looper processing the message queue is exiting. Note that a 16697 * result of true does not mean the Runnable will be processed -- 16698 * if the looper is quit before the delivery time of the message 16699 * occurs then the message will be dropped. 16700 * 16701 * @see #post 16702 * @see #removeCallbacks 16703 */ postDelayed(Runnable action, long delayMillis)16704 public boolean postDelayed(Runnable action, long delayMillis) { 16705 final AttachInfo attachInfo = mAttachInfo; 16706 if (attachInfo != null) { 16707 return attachInfo.mHandler.postDelayed(action, delayMillis); 16708 } 16709 16710 // Postpone the runnable until we know on which thread it needs to run. 16711 // Assume that the runnable will be successfully placed after attach. 16712 getRunQueue().postDelayed(action, delayMillis); 16713 return true; 16714 } 16715 16716 /** 16717 * <p>Causes the Runnable to execute on the next animation time step. 16718 * The runnable will be run on the user interface thread.</p> 16719 * 16720 * @param action The Runnable that will be executed. 16721 * 16722 * @see #postOnAnimationDelayed 16723 * @see #removeCallbacks 16724 */ postOnAnimation(Runnable action)16725 public void postOnAnimation(Runnable action) { 16726 final AttachInfo attachInfo = mAttachInfo; 16727 if (attachInfo != null) { 16728 attachInfo.mViewRootImpl.mChoreographer.postCallback( 16729 Choreographer.CALLBACK_ANIMATION, action, null); 16730 } else { 16731 // Postpone the runnable until we know 16732 // on which thread it needs to run. 16733 getRunQueue().post(action); 16734 } 16735 } 16736 16737 /** 16738 * <p>Causes the Runnable to execute on the next animation time step, 16739 * after the specified amount of time elapses. 16740 * The runnable will be run on the user interface thread.</p> 16741 * 16742 * @param action The Runnable that will be executed. 16743 * @param delayMillis The delay (in milliseconds) until the Runnable 16744 * will be executed. 16745 * 16746 * @see #postOnAnimation 16747 * @see #removeCallbacks 16748 */ postOnAnimationDelayed(Runnable action, long delayMillis)16749 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 16750 final AttachInfo attachInfo = mAttachInfo; 16751 if (attachInfo != null) { 16752 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 16753 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 16754 } else { 16755 // Postpone the runnable until we know 16756 // on which thread it needs to run. 16757 getRunQueue().postDelayed(action, delayMillis); 16758 } 16759 } 16760 16761 /** 16762 * <p>Removes the specified Runnable from the message queue.</p> 16763 * 16764 * @param action The Runnable to remove from the message handling queue 16765 * 16766 * @return true if this view could ask the Handler to remove the Runnable, 16767 * false otherwise. When the returned value is true, the Runnable 16768 * may or may not have been actually removed from the message queue 16769 * (for instance, if the Runnable was not in the queue already.) 16770 * 16771 * @see #post 16772 * @see #postDelayed 16773 * @see #postOnAnimation 16774 * @see #postOnAnimationDelayed 16775 */ removeCallbacks(Runnable action)16776 public boolean removeCallbacks(Runnable action) { 16777 if (action != null) { 16778 final AttachInfo attachInfo = mAttachInfo; 16779 if (attachInfo != null) { 16780 attachInfo.mHandler.removeCallbacks(action); 16781 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 16782 Choreographer.CALLBACK_ANIMATION, action, null); 16783 } 16784 getRunQueue().removeCallbacks(action); 16785 } 16786 return true; 16787 } 16788 16789 /** 16790 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 16791 * Use this to invalidate the View from a non-UI thread.</p> 16792 * 16793 * <p>This method can be invoked from outside of the UI thread 16794 * only when this View is attached to a window.</p> 16795 * 16796 * @see #invalidate() 16797 * @see #postInvalidateDelayed(long) 16798 */ postInvalidate()16799 public void postInvalidate() { 16800 postInvalidateDelayed(0); 16801 } 16802 16803 /** 16804 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 16805 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 16806 * 16807 * <p>This method can be invoked from outside of the UI thread 16808 * only when this View is attached to a window.</p> 16809 * 16810 * @param left The left coordinate of the rectangle to invalidate. 16811 * @param top The top coordinate of the rectangle to invalidate. 16812 * @param right The right coordinate of the rectangle to invalidate. 16813 * @param bottom The bottom coordinate of the rectangle to invalidate. 16814 * 16815 * @see #invalidate(int, int, int, int) 16816 * @see #invalidate(Rect) 16817 * @see #postInvalidateDelayed(long, int, int, int, int) 16818 */ postInvalidate(int left, int top, int right, int bottom)16819 public void postInvalidate(int left, int top, int right, int bottom) { 16820 postInvalidateDelayed(0, left, top, right, bottom); 16821 } 16822 16823 /** 16824 * <p>Cause an invalidate to happen on a subsequent cycle through the event 16825 * loop. Waits for the specified amount of time.</p> 16826 * 16827 * <p>This method can be invoked from outside of the UI thread 16828 * only when this View is attached to a window.</p> 16829 * 16830 * @param delayMilliseconds the duration in milliseconds to delay the 16831 * invalidation by 16832 * 16833 * @see #invalidate() 16834 * @see #postInvalidate() 16835 */ postInvalidateDelayed(long delayMilliseconds)16836 public void postInvalidateDelayed(long delayMilliseconds) { 16837 // We try only with the AttachInfo because there's no point in invalidating 16838 // if we are not attached to our window 16839 final AttachInfo attachInfo = mAttachInfo; 16840 if (attachInfo != null) { 16841 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 16842 } 16843 } 16844 16845 /** 16846 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 16847 * through the event loop. Waits for the specified amount of time.</p> 16848 * 16849 * <p>This method can be invoked from outside of the UI thread 16850 * only when this View is attached to a window.</p> 16851 * 16852 * @param delayMilliseconds the duration in milliseconds to delay the 16853 * invalidation by 16854 * @param left The left coordinate of the rectangle to invalidate. 16855 * @param top The top coordinate of the rectangle to invalidate. 16856 * @param right The right coordinate of the rectangle to invalidate. 16857 * @param bottom The bottom coordinate of the rectangle to invalidate. 16858 * 16859 * @see #invalidate(int, int, int, int) 16860 * @see #invalidate(Rect) 16861 * @see #postInvalidate(int, int, int, int) 16862 */ postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)16863 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 16864 int right, int bottom) { 16865 16866 // We try only with the AttachInfo because there's no point in invalidating 16867 // if we are not attached to our window 16868 final AttachInfo attachInfo = mAttachInfo; 16869 if (attachInfo != null) { 16870 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 16871 info.target = this; 16872 info.left = left; 16873 info.top = top; 16874 info.right = right; 16875 info.bottom = bottom; 16876 16877 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 16878 } 16879 } 16880 16881 /** 16882 * <p>Cause an invalidate to happen on the next animation time step, typically the 16883 * next display frame.</p> 16884 * 16885 * <p>This method can be invoked from outside of the UI thread 16886 * only when this View is attached to a window.</p> 16887 * 16888 * @see #invalidate() 16889 */ postInvalidateOnAnimation()16890 public void postInvalidateOnAnimation() { 16891 // We try only with the AttachInfo because there's no point in invalidating 16892 // if we are not attached to our window 16893 final AttachInfo attachInfo = mAttachInfo; 16894 if (attachInfo != null) { 16895 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 16896 } 16897 } 16898 16899 /** 16900 * <p>Cause an invalidate of the specified area to happen on the next animation 16901 * time step, typically the next display frame.</p> 16902 * 16903 * <p>This method can be invoked from outside of the UI thread 16904 * only when this View is attached to a window.</p> 16905 * 16906 * @param left The left coordinate of the rectangle to invalidate. 16907 * @param top The top coordinate of the rectangle to invalidate. 16908 * @param right The right coordinate of the rectangle to invalidate. 16909 * @param bottom The bottom coordinate of the rectangle to invalidate. 16910 * 16911 * @see #invalidate(int, int, int, int) 16912 * @see #invalidate(Rect) 16913 */ postInvalidateOnAnimation(int left, int top, int right, int bottom)16914 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 16915 // We try only with the AttachInfo because there's no point in invalidating 16916 // if we are not attached to our window 16917 final AttachInfo attachInfo = mAttachInfo; 16918 if (attachInfo != null) { 16919 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 16920 info.target = this; 16921 info.left = left; 16922 info.top = top; 16923 info.right = right; 16924 info.bottom = bottom; 16925 16926 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 16927 } 16928 } 16929 16930 /** 16931 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 16932 * This event is sent at most once every 16933 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 16934 */ postSendViewScrolledAccessibilityEventCallback(int dx, int dy)16935 private void postSendViewScrolledAccessibilityEventCallback(int dx, int dy) { 16936 if (mSendViewScrolledAccessibilityEvent == null) { 16937 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 16938 } 16939 mSendViewScrolledAccessibilityEvent.post(dx, dy); 16940 } 16941 16942 /** 16943 * Called by a parent to request that a child update its values for mScrollX 16944 * and mScrollY if necessary. This will typically be done if the child is 16945 * animating a scroll using a {@link android.widget.Scroller Scroller} 16946 * object. 16947 */ computeScroll()16948 public void computeScroll() { 16949 } 16950 16951 /** 16952 * <p>Indicate whether the horizontal edges are faded when the view is 16953 * scrolled horizontally.</p> 16954 * 16955 * @return true if the horizontal edges should are faded on scroll, false 16956 * otherwise 16957 * 16958 * @see #setHorizontalFadingEdgeEnabled(boolean) 16959 * 16960 * @attr ref android.R.styleable#View_requiresFadingEdge 16961 */ isHorizontalFadingEdgeEnabled()16962 public boolean isHorizontalFadingEdgeEnabled() { 16963 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 16964 } 16965 16966 /** 16967 * <p>Define whether the horizontal edges should be faded when this view 16968 * is scrolled horizontally.</p> 16969 * 16970 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 16971 * be faded when the view is scrolled 16972 * horizontally 16973 * 16974 * @see #isHorizontalFadingEdgeEnabled() 16975 * 16976 * @attr ref android.R.styleable#View_requiresFadingEdge 16977 */ setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)16978 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 16979 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 16980 if (horizontalFadingEdgeEnabled) { 16981 initScrollCache(); 16982 } 16983 16984 mViewFlags ^= FADING_EDGE_HORIZONTAL; 16985 } 16986 } 16987 16988 /** 16989 * <p>Indicate whether the vertical edges are faded when the view is 16990 * scrolled horizontally.</p> 16991 * 16992 * @return true if the vertical edges should are faded on scroll, false 16993 * otherwise 16994 * 16995 * @see #setVerticalFadingEdgeEnabled(boolean) 16996 * 16997 * @attr ref android.R.styleable#View_requiresFadingEdge 16998 */ isVerticalFadingEdgeEnabled()16999 public boolean isVerticalFadingEdgeEnabled() { 17000 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 17001 } 17002 17003 /** 17004 * <p>Define whether the vertical edges should be faded when this view 17005 * is scrolled vertically.</p> 17006 * 17007 * @param verticalFadingEdgeEnabled true if the vertical edges should 17008 * be faded when the view is scrolled 17009 * vertically 17010 * 17011 * @see #isVerticalFadingEdgeEnabled() 17012 * 17013 * @attr ref android.R.styleable#View_requiresFadingEdge 17014 */ setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)17015 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 17016 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 17017 if (verticalFadingEdgeEnabled) { 17018 initScrollCache(); 17019 } 17020 17021 mViewFlags ^= FADING_EDGE_VERTICAL; 17022 } 17023 } 17024 17025 /** 17026 * Returns the strength, or intensity, of the top faded edge. The strength is 17027 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 17028 * returns 0.0 or 1.0 but no value in between. 17029 * 17030 * Subclasses should override this method to provide a smoother fade transition 17031 * when scrolling occurs. 17032 * 17033 * @return the intensity of the top fade as a float between 0.0f and 1.0f 17034 */ getTopFadingEdgeStrength()17035 protected float getTopFadingEdgeStrength() { 17036 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 17037 } 17038 17039 /** 17040 * Returns the strength, or intensity, of the bottom faded edge. The strength is 17041 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 17042 * returns 0.0 or 1.0 but no value in between. 17043 * 17044 * Subclasses should override this method to provide a smoother fade transition 17045 * when scrolling occurs. 17046 * 17047 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 17048 */ getBottomFadingEdgeStrength()17049 protected float getBottomFadingEdgeStrength() { 17050 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 17051 computeVerticalScrollRange() ? 1.0f : 0.0f; 17052 } 17053 17054 /** 17055 * Returns the strength, or intensity, of the left faded edge. The strength is 17056 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 17057 * returns 0.0 or 1.0 but no value in between. 17058 * 17059 * Subclasses should override this method to provide a smoother fade transition 17060 * when scrolling occurs. 17061 * 17062 * @return the intensity of the left fade as a float between 0.0f and 1.0f 17063 */ getLeftFadingEdgeStrength()17064 protected float getLeftFadingEdgeStrength() { 17065 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 17066 } 17067 17068 /** 17069 * Returns the strength, or intensity, of the right faded edge. The strength is 17070 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 17071 * returns 0.0 or 1.0 but no value in between. 17072 * 17073 * Subclasses should override this method to provide a smoother fade transition 17074 * when scrolling occurs. 17075 * 17076 * @return the intensity of the right fade as a float between 0.0f and 1.0f 17077 */ getRightFadingEdgeStrength()17078 protected float getRightFadingEdgeStrength() { 17079 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 17080 computeHorizontalScrollRange() ? 1.0f : 0.0f; 17081 } 17082 17083 /** 17084 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 17085 * scrollbar is not drawn by default.</p> 17086 * 17087 * @return true if the horizontal scrollbar should be painted, false 17088 * otherwise 17089 * 17090 * @see #setHorizontalScrollBarEnabled(boolean) 17091 */ isHorizontalScrollBarEnabled()17092 public boolean isHorizontalScrollBarEnabled() { 17093 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 17094 } 17095 17096 /** 17097 * <p>Define whether the horizontal scrollbar should be drawn or not. The 17098 * scrollbar is not drawn by default.</p> 17099 * 17100 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 17101 * be painted 17102 * 17103 * @see #isHorizontalScrollBarEnabled() 17104 */ setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)17105 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 17106 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 17107 mViewFlags ^= SCROLLBARS_HORIZONTAL; 17108 computeOpaqueFlags(); 17109 resolvePadding(); 17110 } 17111 } 17112 17113 /** 17114 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 17115 * scrollbar is not drawn by default.</p> 17116 * 17117 * @return true if the vertical scrollbar should be painted, false 17118 * otherwise 17119 * 17120 * @see #setVerticalScrollBarEnabled(boolean) 17121 */ isVerticalScrollBarEnabled()17122 public boolean isVerticalScrollBarEnabled() { 17123 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 17124 } 17125 17126 /** 17127 * <p>Define whether the vertical scrollbar should be drawn or not. The 17128 * scrollbar is not drawn by default.</p> 17129 * 17130 * @param verticalScrollBarEnabled true if the vertical scrollbar should 17131 * be painted 17132 * 17133 * @see #isVerticalScrollBarEnabled() 17134 */ setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)17135 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 17136 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 17137 mViewFlags ^= SCROLLBARS_VERTICAL; 17138 computeOpaqueFlags(); 17139 resolvePadding(); 17140 } 17141 } 17142 17143 /** 17144 * @hide 17145 */ recomputePadding()17146 protected void recomputePadding() { 17147 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 17148 } 17149 17150 /** 17151 * Define whether scrollbars will fade when the view is not scrolling. 17152 * 17153 * @param fadeScrollbars whether to enable fading 17154 * 17155 * @attr ref android.R.styleable#View_fadeScrollbars 17156 */ setScrollbarFadingEnabled(boolean fadeScrollbars)17157 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 17158 initScrollCache(); 17159 final ScrollabilityCache scrollabilityCache = mScrollCache; 17160 scrollabilityCache.fadeScrollBars = fadeScrollbars; 17161 if (fadeScrollbars) { 17162 scrollabilityCache.state = ScrollabilityCache.OFF; 17163 } else { 17164 scrollabilityCache.state = ScrollabilityCache.ON; 17165 } 17166 } 17167 17168 /** 17169 * 17170 * Returns true if scrollbars will fade when this view is not scrolling 17171 * 17172 * @return true if scrollbar fading is enabled 17173 * 17174 * @attr ref android.R.styleable#View_fadeScrollbars 17175 */ isScrollbarFadingEnabled()17176 public boolean isScrollbarFadingEnabled() { 17177 return mScrollCache != null && mScrollCache.fadeScrollBars; 17178 } 17179 17180 /** 17181 * 17182 * Returns the delay before scrollbars fade. 17183 * 17184 * @return the delay before scrollbars fade 17185 * 17186 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 17187 */ getScrollBarDefaultDelayBeforeFade()17188 public int getScrollBarDefaultDelayBeforeFade() { 17189 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 17190 mScrollCache.scrollBarDefaultDelayBeforeFade; 17191 } 17192 17193 /** 17194 * Define the delay before scrollbars fade. 17195 * 17196 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 17197 * 17198 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 17199 */ setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)17200 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 17201 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 17202 } 17203 17204 /** 17205 * 17206 * Returns the scrollbar fade duration. 17207 * 17208 * @return the scrollbar fade duration, in milliseconds 17209 * 17210 * @attr ref android.R.styleable#View_scrollbarFadeDuration 17211 */ getScrollBarFadeDuration()17212 public int getScrollBarFadeDuration() { 17213 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 17214 mScrollCache.scrollBarFadeDuration; 17215 } 17216 17217 /** 17218 * Define the scrollbar fade duration. 17219 * 17220 * @param scrollBarFadeDuration - the scrollbar fade duration, in milliseconds 17221 * 17222 * @attr ref android.R.styleable#View_scrollbarFadeDuration 17223 */ setScrollBarFadeDuration(int scrollBarFadeDuration)17224 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 17225 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 17226 } 17227 17228 /** 17229 * 17230 * Returns the scrollbar size. 17231 * 17232 * @return the scrollbar size 17233 * 17234 * @attr ref android.R.styleable#View_scrollbarSize 17235 */ getScrollBarSize()17236 public int getScrollBarSize() { 17237 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 17238 mScrollCache.scrollBarSize; 17239 } 17240 17241 /** 17242 * Define the scrollbar size. 17243 * 17244 * @param scrollBarSize - the scrollbar size 17245 * 17246 * @attr ref android.R.styleable#View_scrollbarSize 17247 */ setScrollBarSize(int scrollBarSize)17248 public void setScrollBarSize(int scrollBarSize) { 17249 getScrollCache().scrollBarSize = scrollBarSize; 17250 } 17251 17252 /** 17253 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 17254 * inset. When inset, they add to the padding of the view. And the scrollbars 17255 * can be drawn inside the padding area or on the edge of the view. For example, 17256 * if a view has a background drawable and you want to draw the scrollbars 17257 * inside the padding specified by the drawable, you can use 17258 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 17259 * appear at the edge of the view, ignoring the padding, then you can use 17260 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 17261 * @param style the style of the scrollbars. Should be one of 17262 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 17263 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 17264 * @see #SCROLLBARS_INSIDE_OVERLAY 17265 * @see #SCROLLBARS_INSIDE_INSET 17266 * @see #SCROLLBARS_OUTSIDE_OVERLAY 17267 * @see #SCROLLBARS_OUTSIDE_INSET 17268 * 17269 * @attr ref android.R.styleable#View_scrollbarStyle 17270 */ setScrollBarStyle(@crollBarStyle int style)17271 public void setScrollBarStyle(@ScrollBarStyle int style) { 17272 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 17273 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 17274 computeOpaqueFlags(); 17275 resolvePadding(); 17276 } 17277 } 17278 17279 /** 17280 * <p>Returns the current scrollbar style.</p> 17281 * @return the current scrollbar style 17282 * @see #SCROLLBARS_INSIDE_OVERLAY 17283 * @see #SCROLLBARS_INSIDE_INSET 17284 * @see #SCROLLBARS_OUTSIDE_OVERLAY 17285 * @see #SCROLLBARS_OUTSIDE_INSET 17286 * 17287 * @attr ref android.R.styleable#View_scrollbarStyle 17288 */ 17289 @ViewDebug.ExportedProperty(mapping = { 17290 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 17291 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 17292 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 17293 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 17294 }) 17295 @ScrollBarStyle getScrollBarStyle()17296 public int getScrollBarStyle() { 17297 return mViewFlags & SCROLLBARS_STYLE_MASK; 17298 } 17299 17300 /** 17301 * <p>Compute the horizontal range that the horizontal scrollbar 17302 * represents.</p> 17303 * 17304 * <p>The range is expressed in arbitrary units that must be the same as the 17305 * units used by {@link #computeHorizontalScrollExtent()} and 17306 * {@link #computeHorizontalScrollOffset()}.</p> 17307 * 17308 * <p>The default range is the drawing width of this view.</p> 17309 * 17310 * @return the total horizontal range represented by the horizontal 17311 * scrollbar 17312 * 17313 * @see #computeHorizontalScrollExtent() 17314 * @see #computeHorizontalScrollOffset() 17315 * @see android.widget.ScrollBarDrawable 17316 */ computeHorizontalScrollRange()17317 protected int computeHorizontalScrollRange() { 17318 return getWidth(); 17319 } 17320 17321 /** 17322 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 17323 * within the horizontal range. This value is used to compute the position 17324 * of the thumb within the scrollbar's track.</p> 17325 * 17326 * <p>The range is expressed in arbitrary units that must be the same as the 17327 * units used by {@link #computeHorizontalScrollRange()} and 17328 * {@link #computeHorizontalScrollExtent()}.</p> 17329 * 17330 * <p>The default offset is the scroll offset of this view.</p> 17331 * 17332 * @return the horizontal offset of the scrollbar's thumb 17333 * 17334 * @see #computeHorizontalScrollRange() 17335 * @see #computeHorizontalScrollExtent() 17336 * @see android.widget.ScrollBarDrawable 17337 */ computeHorizontalScrollOffset()17338 protected int computeHorizontalScrollOffset() { 17339 return mScrollX; 17340 } 17341 17342 /** 17343 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 17344 * within the horizontal range. This value is used to compute the length 17345 * of the thumb within the scrollbar's track.</p> 17346 * 17347 * <p>The range is expressed in arbitrary units that must be the same as the 17348 * units used by {@link #computeHorizontalScrollRange()} and 17349 * {@link #computeHorizontalScrollOffset()}.</p> 17350 * 17351 * <p>The default extent is the drawing width of this view.</p> 17352 * 17353 * @return the horizontal extent of the scrollbar's thumb 17354 * 17355 * @see #computeHorizontalScrollRange() 17356 * @see #computeHorizontalScrollOffset() 17357 * @see android.widget.ScrollBarDrawable 17358 */ computeHorizontalScrollExtent()17359 protected int computeHorizontalScrollExtent() { 17360 return getWidth(); 17361 } 17362 17363 /** 17364 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 17365 * 17366 * <p>The range is expressed in arbitrary units that must be the same as the 17367 * units used by {@link #computeVerticalScrollExtent()} and 17368 * {@link #computeVerticalScrollOffset()}.</p> 17369 * 17370 * @return the total vertical range represented by the vertical scrollbar 17371 * 17372 * <p>The default range is the drawing height of this view.</p> 17373 * 17374 * @see #computeVerticalScrollExtent() 17375 * @see #computeVerticalScrollOffset() 17376 * @see android.widget.ScrollBarDrawable 17377 */ computeVerticalScrollRange()17378 protected int computeVerticalScrollRange() { 17379 return getHeight(); 17380 } 17381 17382 /** 17383 * <p>Compute the vertical offset of the vertical scrollbar's thumb 17384 * within the horizontal range. This value is used to compute the position 17385 * of the thumb within the scrollbar's track.</p> 17386 * 17387 * <p>The range is expressed in arbitrary units that must be the same as the 17388 * units used by {@link #computeVerticalScrollRange()} and 17389 * {@link #computeVerticalScrollExtent()}.</p> 17390 * 17391 * <p>The default offset is the scroll offset of this view.</p> 17392 * 17393 * @return the vertical offset of the scrollbar's thumb 17394 * 17395 * @see #computeVerticalScrollRange() 17396 * @see #computeVerticalScrollExtent() 17397 * @see android.widget.ScrollBarDrawable 17398 */ computeVerticalScrollOffset()17399 protected int computeVerticalScrollOffset() { 17400 return mScrollY; 17401 } 17402 17403 /** 17404 * <p>Compute the vertical extent of the vertical scrollbar's thumb 17405 * within the vertical range. This value is used to compute the length 17406 * of the thumb within the scrollbar's track.</p> 17407 * 17408 * <p>The range is expressed in arbitrary units that must be the same as the 17409 * units used by {@link #computeVerticalScrollRange()} and 17410 * {@link #computeVerticalScrollOffset()}.</p> 17411 * 17412 * <p>The default extent is the drawing height of this view.</p> 17413 * 17414 * @return the vertical extent of the scrollbar's thumb 17415 * 17416 * @see #computeVerticalScrollRange() 17417 * @see #computeVerticalScrollOffset() 17418 * @see android.widget.ScrollBarDrawable 17419 */ computeVerticalScrollExtent()17420 protected int computeVerticalScrollExtent() { 17421 return getHeight(); 17422 } 17423 17424 /** 17425 * Check if this view can be scrolled horizontally in a certain direction. 17426 * 17427 * @param direction Negative to check scrolling left, positive to check scrolling right. 17428 * @return true if this view can be scrolled in the specified direction, false otherwise. 17429 */ canScrollHorizontally(int direction)17430 public boolean canScrollHorizontally(int direction) { 17431 final int offset = computeHorizontalScrollOffset(); 17432 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 17433 if (range == 0) return false; 17434 if (direction < 0) { 17435 return offset > 0; 17436 } else { 17437 return offset < range - 1; 17438 } 17439 } 17440 17441 /** 17442 * Check if this view can be scrolled vertically in a certain direction. 17443 * 17444 * @param direction Negative to check scrolling up, positive to check scrolling down. 17445 * @return true if this view can be scrolled in the specified direction, false otherwise. 17446 */ canScrollVertically(int direction)17447 public boolean canScrollVertically(int direction) { 17448 final int offset = computeVerticalScrollOffset(); 17449 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 17450 if (range == 0) return false; 17451 if (direction < 0) { 17452 return offset > 0; 17453 } else { 17454 return offset < range - 1; 17455 } 17456 } 17457 getScrollIndicatorBounds(@onNull Rect out)17458 void getScrollIndicatorBounds(@NonNull Rect out) { 17459 out.left = mScrollX; 17460 out.right = mScrollX + mRight - mLeft; 17461 out.top = mScrollY; 17462 out.bottom = mScrollY + mBottom - mTop; 17463 } 17464 onDrawScrollIndicators(Canvas c)17465 private void onDrawScrollIndicators(Canvas c) { 17466 if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { 17467 // No scroll indicators enabled. 17468 return; 17469 } 17470 17471 final Drawable dr = mScrollIndicatorDrawable; 17472 if (dr == null) { 17473 // Scroll indicators aren't supported here. 17474 return; 17475 } 17476 17477 final int h = dr.getIntrinsicHeight(); 17478 final int w = dr.getIntrinsicWidth(); 17479 final Rect rect = mAttachInfo.mTmpInvalRect; 17480 getScrollIndicatorBounds(rect); 17481 17482 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { 17483 final boolean canScrollUp = canScrollVertically(-1); 17484 if (canScrollUp) { 17485 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); 17486 dr.draw(c); 17487 } 17488 } 17489 17490 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { 17491 final boolean canScrollDown = canScrollVertically(1); 17492 if (canScrollDown) { 17493 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); 17494 dr.draw(c); 17495 } 17496 } 17497 17498 final int leftRtl; 17499 final int rightRtl; 17500 if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 17501 leftRtl = PFLAG3_SCROLL_INDICATOR_END; 17502 rightRtl = PFLAG3_SCROLL_INDICATOR_START; 17503 } else { 17504 leftRtl = PFLAG3_SCROLL_INDICATOR_START; 17505 rightRtl = PFLAG3_SCROLL_INDICATOR_END; 17506 } 17507 17508 final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; 17509 if ((mPrivateFlags3 & leftMask) != 0) { 17510 final boolean canScrollLeft = canScrollHorizontally(-1); 17511 if (canScrollLeft) { 17512 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); 17513 dr.draw(c); 17514 } 17515 } 17516 17517 final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; 17518 if ((mPrivateFlags3 & rightMask) != 0) { 17519 final boolean canScrollRight = canScrollHorizontally(1); 17520 if (canScrollRight) { 17521 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); 17522 dr.draw(c); 17523 } 17524 } 17525 } 17526 getHorizontalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)17527 private void getHorizontalScrollBarBounds(@Nullable Rect drawBounds, 17528 @Nullable Rect touchBounds) { 17529 final Rect bounds = drawBounds != null ? drawBounds : touchBounds; 17530 if (bounds == null) { 17531 return; 17532 } 17533 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 17534 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 17535 && !isVerticalScrollBarHidden(); 17536 final int size = getHorizontalScrollbarHeight(); 17537 final int verticalScrollBarGap = drawVerticalScrollBar ? 17538 getVerticalScrollbarWidth() : 0; 17539 final int width = mRight - mLeft; 17540 final int height = mBottom - mTop; 17541 bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside); 17542 bounds.left = mScrollX + (mPaddingLeft & inside); 17543 bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 17544 bounds.bottom = bounds.top + size; 17545 17546 if (touchBounds == null) { 17547 return; 17548 } 17549 if (touchBounds != bounds) { 17550 touchBounds.set(bounds); 17551 } 17552 final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget; 17553 if (touchBounds.height() < minTouchTarget) { 17554 final int adjust = (minTouchTarget - touchBounds.height()) / 2; 17555 touchBounds.bottom = Math.min(touchBounds.bottom + adjust, mScrollY + height); 17556 touchBounds.top = touchBounds.bottom - minTouchTarget; 17557 } 17558 if (touchBounds.width() < minTouchTarget) { 17559 final int adjust = (minTouchTarget - touchBounds.width()) / 2; 17560 touchBounds.left -= adjust; 17561 touchBounds.right = touchBounds.left + minTouchTarget; 17562 } 17563 } 17564 getVerticalScrollBarBounds(@ullable Rect bounds, @Nullable Rect touchBounds)17565 private void getVerticalScrollBarBounds(@Nullable Rect bounds, @Nullable Rect touchBounds) { 17566 if (mRoundScrollbarRenderer == null) { 17567 getStraightVerticalScrollBarBounds(bounds, touchBounds); 17568 } else { 17569 getRoundVerticalScrollBarBounds(bounds != null ? bounds : touchBounds); 17570 } 17571 } 17572 getRoundVerticalScrollBarBounds(Rect bounds)17573 private void getRoundVerticalScrollBarBounds(Rect bounds) { 17574 final int width = mRight - mLeft; 17575 final int height = mBottom - mTop; 17576 // Do not take padding into account as we always want the scrollbars 17577 // to hug the screen for round wearable devices. 17578 bounds.left = mScrollX; 17579 bounds.top = mScrollY; 17580 bounds.right = bounds.left + width; 17581 bounds.bottom = mScrollY + height; 17582 } 17583 getStraightVerticalScrollBarBounds(@ullable Rect drawBounds, @Nullable Rect touchBounds)17584 private void getStraightVerticalScrollBarBounds(@Nullable Rect drawBounds, 17585 @Nullable Rect touchBounds) { 17586 final Rect bounds = drawBounds != null ? drawBounds : touchBounds; 17587 if (bounds == null) { 17588 return; 17589 } 17590 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 17591 final int size = getVerticalScrollbarWidth(); 17592 int verticalScrollbarPosition = mVerticalScrollbarPosition; 17593 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 17594 verticalScrollbarPosition = isLayoutRtl() ? 17595 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 17596 } 17597 final int width = mRight - mLeft; 17598 final int height = mBottom - mTop; 17599 switch (verticalScrollbarPosition) { 17600 default: 17601 case SCROLLBAR_POSITION_RIGHT: 17602 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside); 17603 break; 17604 case SCROLLBAR_POSITION_LEFT: 17605 bounds.left = mScrollX + (mUserPaddingLeft & inside); 17606 break; 17607 } 17608 bounds.top = mScrollY + (mPaddingTop & inside); 17609 bounds.right = bounds.left + size; 17610 bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside); 17611 17612 if (touchBounds == null) { 17613 return; 17614 } 17615 if (touchBounds != bounds) { 17616 touchBounds.set(bounds); 17617 } 17618 final int minTouchTarget = mScrollCache.scrollBarMinTouchTarget; 17619 if (touchBounds.width() < minTouchTarget) { 17620 final int adjust = (minTouchTarget - touchBounds.width()) / 2; 17621 if (verticalScrollbarPosition == SCROLLBAR_POSITION_RIGHT) { 17622 touchBounds.right = Math.min(touchBounds.right + adjust, mScrollX + width); 17623 touchBounds.left = touchBounds.right - minTouchTarget; 17624 } else { 17625 touchBounds.left = Math.max(touchBounds.left + adjust, mScrollX); 17626 touchBounds.right = touchBounds.left + minTouchTarget; 17627 } 17628 } 17629 if (touchBounds.height() < minTouchTarget) { 17630 final int adjust = (minTouchTarget - touchBounds.height()) / 2; 17631 touchBounds.top -= adjust; 17632 touchBounds.bottom = touchBounds.top + minTouchTarget; 17633 } 17634 } 17635 17636 /** 17637 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 17638 * scrollbars are painted only if they have been awakened first.</p> 17639 * 17640 * @param canvas the canvas on which to draw the scrollbars 17641 * 17642 * @see #awakenScrollBars(int) 17643 */ onDrawScrollBars(Canvas canvas)17644 protected final void onDrawScrollBars(Canvas canvas) { 17645 // scrollbars are drawn only when the animation is running 17646 final ScrollabilityCache cache = mScrollCache; 17647 17648 if (cache != null) { 17649 17650 int state = cache.state; 17651 17652 if (state == ScrollabilityCache.OFF) { 17653 return; 17654 } 17655 17656 boolean invalidate = false; 17657 17658 if (state == ScrollabilityCache.FADING) { 17659 // We're fading -- get our fade interpolation 17660 if (cache.interpolatorValues == null) { 17661 cache.interpolatorValues = new float[1]; 17662 } 17663 17664 float[] values = cache.interpolatorValues; 17665 17666 // Stops the animation if we're done 17667 if (cache.scrollBarInterpolator.timeToValues(values) == 17668 Interpolator.Result.FREEZE_END) { 17669 cache.state = ScrollabilityCache.OFF; 17670 } else { 17671 cache.scrollBar.mutate().setAlpha(Math.round(values[0])); 17672 } 17673 17674 // This will make the scroll bars inval themselves after 17675 // drawing. We only want this when we're fading so that 17676 // we prevent excessive redraws 17677 invalidate = true; 17678 } else { 17679 // We're just on -- but we may have been fading before so 17680 // reset alpha 17681 cache.scrollBar.mutate().setAlpha(255); 17682 } 17683 17684 final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled(); 17685 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 17686 && !isVerticalScrollBarHidden(); 17687 17688 // Fork out the scroll bar drawing for round wearable devices. 17689 if (mRoundScrollbarRenderer != null) { 17690 if (drawVerticalScrollBar) { 17691 final Rect bounds = cache.mScrollBarBounds; 17692 getVerticalScrollBarBounds(bounds, null); 17693 mRoundScrollbarRenderer.drawRoundScrollbars( 17694 canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds); 17695 if (invalidate) { 17696 invalidate(); 17697 } 17698 } 17699 // Do not draw horizontal scroll bars for round wearable devices. 17700 } else if (drawVerticalScrollBar || drawHorizontalScrollBar) { 17701 final ScrollBarDrawable scrollBar = cache.scrollBar; 17702 17703 if (drawHorizontalScrollBar) { 17704 scrollBar.setParameters(computeHorizontalScrollRange(), 17705 computeHorizontalScrollOffset(), 17706 computeHorizontalScrollExtent(), false); 17707 final Rect bounds = cache.mScrollBarBounds; 17708 getHorizontalScrollBarBounds(bounds, null); 17709 onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 17710 bounds.right, bounds.bottom); 17711 if (invalidate) { 17712 invalidate(bounds); 17713 } 17714 } 17715 17716 if (drawVerticalScrollBar) { 17717 scrollBar.setParameters(computeVerticalScrollRange(), 17718 computeVerticalScrollOffset(), 17719 computeVerticalScrollExtent(), true); 17720 final Rect bounds = cache.mScrollBarBounds; 17721 getVerticalScrollBarBounds(bounds, null); 17722 onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 17723 bounds.right, bounds.bottom); 17724 if (invalidate) { 17725 invalidate(bounds); 17726 } 17727 } 17728 } 17729 } 17730 } 17731 17732 /** 17733 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 17734 * FastScroller is visible. 17735 * @return whether to temporarily hide the vertical scrollbar 17736 * @hide 17737 */ isVerticalScrollBarHidden()17738 protected boolean isVerticalScrollBarHidden() { 17739 return false; 17740 } 17741 17742 /** 17743 * <p>Draw the horizontal scrollbar if 17744 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 17745 * 17746 * @param canvas the canvas on which to draw the scrollbar 17747 * @param scrollBar the scrollbar's drawable 17748 * 17749 * @see #isHorizontalScrollBarEnabled() 17750 * @see #computeHorizontalScrollRange() 17751 * @see #computeHorizontalScrollExtent() 17752 * @see #computeHorizontalScrollOffset() 17753 * @see android.widget.ScrollBarDrawable 17754 * @hide 17755 */ onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)17756 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 17757 int l, int t, int r, int b) { 17758 scrollBar.setBounds(l, t, r, b); 17759 scrollBar.draw(canvas); 17760 } 17761 17762 /** 17763 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 17764 * returns true.</p> 17765 * 17766 * @param canvas the canvas on which to draw the scrollbar 17767 * @param scrollBar the scrollbar's drawable 17768 * 17769 * @see #isVerticalScrollBarEnabled() 17770 * @see #computeVerticalScrollRange() 17771 * @see #computeVerticalScrollExtent() 17772 * @see #computeVerticalScrollOffset() 17773 * @see android.widget.ScrollBarDrawable 17774 * @hide 17775 */ onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)17776 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 17777 int l, int t, int r, int b) { 17778 scrollBar.setBounds(l, t, r, b); 17779 scrollBar.draw(canvas); 17780 } 17781 17782 /** 17783 * Implement this to do your drawing. 17784 * 17785 * @param canvas the canvas on which the background will be drawn 17786 */ onDraw(Canvas canvas)17787 protected void onDraw(Canvas canvas) { 17788 } 17789 17790 /* 17791 * Caller is responsible for calling requestLayout if necessary. 17792 * (This allows addViewInLayout to not request a new layout.) 17793 */ assignParent(ViewParent parent)17794 void assignParent(ViewParent parent) { 17795 if (mParent == null) { 17796 mParent = parent; 17797 } else if (parent == null) { 17798 mParent = null; 17799 } else { 17800 throw new RuntimeException("view " + this + " being added, but" 17801 + " it already has a parent"); 17802 } 17803 } 17804 17805 /** 17806 * This is called when the view is attached to a window. At this point it 17807 * has a Surface and will start drawing. Note that this function is 17808 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 17809 * however it may be called any time before the first onDraw -- including 17810 * before or after {@link #onMeasure(int, int)}. 17811 * 17812 * @see #onDetachedFromWindow() 17813 */ 17814 @CallSuper onAttachedToWindow()17815 protected void onAttachedToWindow() { 17816 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 17817 mParent.requestTransparentRegion(this); 17818 } 17819 17820 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 17821 17822 jumpDrawablesToCurrentState(); 17823 17824 resetSubtreeAccessibilityStateChanged(); 17825 17826 // rebuild, since Outline not maintained while View is detached 17827 rebuildOutline(); 17828 17829 if (isFocused()) { 17830 InputMethodManager imm = InputMethodManager.peekInstance(); 17831 if (imm != null) { 17832 imm.focusIn(this); 17833 } 17834 } 17835 } 17836 17837 /** 17838 * Resolve all RTL related properties. 17839 * 17840 * @return true if resolution of RTL properties has been done 17841 * 17842 * @hide 17843 */ resolveRtlPropertiesIfNeeded()17844 public boolean resolveRtlPropertiesIfNeeded() { 17845 if (!needRtlPropertiesResolution()) return false; 17846 17847 // Order is important here: LayoutDirection MUST be resolved first 17848 if (!isLayoutDirectionResolved()) { 17849 resolveLayoutDirection(); 17850 resolveLayoutParams(); 17851 } 17852 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 17853 if (!isTextDirectionResolved()) { 17854 resolveTextDirection(); 17855 } 17856 if (!isTextAlignmentResolved()) { 17857 resolveTextAlignment(); 17858 } 17859 // Should resolve Drawables before Padding because we need the layout direction of the 17860 // Drawable to correctly resolve Padding. 17861 if (!areDrawablesResolved()) { 17862 resolveDrawables(); 17863 } 17864 if (!isPaddingResolved()) { 17865 resolvePadding(); 17866 } 17867 onRtlPropertiesChanged(getLayoutDirection()); 17868 return true; 17869 } 17870 17871 /** 17872 * Reset resolution of all RTL related properties. 17873 * 17874 * @hide 17875 */ resetRtlProperties()17876 public void resetRtlProperties() { 17877 resetResolvedLayoutDirection(); 17878 resetResolvedTextDirection(); 17879 resetResolvedTextAlignment(); 17880 resetResolvedPadding(); 17881 resetResolvedDrawables(); 17882 } 17883 17884 /** 17885 * @see #onScreenStateChanged(int) 17886 */ dispatchScreenStateChanged(int screenState)17887 void dispatchScreenStateChanged(int screenState) { 17888 onScreenStateChanged(screenState); 17889 } 17890 17891 /** 17892 * This method is called whenever the state of the screen this view is 17893 * attached to changes. A state change will usually occurs when the screen 17894 * turns on or off (whether it happens automatically or the user does it 17895 * manually.) 17896 * 17897 * @param screenState The new state of the screen. Can be either 17898 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 17899 */ onScreenStateChanged(int screenState)17900 public void onScreenStateChanged(int screenState) { 17901 } 17902 17903 /** 17904 * @see #onMovedToDisplay(int, Configuration) 17905 */ dispatchMovedToDisplay(Display display, Configuration config)17906 void dispatchMovedToDisplay(Display display, Configuration config) { 17907 mAttachInfo.mDisplay = display; 17908 mAttachInfo.mDisplayState = display.getState(); 17909 onMovedToDisplay(display.getDisplayId(), config); 17910 } 17911 17912 /** 17913 * Called by the system when the hosting activity is moved from one display to another without 17914 * recreation. This means that the activity is declared to handle all changes to configuration 17915 * that happened when it was switched to another display, so it wasn't destroyed and created 17916 * again. 17917 * 17918 * <p>This call will be followed by {@link #onConfigurationChanged(Configuration)} if the 17919 * applied configuration actually changed. It is up to app developer to choose whether to handle 17920 * the change in this method or in the following {@link #onConfigurationChanged(Configuration)} 17921 * call. 17922 * 17923 * <p>Use this callback to track changes to the displays if some functionality relies on an 17924 * association with some display properties. 17925 * 17926 * @param displayId The id of the display to which the view was moved. 17927 * @param config Configuration of the resources on new display after move. 17928 * 17929 * @see #onConfigurationChanged(Configuration) 17930 * @hide 17931 */ onMovedToDisplay(int displayId, Configuration config)17932 public void onMovedToDisplay(int displayId, Configuration config) { 17933 } 17934 17935 /** 17936 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 17937 */ hasRtlSupport()17938 private boolean hasRtlSupport() { 17939 return mContext.getApplicationInfo().hasRtlSupport(); 17940 } 17941 17942 /** 17943 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 17944 * RTL not supported) 17945 */ isRtlCompatibilityMode()17946 private boolean isRtlCompatibilityMode() { 17947 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 17948 return targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1 || !hasRtlSupport(); 17949 } 17950 17951 /** 17952 * @return true if RTL properties need resolution. 17953 * 17954 */ needRtlPropertiesResolution()17955 private boolean needRtlPropertiesResolution() { 17956 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 17957 } 17958 17959 /** 17960 * Called when any RTL property (layout direction or text direction or text alignment) has 17961 * been changed. 17962 * 17963 * Subclasses need to override this method to take care of cached information that depends on the 17964 * resolved layout direction, or to inform child views that inherit their layout direction. 17965 * 17966 * The default implementation does nothing. 17967 * 17968 * @param layoutDirection the direction of the layout 17969 * 17970 * @see #LAYOUT_DIRECTION_LTR 17971 * @see #LAYOUT_DIRECTION_RTL 17972 */ onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)17973 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { 17974 } 17975 17976 /** 17977 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 17978 * that the parent directionality can and will be resolved before its children. 17979 * 17980 * @return true if resolution has been done, false otherwise. 17981 * 17982 * @hide 17983 */ resolveLayoutDirection()17984 public boolean resolveLayoutDirection() { 17985 // Clear any previous layout direction resolution 17986 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 17987 17988 if (hasRtlSupport()) { 17989 // Set resolved depending on layout direction 17990 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 17991 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 17992 case LAYOUT_DIRECTION_INHERIT: 17993 // We cannot resolve yet. LTR is by default and let the resolution happen again 17994 // later to get the correct resolved value 17995 if (!canResolveLayoutDirection()) return false; 17996 17997 // Parent has not yet resolved, LTR is still the default 17998 try { 17999 if (!mParent.isLayoutDirectionResolved()) return false; 18000 18001 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 18002 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 18003 } 18004 } catch (AbstractMethodError e) { 18005 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18006 " does not fully implement ViewParent", e); 18007 } 18008 break; 18009 case LAYOUT_DIRECTION_RTL: 18010 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 18011 break; 18012 case LAYOUT_DIRECTION_LOCALE: 18013 if((LAYOUT_DIRECTION_RTL == 18014 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 18015 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 18016 } 18017 break; 18018 default: 18019 // Nothing to do, LTR by default 18020 } 18021 } 18022 18023 // Set to resolved 18024 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 18025 return true; 18026 } 18027 18028 /** 18029 * Check if layout direction resolution can be done. 18030 * 18031 * @return true if layout direction resolution can be done otherwise return false. 18032 */ canResolveLayoutDirection()18033 public boolean canResolveLayoutDirection() { 18034 switch (getRawLayoutDirection()) { 18035 case LAYOUT_DIRECTION_INHERIT: 18036 if (mParent != null) { 18037 try { 18038 return mParent.canResolveLayoutDirection(); 18039 } catch (AbstractMethodError e) { 18040 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18041 " does not fully implement ViewParent", e); 18042 } 18043 } 18044 return false; 18045 18046 default: 18047 return true; 18048 } 18049 } 18050 18051 /** 18052 * Reset the resolved layout direction. Layout direction will be resolved during a call to 18053 * {@link #onMeasure(int, int)}. 18054 * 18055 * @hide 18056 */ resetResolvedLayoutDirection()18057 public void resetResolvedLayoutDirection() { 18058 // Reset the current resolved bits 18059 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 18060 } 18061 18062 /** 18063 * @return true if the layout direction is inherited. 18064 * 18065 * @hide 18066 */ isLayoutDirectionInherited()18067 public boolean isLayoutDirectionInherited() { 18068 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 18069 } 18070 18071 /** 18072 * @return true if layout direction has been resolved. 18073 */ isLayoutDirectionResolved()18074 public boolean isLayoutDirectionResolved() { 18075 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 18076 } 18077 18078 /** 18079 * Return if padding has been resolved 18080 * 18081 * @hide 18082 */ isPaddingResolved()18083 boolean isPaddingResolved() { 18084 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 18085 } 18086 18087 /** 18088 * Resolves padding depending on layout direction, if applicable, and 18089 * recomputes internal padding values to adjust for scroll bars. 18090 * 18091 * @hide 18092 */ resolvePadding()18093 public void resolvePadding() { 18094 final int resolvedLayoutDirection = getLayoutDirection(); 18095 18096 if (!isRtlCompatibilityMode()) { 18097 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 18098 // If start / end padding are defined, they will be resolved (hence overriding) to 18099 // left / right or right / left depending on the resolved layout direction. 18100 // If start / end padding are not defined, use the left / right ones. 18101 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 18102 Rect padding = sThreadLocal.get(); 18103 if (padding == null) { 18104 padding = new Rect(); 18105 sThreadLocal.set(padding); 18106 } 18107 mBackground.getPadding(padding); 18108 if (!mLeftPaddingDefined) { 18109 mUserPaddingLeftInitial = padding.left; 18110 } 18111 if (!mRightPaddingDefined) { 18112 mUserPaddingRightInitial = padding.right; 18113 } 18114 } 18115 switch (resolvedLayoutDirection) { 18116 case LAYOUT_DIRECTION_RTL: 18117 if (mUserPaddingStart != UNDEFINED_PADDING) { 18118 mUserPaddingRight = mUserPaddingStart; 18119 } else { 18120 mUserPaddingRight = mUserPaddingRightInitial; 18121 } 18122 if (mUserPaddingEnd != UNDEFINED_PADDING) { 18123 mUserPaddingLeft = mUserPaddingEnd; 18124 } else { 18125 mUserPaddingLeft = mUserPaddingLeftInitial; 18126 } 18127 break; 18128 case LAYOUT_DIRECTION_LTR: 18129 default: 18130 if (mUserPaddingStart != UNDEFINED_PADDING) { 18131 mUserPaddingLeft = mUserPaddingStart; 18132 } else { 18133 mUserPaddingLeft = mUserPaddingLeftInitial; 18134 } 18135 if (mUserPaddingEnd != UNDEFINED_PADDING) { 18136 mUserPaddingRight = mUserPaddingEnd; 18137 } else { 18138 mUserPaddingRight = mUserPaddingRightInitial; 18139 } 18140 } 18141 18142 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 18143 } 18144 18145 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 18146 onRtlPropertiesChanged(resolvedLayoutDirection); 18147 18148 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 18149 } 18150 18151 /** 18152 * Reset the resolved layout direction. 18153 * 18154 * @hide 18155 */ resetResolvedPadding()18156 public void resetResolvedPadding() { 18157 resetResolvedPaddingInternal(); 18158 } 18159 18160 /** 18161 * Used when we only want to reset *this* view's padding and not trigger overrides 18162 * in ViewGroup that reset children too. 18163 */ resetResolvedPaddingInternal()18164 void resetResolvedPaddingInternal() { 18165 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 18166 } 18167 18168 /** 18169 * This is called when the view is detached from a window. At this point it 18170 * no longer has a surface for drawing. 18171 * 18172 * @see #onAttachedToWindow() 18173 */ 18174 @CallSuper onDetachedFromWindow()18175 protected void onDetachedFromWindow() { 18176 } 18177 18178 /** 18179 * This is a framework-internal mirror of onDetachedFromWindow() that's called 18180 * after onDetachedFromWindow(). 18181 * 18182 * If you override this you *MUST* call super.onDetachedFromWindowInternal()! 18183 * The super method should be called at the end of the overridden method to ensure 18184 * subclasses are destroyed first 18185 * 18186 * @hide 18187 */ 18188 @CallSuper onDetachedFromWindowInternal()18189 protected void onDetachedFromWindowInternal() { 18190 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 18191 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 18192 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 18193 18194 removeUnsetPressCallback(); 18195 removeLongPressCallback(); 18196 removePerformClickCallback(); 18197 cancel(mSendViewScrolledAccessibilityEvent); 18198 stopNestedScroll(); 18199 18200 // Anything that started animating right before detach should already 18201 // be in its final state when re-attached. 18202 jumpDrawablesToCurrentState(); 18203 18204 destroyDrawingCache(); 18205 18206 cleanupDraw(); 18207 mCurrentAnimation = null; 18208 18209 if ((mViewFlags & TOOLTIP) == TOOLTIP) { 18210 hideTooltip(); 18211 } 18212 } 18213 cleanupDraw()18214 private void cleanupDraw() { 18215 resetDisplayList(); 18216 if (mAttachInfo != null) { 18217 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 18218 } 18219 } 18220 invalidateInheritedLayoutMode(int layoutModeOfRoot)18221 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 18222 } 18223 18224 /** 18225 * @return The number of times this view has been attached to a window 18226 */ getWindowAttachCount()18227 protected int getWindowAttachCount() { 18228 return mWindowAttachCount; 18229 } 18230 18231 /** 18232 * Retrieve a unique token identifying the window this view is attached to. 18233 * @return Return the window's token for use in 18234 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 18235 */ getWindowToken()18236 public IBinder getWindowToken() { 18237 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 18238 } 18239 18240 /** 18241 * Retrieve the {@link WindowId} for the window this view is 18242 * currently attached to. 18243 */ getWindowId()18244 public WindowId getWindowId() { 18245 AttachInfo ai = mAttachInfo; 18246 if (ai == null) { 18247 return null; 18248 } 18249 if (ai.mWindowId == null) { 18250 try { 18251 ai.mIWindowId = ai.mSession.getWindowId(ai.mWindowToken); 18252 if (ai.mIWindowId != null) { 18253 ai.mWindowId = new WindowId(ai.mIWindowId); 18254 } 18255 } catch (RemoteException e) { 18256 } 18257 } 18258 return ai.mWindowId; 18259 } 18260 18261 /** 18262 * Retrieve a unique token identifying the top-level "real" window of 18263 * the window that this view is attached to. That is, this is like 18264 * {@link #getWindowToken}, except if the window this view in is a panel 18265 * window (attached to another containing window), then the token of 18266 * the containing window is returned instead. 18267 * 18268 * @return Returns the associated window token, either 18269 * {@link #getWindowToken()} or the containing window's token. 18270 */ getApplicationWindowToken()18271 public IBinder getApplicationWindowToken() { 18272 AttachInfo ai = mAttachInfo; 18273 if (ai != null) { 18274 IBinder appWindowToken = ai.mPanelParentWindowToken; 18275 if (appWindowToken == null) { 18276 appWindowToken = ai.mWindowToken; 18277 } 18278 return appWindowToken; 18279 } 18280 return null; 18281 } 18282 18283 /** 18284 * Gets the logical display to which the view's window has been attached. 18285 * 18286 * @return The logical display, or null if the view is not currently attached to a window. 18287 */ getDisplay()18288 public Display getDisplay() { 18289 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 18290 } 18291 18292 /** 18293 * Retrieve private session object this view hierarchy is using to 18294 * communicate with the window manager. 18295 * @return the session object to communicate with the window manager 18296 */ getWindowSession()18297 /*package*/ IWindowSession getWindowSession() { 18298 return mAttachInfo != null ? mAttachInfo.mSession : null; 18299 } 18300 18301 /** 18302 * Return the window this view is currently attached to. Used in 18303 * {@link android.app.ActivityView} to communicate with WM. 18304 * @hide 18305 */ getWindow()18306 protected IWindow getWindow() { 18307 return mAttachInfo != null ? mAttachInfo.mWindow : null; 18308 } 18309 18310 /** 18311 * Return the visibility value of the least visible component passed. 18312 */ combineVisibility(int vis1, int vis2)18313 int combineVisibility(int vis1, int vis2) { 18314 // This works because VISIBLE < INVISIBLE < GONE. 18315 return Math.max(vis1, vis2); 18316 } 18317 18318 /** 18319 * @param info the {@link android.view.View.AttachInfo} to associated with 18320 * this view 18321 */ dispatchAttachedToWindow(AttachInfo info, int visibility)18322 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 18323 mAttachInfo = info; 18324 if (mOverlay != null) { 18325 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 18326 } 18327 mWindowAttachCount++; 18328 // We will need to evaluate the drawable state at least once. 18329 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 18330 if (mFloatingTreeObserver != null) { 18331 info.mTreeObserver.merge(mFloatingTreeObserver); 18332 mFloatingTreeObserver = null; 18333 } 18334 18335 registerPendingFrameMetricsObservers(); 18336 18337 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 18338 mAttachInfo.mScrollContainers.add(this); 18339 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 18340 } 18341 // Transfer all pending runnables. 18342 if (mRunQueue != null) { 18343 mRunQueue.executeActions(info.mHandler); 18344 mRunQueue = null; 18345 } 18346 performCollectViewAttributes(mAttachInfo, visibility); 18347 onAttachedToWindow(); 18348 18349 ListenerInfo li = mListenerInfo; 18350 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 18351 li != null ? li.mOnAttachStateChangeListeners : null; 18352 if (listeners != null && listeners.size() > 0) { 18353 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 18354 // perform the dispatching. The iterator is a safe guard against listeners that 18355 // could mutate the list by calling the various add/remove methods. This prevents 18356 // the array from being modified while we iterate it. 18357 for (OnAttachStateChangeListener listener : listeners) { 18358 listener.onViewAttachedToWindow(this); 18359 } 18360 } 18361 18362 int vis = info.mWindowVisibility; 18363 if (vis != GONE) { 18364 onWindowVisibilityChanged(vis); 18365 if (isShown()) { 18366 // Calling onVisibilityAggregated directly here since the subtree will also 18367 // receive dispatchAttachedToWindow and this same call 18368 onVisibilityAggregated(vis == VISIBLE); 18369 } 18370 } 18371 18372 // Send onVisibilityChanged directly instead of dispatchVisibilityChanged. 18373 // As all views in the subtree will already receive dispatchAttachedToWindow 18374 // traversing the subtree again here is not desired. 18375 onVisibilityChanged(this, visibility); 18376 18377 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 18378 // If nobody has evaluated the drawable state yet, then do it now. 18379 refreshDrawableState(); 18380 } 18381 needGlobalAttributesUpdate(false); 18382 18383 notifyEnterOrExitForAutoFillIfNeeded(true); 18384 } 18385 dispatchDetachedFromWindow()18386 void dispatchDetachedFromWindow() { 18387 AttachInfo info = mAttachInfo; 18388 if (info != null) { 18389 int vis = info.mWindowVisibility; 18390 if (vis != GONE) { 18391 onWindowVisibilityChanged(GONE); 18392 if (isShown()) { 18393 // Invoking onVisibilityAggregated directly here since the subtree 18394 // will also receive detached from window 18395 onVisibilityAggregated(false); 18396 } 18397 } 18398 } 18399 18400 onDetachedFromWindow(); 18401 onDetachedFromWindowInternal(); 18402 18403 InputMethodManager imm = InputMethodManager.peekInstance(); 18404 if (imm != null) { 18405 imm.onViewDetachedFromWindow(this); 18406 } 18407 18408 ListenerInfo li = mListenerInfo; 18409 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 18410 li != null ? li.mOnAttachStateChangeListeners : null; 18411 if (listeners != null && listeners.size() > 0) { 18412 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 18413 // perform the dispatching. The iterator is a safe guard against listeners that 18414 // could mutate the list by calling the various add/remove methods. This prevents 18415 // the array from being modified while we iterate it. 18416 for (OnAttachStateChangeListener listener : listeners) { 18417 listener.onViewDetachedFromWindow(this); 18418 } 18419 } 18420 18421 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 18422 mAttachInfo.mScrollContainers.remove(this); 18423 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 18424 } 18425 18426 mAttachInfo = null; 18427 if (mOverlay != null) { 18428 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 18429 } 18430 18431 notifyEnterOrExitForAutoFillIfNeeded(false); 18432 } 18433 18434 /** 18435 * Cancel any deferred high-level input events that were previously posted to the event queue. 18436 * 18437 * <p>Many views post high-level events such as click handlers to the event queue 18438 * to run deferred in order to preserve a desired user experience - clearing visible 18439 * pressed states before executing, etc. This method will abort any events of this nature 18440 * that are currently in flight.</p> 18441 * 18442 * <p>Custom views that generate their own high-level deferred input events should override 18443 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 18444 * 18445 * <p>This will also cancel pending input events for any child views.</p> 18446 * 18447 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 18448 * This will not impact newer events posted after this call that may occur as a result of 18449 * lower-level input events still waiting in the queue. If you are trying to prevent 18450 * double-submitted events for the duration of some sort of asynchronous transaction 18451 * you should also take other steps to protect against unexpected double inputs e.g. calling 18452 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 18453 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 18454 */ cancelPendingInputEvents()18455 public final void cancelPendingInputEvents() { 18456 dispatchCancelPendingInputEvents(); 18457 } 18458 18459 /** 18460 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 18461 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 18462 */ dispatchCancelPendingInputEvents()18463 void dispatchCancelPendingInputEvents() { 18464 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 18465 onCancelPendingInputEvents(); 18466 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 18467 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 18468 " did not call through to super.onCancelPendingInputEvents()"); 18469 } 18470 } 18471 18472 /** 18473 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 18474 * a parent view. 18475 * 18476 * <p>This method is responsible for removing any pending high-level input events that were 18477 * posted to the event queue to run later. Custom view classes that post their own deferred 18478 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 18479 * {@link android.os.Handler} should override this method, call 18480 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 18481 * </p> 18482 */ onCancelPendingInputEvents()18483 public void onCancelPendingInputEvents() { 18484 removePerformClickCallback(); 18485 cancelLongPress(); 18486 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 18487 } 18488 18489 /** 18490 * Store this view hierarchy's frozen state into the given container. 18491 * 18492 * @param container The SparseArray in which to save the view's state. 18493 * 18494 * @see #restoreHierarchyState(android.util.SparseArray) 18495 * @see #dispatchSaveInstanceState(android.util.SparseArray) 18496 * @see #onSaveInstanceState() 18497 */ saveHierarchyState(SparseArray<Parcelable> container)18498 public void saveHierarchyState(SparseArray<Parcelable> container) { 18499 dispatchSaveInstanceState(container); 18500 } 18501 18502 /** 18503 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 18504 * this view and its children. May be overridden to modify how freezing happens to a 18505 * view's children; for example, some views may want to not store state for their children. 18506 * 18507 * @param container The SparseArray in which to save the view's state. 18508 * 18509 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 18510 * @see #saveHierarchyState(android.util.SparseArray) 18511 * @see #onSaveInstanceState() 18512 */ dispatchSaveInstanceState(SparseArray<Parcelable> container)18513 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 18514 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 18515 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 18516 Parcelable state = onSaveInstanceState(); 18517 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 18518 throw new IllegalStateException( 18519 "Derived class did not call super.onSaveInstanceState()"); 18520 } 18521 if (state != null) { 18522 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 18523 // + ": " + state); 18524 container.put(mID, state); 18525 } 18526 } 18527 } 18528 18529 /** 18530 * Hook allowing a view to generate a representation of its internal state 18531 * that can later be used to create a new instance with that same state. 18532 * This state should only contain information that is not persistent or can 18533 * not be reconstructed later. For example, you will never store your 18534 * current position on screen because that will be computed again when a 18535 * new instance of the view is placed in its view hierarchy. 18536 * <p> 18537 * Some examples of things you may store here: the current cursor position 18538 * in a text view (but usually not the text itself since that is stored in a 18539 * content provider or other persistent storage), the currently selected 18540 * item in a list view. 18541 * 18542 * @return Returns a Parcelable object containing the view's current dynamic 18543 * state, or null if there is nothing interesting to save. 18544 * @see #onRestoreInstanceState(Parcelable) 18545 * @see #saveHierarchyState(SparseArray) 18546 * @see #dispatchSaveInstanceState(SparseArray) 18547 * @see #setSaveEnabled(boolean) 18548 */ 18549 @CallSuper onSaveInstanceState()18550 @Nullable protected Parcelable onSaveInstanceState() { 18551 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 18552 if (mStartActivityRequestWho != null || isAutofilled() 18553 || mAutofillViewId > LAST_APP_AUTOFILL_ID) { 18554 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE); 18555 18556 if (mStartActivityRequestWho != null) { 18557 state.mSavedData |= BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED; 18558 } 18559 18560 if (isAutofilled()) { 18561 state.mSavedData |= BaseSavedState.IS_AUTOFILLED; 18562 } 18563 18564 if (mAutofillViewId > LAST_APP_AUTOFILL_ID) { 18565 state.mSavedData |= BaseSavedState.AUTOFILL_ID; 18566 } 18567 18568 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; 18569 state.mIsAutofilled = isAutofilled(); 18570 state.mAutofillViewId = mAutofillViewId; 18571 return state; 18572 } 18573 return BaseSavedState.EMPTY_STATE; 18574 } 18575 18576 /** 18577 * Restore this view hierarchy's frozen state from the given container. 18578 * 18579 * @param container The SparseArray which holds previously frozen states. 18580 * 18581 * @see #saveHierarchyState(android.util.SparseArray) 18582 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 18583 * @see #onRestoreInstanceState(android.os.Parcelable) 18584 */ restoreHierarchyState(SparseArray<Parcelable> container)18585 public void restoreHierarchyState(SparseArray<Parcelable> container) { 18586 dispatchRestoreInstanceState(container); 18587 } 18588 18589 /** 18590 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 18591 * state for this view and its children. May be overridden to modify how restoring 18592 * happens to a view's children; for example, some views may want to not store state 18593 * for their children. 18594 * 18595 * @param container The SparseArray which holds previously saved state. 18596 * 18597 * @see #dispatchSaveInstanceState(android.util.SparseArray) 18598 * @see #restoreHierarchyState(android.util.SparseArray) 18599 * @see #onRestoreInstanceState(android.os.Parcelable) 18600 */ dispatchRestoreInstanceState(SparseArray<Parcelable> container)18601 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 18602 if (mID != NO_ID) { 18603 Parcelable state = container.get(mID); 18604 if (state != null) { 18605 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 18606 // + ": " + state); 18607 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 18608 onRestoreInstanceState(state); 18609 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 18610 throw new IllegalStateException( 18611 "Derived class did not call super.onRestoreInstanceState()"); 18612 } 18613 } 18614 } 18615 } 18616 18617 /** 18618 * Hook allowing a view to re-apply a representation of its internal state that had previously 18619 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 18620 * null state. 18621 * 18622 * @param state The frozen state that had previously been returned by 18623 * {@link #onSaveInstanceState}. 18624 * 18625 * @see #onSaveInstanceState() 18626 * @see #restoreHierarchyState(android.util.SparseArray) 18627 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 18628 */ 18629 @CallSuper onRestoreInstanceState(Parcelable state)18630 protected void onRestoreInstanceState(Parcelable state) { 18631 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 18632 if (state != null && !(state instanceof AbsSavedState)) { 18633 throw new IllegalArgumentException("Wrong state class, expecting View State but " 18634 + "received " + state.getClass().toString() + " instead. This usually happens " 18635 + "when two views of different type have the same id in the same hierarchy. " 18636 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 18637 + "other views do not use the same id."); 18638 } 18639 if (state != null && state instanceof BaseSavedState) { 18640 BaseSavedState baseState = (BaseSavedState) state; 18641 18642 if ((baseState.mSavedData & BaseSavedState.START_ACTIVITY_REQUESTED_WHO_SAVED) != 0) { 18643 mStartActivityRequestWho = baseState.mStartActivityRequestWhoSaved; 18644 } 18645 if ((baseState.mSavedData & BaseSavedState.IS_AUTOFILLED) != 0) { 18646 setAutofilled(baseState.mIsAutofilled); 18647 } 18648 if ((baseState.mSavedData & BaseSavedState.AUTOFILL_ID) != 0) { 18649 // It can happen that views have the same view id and the restoration path will not 18650 // be able to distinguish between them. The autofill id needs to be unique though. 18651 // Hence prevent the same autofill view id from being restored multiple times. 18652 ((BaseSavedState) state).mSavedData &= ~BaseSavedState.AUTOFILL_ID; 18653 18654 if ((mPrivateFlags3 & PFLAG3_AUTOFILLID_EXPLICITLY_SET) != 0) { 18655 // Ignore when view already set it through setAutofillId(); 18656 if (android.view.autofill.Helper.sDebug) { 18657 Log.d(VIEW_LOG_TAG, "onRestoreInstanceState(): not setting autofillId to " 18658 + baseState.mAutofillViewId + " because view explicitly set it to " 18659 + mAutofillId); 18660 } 18661 } else { 18662 mAutofillViewId = baseState.mAutofillViewId; 18663 mAutofillId = null; // will be set on demand by getAutofillId() 18664 } 18665 } 18666 } 18667 } 18668 18669 /** 18670 * <p>Return the time at which the drawing of the view hierarchy started.</p> 18671 * 18672 * @return the drawing start time in milliseconds 18673 */ getDrawingTime()18674 public long getDrawingTime() { 18675 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 18676 } 18677 18678 /** 18679 * <p>Enables or disables the duplication of the parent's state into this view. When 18680 * duplication is enabled, this view gets its drawable state from its parent rather 18681 * than from its own internal properties.</p> 18682 * 18683 * <p>Note: in the current implementation, setting this property to true after the 18684 * view was added to a ViewGroup might have no effect at all. This property should 18685 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 18686 * 18687 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 18688 * property is enabled, an exception will be thrown.</p> 18689 * 18690 * <p>Note: if the child view uses and updates additional states which are unknown to the 18691 * parent, these states should not be affected by this method.</p> 18692 * 18693 * @param enabled True to enable duplication of the parent's drawable state, false 18694 * to disable it. 18695 * 18696 * @see #getDrawableState() 18697 * @see #isDuplicateParentStateEnabled() 18698 */ setDuplicateParentStateEnabled(boolean enabled)18699 public void setDuplicateParentStateEnabled(boolean enabled) { 18700 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 18701 } 18702 18703 /** 18704 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 18705 * 18706 * @return True if this view's drawable state is duplicated from the parent, 18707 * false otherwise 18708 * 18709 * @see #getDrawableState() 18710 * @see #setDuplicateParentStateEnabled(boolean) 18711 */ isDuplicateParentStateEnabled()18712 public boolean isDuplicateParentStateEnabled() { 18713 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 18714 } 18715 18716 /** 18717 * <p>Specifies the type of layer backing this view. The layer can be 18718 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 18719 * {@link #LAYER_TYPE_HARDWARE}.</p> 18720 * 18721 * <p>A layer is associated with an optional {@link android.graphics.Paint} 18722 * instance that controls how the layer is composed on screen. The following 18723 * properties of the paint are taken into account when composing the layer:</p> 18724 * <ul> 18725 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 18726 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 18727 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 18728 * </ul> 18729 * 18730 * <p>If this view has an alpha value set to < 1.0 by calling 18731 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded 18732 * by this view's alpha value.</p> 18733 * 18734 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 18735 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 18736 * for more information on when and how to use layers.</p> 18737 * 18738 * @param layerType The type of layer to use with this view, must be one of 18739 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 18740 * {@link #LAYER_TYPE_HARDWARE} 18741 * @param paint The paint used to compose the layer. This argument is optional 18742 * and can be null. It is ignored when the layer type is 18743 * {@link #LAYER_TYPE_NONE} 18744 * 18745 * @see #getLayerType() 18746 * @see #LAYER_TYPE_NONE 18747 * @see #LAYER_TYPE_SOFTWARE 18748 * @see #LAYER_TYPE_HARDWARE 18749 * @see #setAlpha(float) 18750 * 18751 * @attr ref android.R.styleable#View_layerType 18752 */ setLayerType(int layerType, @Nullable Paint paint)18753 public void setLayerType(int layerType, @Nullable Paint paint) { 18754 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 18755 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 18756 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 18757 } 18758 18759 boolean typeChanged = mRenderNode.setLayerType(layerType); 18760 18761 if (!typeChanged) { 18762 setLayerPaint(paint); 18763 return; 18764 } 18765 18766 if (layerType != LAYER_TYPE_SOFTWARE) { 18767 // Destroy any previous software drawing cache if present 18768 // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up 18769 // drawing cache created in View#draw when drawing to a SW canvas. 18770 destroyDrawingCache(); 18771 } 18772 18773 mLayerType = layerType; 18774 mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint; 18775 mRenderNode.setLayerPaint(mLayerPaint); 18776 18777 // draw() behaves differently if we are on a layer, so we need to 18778 // invalidate() here 18779 invalidateParentCaches(); 18780 invalidate(true); 18781 } 18782 18783 /** 18784 * Updates the {@link Paint} object used with the current layer (used only if the current 18785 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 18786 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 18787 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 18788 * ensure that the view gets redrawn immediately. 18789 * 18790 * <p>A layer is associated with an optional {@link android.graphics.Paint} 18791 * instance that controls how the layer is composed on screen. The following 18792 * properties of the paint are taken into account when composing the layer:</p> 18793 * <ul> 18794 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 18795 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 18796 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 18797 * </ul> 18798 * 18799 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 18800 * alpha value of the layer's paint is superseded by this view's alpha value.</p> 18801 * 18802 * @param paint The paint used to compose the layer. This argument is optional 18803 * and can be null. It is ignored when the layer type is 18804 * {@link #LAYER_TYPE_NONE} 18805 * 18806 * @see #setLayerType(int, android.graphics.Paint) 18807 */ setLayerPaint(@ullable Paint paint)18808 public void setLayerPaint(@Nullable Paint paint) { 18809 int layerType = getLayerType(); 18810 if (layerType != LAYER_TYPE_NONE) { 18811 mLayerPaint = paint; 18812 if (layerType == LAYER_TYPE_HARDWARE) { 18813 if (mRenderNode.setLayerPaint(paint)) { 18814 invalidateViewProperty(false, false); 18815 } 18816 } else { 18817 invalidate(); 18818 } 18819 } 18820 } 18821 18822 /** 18823 * Indicates what type of layer is currently associated with this view. By default 18824 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 18825 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 18826 * for more information on the different types of layers. 18827 * 18828 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 18829 * {@link #LAYER_TYPE_HARDWARE} 18830 * 18831 * @see #setLayerType(int, android.graphics.Paint) 18832 * @see #buildLayer() 18833 * @see #LAYER_TYPE_NONE 18834 * @see #LAYER_TYPE_SOFTWARE 18835 * @see #LAYER_TYPE_HARDWARE 18836 */ getLayerType()18837 public int getLayerType() { 18838 return mLayerType; 18839 } 18840 18841 /** 18842 * Forces this view's layer to be created and this view to be rendered 18843 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 18844 * invoking this method will have no effect. 18845 * 18846 * This method can for instance be used to render a view into its layer before 18847 * starting an animation. If this view is complex, rendering into the layer 18848 * before starting the animation will avoid skipping frames. 18849 * 18850 * @throws IllegalStateException If this view is not attached to a window 18851 * 18852 * @see #setLayerType(int, android.graphics.Paint) 18853 */ buildLayer()18854 public void buildLayer() { 18855 if (mLayerType == LAYER_TYPE_NONE) return; 18856 18857 final AttachInfo attachInfo = mAttachInfo; 18858 if (attachInfo == null) { 18859 throw new IllegalStateException("This view must be attached to a window first"); 18860 } 18861 18862 if (getWidth() == 0 || getHeight() == 0) { 18863 return; 18864 } 18865 18866 switch (mLayerType) { 18867 case LAYER_TYPE_HARDWARE: 18868 updateDisplayListIfDirty(); 18869 if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) { 18870 attachInfo.mThreadedRenderer.buildLayer(mRenderNode); 18871 } 18872 break; 18873 case LAYER_TYPE_SOFTWARE: 18874 buildDrawingCache(true); 18875 break; 18876 } 18877 } 18878 18879 /** 18880 * Destroys all hardware rendering resources. This method is invoked 18881 * when the system needs to reclaim resources. Upon execution of this 18882 * method, you should free any OpenGL resources created by the view. 18883 * 18884 * Note: you <strong>must</strong> call 18885 * <code>super.destroyHardwareResources()</code> when overriding 18886 * this method. 18887 * 18888 * @hide 18889 */ 18890 @CallSuper destroyHardwareResources()18891 protected void destroyHardwareResources() { 18892 if (mOverlay != null) { 18893 mOverlay.getOverlayView().destroyHardwareResources(); 18894 } 18895 if (mGhostView != null) { 18896 mGhostView.destroyHardwareResources(); 18897 } 18898 } 18899 18900 /** 18901 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 18902 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 18903 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 18904 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 18905 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 18906 * null.</p> 18907 * 18908 * <p>Enabling the drawing cache is similar to 18909 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 18910 * acceleration is turned off. When hardware acceleration is turned on, enabling the 18911 * drawing cache has no effect on rendering because the system uses a different mechanism 18912 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 18913 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 18914 * for information on how to enable software and hardware layers.</p> 18915 * 18916 * <p>This API can be used to manually generate 18917 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 18918 * {@link #getDrawingCache()}.</p> 18919 * 18920 * @param enabled true to enable the drawing cache, false otherwise 18921 * 18922 * @see #isDrawingCacheEnabled() 18923 * @see #getDrawingCache() 18924 * @see #buildDrawingCache() 18925 * @see #setLayerType(int, android.graphics.Paint) 18926 * 18927 * @deprecated The view drawing cache was largely made obsolete with the introduction of 18928 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 18929 * layers are largely unnecessary and can easily result in a net loss in performance due to the 18930 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 18931 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 18932 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 18933 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 18934 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 18935 * software-rendered usages are discouraged and have compatibility issues with hardware-only 18936 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 18937 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 18938 * reports or unit testing the {@link PixelCopy} API is recommended. 18939 */ 18940 @Deprecated setDrawingCacheEnabled(boolean enabled)18941 public void setDrawingCacheEnabled(boolean enabled) { 18942 mCachingFailed = false; 18943 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 18944 } 18945 18946 /** 18947 * <p>Indicates whether the drawing cache is enabled for this view.</p> 18948 * 18949 * @return true if the drawing cache is enabled 18950 * 18951 * @see #setDrawingCacheEnabled(boolean) 18952 * @see #getDrawingCache() 18953 * 18954 * @deprecated The view drawing cache was largely made obsolete with the introduction of 18955 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 18956 * layers are largely unnecessary and can easily result in a net loss in performance due to the 18957 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 18958 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 18959 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 18960 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 18961 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 18962 * software-rendered usages are discouraged and have compatibility issues with hardware-only 18963 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 18964 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 18965 * reports or unit testing the {@link PixelCopy} API is recommended. 18966 */ 18967 @Deprecated 18968 @ViewDebug.ExportedProperty(category = "drawing") isDrawingCacheEnabled()18969 public boolean isDrawingCacheEnabled() { 18970 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 18971 } 18972 18973 /** 18974 * Debugging utility which recursively outputs the dirty state of a view and its 18975 * descendants. 18976 * 18977 * @hide 18978 */ 18979 @SuppressWarnings({"UnusedDeclaration"}) outputDirtyFlags(String indent, boolean clear, int clearMask)18980 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 18981 Log.d(VIEW_LOG_TAG, indent + this + " DIRTY(" 18982 + (mPrivateFlags & View.PFLAG_DIRTY_MASK) 18983 + ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" 18984 + (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) 18985 + ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 18986 if (clear) { 18987 mPrivateFlags &= clearMask; 18988 } 18989 if (this instanceof ViewGroup) { 18990 ViewGroup parent = (ViewGroup) this; 18991 final int count = parent.getChildCount(); 18992 for (int i = 0; i < count; i++) { 18993 final View child = parent.getChildAt(i); 18994 child.outputDirtyFlags(indent + " ", clear, clearMask); 18995 } 18996 } 18997 } 18998 18999 /** 19000 * This method is used by ViewGroup to cause its children to restore or recreate their 19001 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 19002 * to recreate its own display list, which would happen if it went through the normal 19003 * draw/dispatchDraw mechanisms. 19004 * 19005 * @hide 19006 */ dispatchGetDisplayList()19007 protected void dispatchGetDisplayList() {} 19008 19009 /** 19010 * A view that is not attached or hardware accelerated cannot create a display list. 19011 * This method checks these conditions and returns the appropriate result. 19012 * 19013 * @return true if view has the ability to create a display list, false otherwise. 19014 * 19015 * @hide 19016 */ canHaveDisplayList()19017 public boolean canHaveDisplayList() { 19018 return !(mAttachInfo == null || mAttachInfo.mThreadedRenderer == null); 19019 } 19020 19021 /** 19022 * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported) 19023 * @hide 19024 */ 19025 @NonNull updateDisplayListIfDirty()19026 public RenderNode updateDisplayListIfDirty() { 19027 final RenderNode renderNode = mRenderNode; 19028 if (!canHaveDisplayList()) { 19029 // can't populate RenderNode, don't try 19030 return renderNode; 19031 } 19032 19033 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 19034 || !renderNode.isValid() 19035 || (mRecreateDisplayList)) { 19036 // Don't need to recreate the display list, just need to tell our 19037 // children to restore/recreate theirs 19038 if (renderNode.isValid() 19039 && !mRecreateDisplayList) { 19040 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 19041 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 19042 dispatchGetDisplayList(); 19043 19044 return renderNode; // no work needed 19045 } 19046 19047 // If we got here, we're recreating it. Mark it as such to ensure that 19048 // we copy in child display lists into ours in drawChild() 19049 mRecreateDisplayList = true; 19050 19051 int width = mRight - mLeft; 19052 int height = mBottom - mTop; 19053 int layerType = getLayerType(); 19054 19055 final DisplayListCanvas canvas = renderNode.start(width, height); 19056 19057 try { 19058 if (layerType == LAYER_TYPE_SOFTWARE) { 19059 buildDrawingCache(true); 19060 Bitmap cache = getDrawingCache(true); 19061 if (cache != null) { 19062 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 19063 } 19064 } else { 19065 computeScroll(); 19066 19067 canvas.translate(-mScrollX, -mScrollY); 19068 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 19069 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 19070 19071 // Fast path for layouts with no backgrounds 19072 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 19073 dispatchDraw(canvas); 19074 drawAutofilledHighlight(canvas); 19075 if (mOverlay != null && !mOverlay.isEmpty()) { 19076 mOverlay.getOverlayView().draw(canvas); 19077 } 19078 if (debugDraw()) { 19079 debugDrawFocus(canvas); 19080 } 19081 } else { 19082 draw(canvas); 19083 } 19084 } 19085 } finally { 19086 renderNode.end(canvas); 19087 setDisplayListProperties(renderNode); 19088 } 19089 } else { 19090 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 19091 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 19092 } 19093 return renderNode; 19094 } 19095 resetDisplayList()19096 private void resetDisplayList() { 19097 mRenderNode.discardDisplayList(); 19098 if (mBackgroundRenderNode != null) { 19099 mBackgroundRenderNode.discardDisplayList(); 19100 } 19101 } 19102 19103 /** 19104 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 19105 * 19106 * @return A non-scaled bitmap representing this view or null if cache is disabled. 19107 * 19108 * @see #getDrawingCache(boolean) 19109 * 19110 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19111 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19112 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19113 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19114 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19115 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19116 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19117 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19118 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19119 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19120 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19121 * reports or unit testing the {@link PixelCopy} API is recommended. 19122 */ 19123 @Deprecated getDrawingCache()19124 public Bitmap getDrawingCache() { 19125 return getDrawingCache(false); 19126 } 19127 19128 /** 19129 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 19130 * is null when caching is disabled. If caching is enabled and the cache is not ready, 19131 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 19132 * draw from the cache when the cache is enabled. To benefit from the cache, you must 19133 * request the drawing cache by calling this method and draw it on screen if the 19134 * returned bitmap is not null.</p> 19135 * 19136 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 19137 * this method will create a bitmap of the same size as this view. Because this bitmap 19138 * will be drawn scaled by the parent ViewGroup, the result on screen might show 19139 * scaling artifacts. To avoid such artifacts, you should call this method by setting 19140 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 19141 * size than the view. This implies that your application must be able to handle this 19142 * size.</p> 19143 * 19144 * @param autoScale Indicates whether the generated bitmap should be scaled based on 19145 * the current density of the screen when the application is in compatibility 19146 * mode. 19147 * 19148 * @return A bitmap representing this view or null if cache is disabled. 19149 * 19150 * @see #setDrawingCacheEnabled(boolean) 19151 * @see #isDrawingCacheEnabled() 19152 * @see #buildDrawingCache(boolean) 19153 * @see #destroyDrawingCache() 19154 * 19155 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19156 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19157 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19158 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19159 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19160 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19161 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19162 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19163 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19164 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19165 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19166 * reports or unit testing the {@link PixelCopy} API is recommended. 19167 */ 19168 @Deprecated getDrawingCache(boolean autoScale)19169 public Bitmap getDrawingCache(boolean autoScale) { 19170 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 19171 return null; 19172 } 19173 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 19174 buildDrawingCache(autoScale); 19175 } 19176 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 19177 } 19178 19179 /** 19180 * <p>Frees the resources used by the drawing cache. If you call 19181 * {@link #buildDrawingCache()} manually without calling 19182 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 19183 * should cleanup the cache with this method afterwards.</p> 19184 * 19185 * @see #setDrawingCacheEnabled(boolean) 19186 * @see #buildDrawingCache() 19187 * @see #getDrawingCache() 19188 * 19189 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19190 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19191 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19192 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19193 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19194 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19195 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19196 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19197 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19198 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19199 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19200 * reports or unit testing the {@link PixelCopy} API is recommended. 19201 */ 19202 @Deprecated destroyDrawingCache()19203 public void destroyDrawingCache() { 19204 if (mDrawingCache != null) { 19205 mDrawingCache.recycle(); 19206 mDrawingCache = null; 19207 } 19208 if (mUnscaledDrawingCache != null) { 19209 mUnscaledDrawingCache.recycle(); 19210 mUnscaledDrawingCache = null; 19211 } 19212 } 19213 19214 /** 19215 * Setting a solid background color for the drawing cache's bitmaps will improve 19216 * performance and memory usage. Note, though that this should only be used if this 19217 * view will always be drawn on top of a solid color. 19218 * 19219 * @param color The background color to use for the drawing cache's bitmap 19220 * 19221 * @see #setDrawingCacheEnabled(boolean) 19222 * @see #buildDrawingCache() 19223 * @see #getDrawingCache() 19224 * 19225 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19226 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19227 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19228 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19229 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19230 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19231 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19232 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19233 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19234 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19235 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19236 * reports or unit testing the {@link PixelCopy} API is recommended. 19237 */ 19238 @Deprecated setDrawingCacheBackgroundColor(@olorInt int color)19239 public void setDrawingCacheBackgroundColor(@ColorInt int color) { 19240 if (color != mDrawingCacheBackgroundColor) { 19241 mDrawingCacheBackgroundColor = color; 19242 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 19243 } 19244 } 19245 19246 /** 19247 * @see #setDrawingCacheBackgroundColor(int) 19248 * 19249 * @return The background color to used for the drawing cache's bitmap 19250 * 19251 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19252 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19253 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19254 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19255 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19256 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19257 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19258 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19259 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19260 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19261 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19262 * reports or unit testing the {@link PixelCopy} API is recommended. 19263 */ 19264 @Deprecated 19265 @ColorInt getDrawingCacheBackgroundColor()19266 public int getDrawingCacheBackgroundColor() { 19267 return mDrawingCacheBackgroundColor; 19268 } 19269 19270 /** 19271 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 19272 * 19273 * @see #buildDrawingCache(boolean) 19274 * 19275 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19276 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19277 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19278 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19279 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19280 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19281 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19282 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19283 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19284 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19285 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19286 * reports or unit testing the {@link PixelCopy} API is recommended. 19287 */ 19288 @Deprecated buildDrawingCache()19289 public void buildDrawingCache() { 19290 buildDrawingCache(false); 19291 } 19292 19293 /** 19294 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 19295 * 19296 * <p>If you call {@link #buildDrawingCache()} manually without calling 19297 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 19298 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 19299 * 19300 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 19301 * this method will create a bitmap of the same size as this view. Because this bitmap 19302 * will be drawn scaled by the parent ViewGroup, the result on screen might show 19303 * scaling artifacts. To avoid such artifacts, you should call this method by setting 19304 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 19305 * size than the view. This implies that your application must be able to handle this 19306 * size.</p> 19307 * 19308 * <p>You should avoid calling this method when hardware acceleration is enabled. If 19309 * you do not need the drawing cache bitmap, calling this method will increase memory 19310 * usage and cause the view to be rendered in software once, thus negatively impacting 19311 * performance.</p> 19312 * 19313 * @see #getDrawingCache() 19314 * @see #destroyDrawingCache() 19315 * 19316 * @deprecated The view drawing cache was largely made obsolete with the introduction of 19317 * hardware-accelerated rendering in API 11. With hardware-acceleration, intermediate cache 19318 * layers are largely unnecessary and can easily result in a net loss in performance due to the 19319 * cost of creating and updating the layer. In the rare cases where caching layers are useful, 19320 * such as for alpha animations, {@link #setLayerType(int, Paint)} handles this with hardware 19321 * rendering. For software-rendered snapshots of a small part of the View hierarchy or 19322 * individual Views it is recommended to create a {@link Canvas} from either a {@link Bitmap} or 19323 * {@link android.graphics.Picture} and call {@link #draw(Canvas)} on the View. However these 19324 * software-rendered usages are discouraged and have compatibility issues with hardware-only 19325 * rendering features such as {@link android.graphics.Bitmap.Config#HARDWARE Config.HARDWARE} 19326 * bitmaps, real-time shadows, and outline clipping. For screenshots of the UI for feedback 19327 * reports or unit testing the {@link PixelCopy} API is recommended. 19328 */ 19329 @Deprecated buildDrawingCache(boolean autoScale)19330 public void buildDrawingCache(boolean autoScale) { 19331 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 19332 mDrawingCache == null : mUnscaledDrawingCache == null)) { 19333 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 19334 Trace.traceBegin(Trace.TRACE_TAG_VIEW, 19335 "buildDrawingCache/SW Layer for " + getClass().getSimpleName()); 19336 } 19337 try { 19338 buildDrawingCacheImpl(autoScale); 19339 } finally { 19340 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 19341 } 19342 } 19343 } 19344 19345 /** 19346 * private, internal implementation of buildDrawingCache, used to enable tracing 19347 */ buildDrawingCacheImpl(boolean autoScale)19348 private void buildDrawingCacheImpl(boolean autoScale) { 19349 mCachingFailed = false; 19350 19351 int width = mRight - mLeft; 19352 int height = mBottom - mTop; 19353 19354 final AttachInfo attachInfo = mAttachInfo; 19355 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 19356 19357 if (autoScale && scalingRequired) { 19358 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 19359 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 19360 } 19361 19362 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 19363 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 19364 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 19365 19366 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 19367 final long drawingCacheSize = 19368 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 19369 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 19370 if (width > 0 && height > 0) { 19371 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is" 19372 + " too large to fit into a software layer (or drawing cache), needs " 19373 + projectedBitmapSize + " bytes, only " 19374 + drawingCacheSize + " available"); 19375 } 19376 destroyDrawingCache(); 19377 mCachingFailed = true; 19378 return; 19379 } 19380 19381 boolean clear = true; 19382 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 19383 19384 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 19385 Bitmap.Config quality; 19386 if (!opaque) { 19387 // Never pick ARGB_4444 because it looks awful 19388 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 19389 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 19390 case DRAWING_CACHE_QUALITY_AUTO: 19391 case DRAWING_CACHE_QUALITY_LOW: 19392 case DRAWING_CACHE_QUALITY_HIGH: 19393 default: 19394 quality = Bitmap.Config.ARGB_8888; 19395 break; 19396 } 19397 } else { 19398 // Optimization for translucent windows 19399 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 19400 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 19401 } 19402 19403 // Try to cleanup memory 19404 if (bitmap != null) bitmap.recycle(); 19405 19406 try { 19407 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 19408 width, height, quality); 19409 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 19410 if (autoScale) { 19411 mDrawingCache = bitmap; 19412 } else { 19413 mUnscaledDrawingCache = bitmap; 19414 } 19415 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 19416 } catch (OutOfMemoryError e) { 19417 // If there is not enough memory to create the bitmap cache, just 19418 // ignore the issue as bitmap caches are not required to draw the 19419 // view hierarchy 19420 if (autoScale) { 19421 mDrawingCache = null; 19422 } else { 19423 mUnscaledDrawingCache = null; 19424 } 19425 mCachingFailed = true; 19426 return; 19427 } 19428 19429 clear = drawingCacheBackgroundColor != 0; 19430 } 19431 19432 Canvas canvas; 19433 if (attachInfo != null) { 19434 canvas = attachInfo.mCanvas; 19435 if (canvas == null) { 19436 canvas = new Canvas(); 19437 } 19438 canvas.setBitmap(bitmap); 19439 // Temporarily clobber the cached Canvas in case one of our children 19440 // is also using a drawing cache. Without this, the children would 19441 // steal the canvas by attaching their own bitmap to it and bad, bad 19442 // thing would happen (invisible views, corrupted drawings, etc.) 19443 attachInfo.mCanvas = null; 19444 } else { 19445 // This case should hopefully never or seldom happen 19446 canvas = new Canvas(bitmap); 19447 } 19448 19449 if (clear) { 19450 bitmap.eraseColor(drawingCacheBackgroundColor); 19451 } 19452 19453 computeScroll(); 19454 final int restoreCount = canvas.save(); 19455 19456 if (autoScale && scalingRequired) { 19457 final float scale = attachInfo.mApplicationScale; 19458 canvas.scale(scale, scale); 19459 } 19460 19461 canvas.translate(-mScrollX, -mScrollY); 19462 19463 mPrivateFlags |= PFLAG_DRAWN; 19464 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 19465 mLayerType != LAYER_TYPE_NONE) { 19466 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 19467 } 19468 19469 // Fast path for layouts with no backgrounds 19470 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 19471 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 19472 dispatchDraw(canvas); 19473 drawAutofilledHighlight(canvas); 19474 if (mOverlay != null && !mOverlay.isEmpty()) { 19475 mOverlay.getOverlayView().draw(canvas); 19476 } 19477 } else { 19478 draw(canvas); 19479 } 19480 19481 canvas.restoreToCount(restoreCount); 19482 canvas.setBitmap(null); 19483 19484 if (attachInfo != null) { 19485 // Restore the cached Canvas for our siblings 19486 attachInfo.mCanvas = canvas; 19487 } 19488 } 19489 19490 /** 19491 * Create a snapshot of the view into a bitmap. We should probably make 19492 * some form of this public, but should think about the API. 19493 * 19494 * @hide 19495 */ createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren)19496 public Bitmap createSnapshot(ViewDebug.CanvasProvider canvasProvider, boolean skipChildren) { 19497 int width = mRight - mLeft; 19498 int height = mBottom - mTop; 19499 19500 final AttachInfo attachInfo = mAttachInfo; 19501 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 19502 width = (int) ((width * scale) + 0.5f); 19503 height = (int) ((height * scale) + 0.5f); 19504 19505 Canvas oldCanvas = null; 19506 try { 19507 Canvas canvas = canvasProvider.getCanvas(this, 19508 width > 0 ? width : 1, height > 0 ? height : 1); 19509 19510 if (attachInfo != null) { 19511 oldCanvas = attachInfo.mCanvas; 19512 // Temporarily clobber the cached Canvas in case one of our children 19513 // is also using a drawing cache. Without this, the children would 19514 // steal the canvas by attaching their own bitmap to it and bad, bad 19515 // things would happen (invisible views, corrupted drawings, etc.) 19516 attachInfo.mCanvas = null; 19517 } 19518 19519 computeScroll(); 19520 final int restoreCount = canvas.save(); 19521 canvas.scale(scale, scale); 19522 canvas.translate(-mScrollX, -mScrollY); 19523 19524 // Temporarily remove the dirty mask 19525 int flags = mPrivateFlags; 19526 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 19527 19528 // Fast path for layouts with no backgrounds 19529 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 19530 dispatchDraw(canvas); 19531 drawAutofilledHighlight(canvas); 19532 if (mOverlay != null && !mOverlay.isEmpty()) { 19533 mOverlay.getOverlayView().draw(canvas); 19534 } 19535 } else { 19536 draw(canvas); 19537 } 19538 19539 mPrivateFlags = flags; 19540 canvas.restoreToCount(restoreCount); 19541 return canvasProvider.createBitmap(); 19542 } finally { 19543 if (oldCanvas != null) { 19544 attachInfo.mCanvas = oldCanvas; 19545 } 19546 } 19547 } 19548 19549 /** 19550 * Indicates whether this View is currently in edit mode. A View is usually 19551 * in edit mode when displayed within a developer tool. For instance, if 19552 * this View is being drawn by a visual user interface builder, this method 19553 * should return true. 19554 * 19555 * Subclasses should check the return value of this method to provide 19556 * different behaviors if their normal behavior might interfere with the 19557 * host environment. For instance: the class spawns a thread in its 19558 * constructor, the drawing code relies on device-specific features, etc. 19559 * 19560 * This method is usually checked in the drawing code of custom widgets. 19561 * 19562 * @return True if this View is in edit mode, false otherwise. 19563 */ isInEditMode()19564 public boolean isInEditMode() { 19565 return false; 19566 } 19567 19568 /** 19569 * If the View draws content inside its padding and enables fading edges, 19570 * it needs to support padding offsets. Padding offsets are added to the 19571 * fading edges to extend the length of the fade so that it covers pixels 19572 * drawn inside the padding. 19573 * 19574 * Subclasses of this class should override this method if they need 19575 * to draw content inside the padding. 19576 * 19577 * @return True if padding offset must be applied, false otherwise. 19578 * 19579 * @see #getLeftPaddingOffset() 19580 * @see #getRightPaddingOffset() 19581 * @see #getTopPaddingOffset() 19582 * @see #getBottomPaddingOffset() 19583 * 19584 * @since CURRENT 19585 */ isPaddingOffsetRequired()19586 protected boolean isPaddingOffsetRequired() { 19587 return false; 19588 } 19589 19590 /** 19591 * Amount by which to extend the left fading region. Called only when 19592 * {@link #isPaddingOffsetRequired()} returns true. 19593 * 19594 * @return The left padding offset in pixels. 19595 * 19596 * @see #isPaddingOffsetRequired() 19597 * 19598 * @since CURRENT 19599 */ getLeftPaddingOffset()19600 protected int getLeftPaddingOffset() { 19601 return 0; 19602 } 19603 19604 /** 19605 * Amount by which to extend the right fading region. Called only when 19606 * {@link #isPaddingOffsetRequired()} returns true. 19607 * 19608 * @return The right padding offset in pixels. 19609 * 19610 * @see #isPaddingOffsetRequired() 19611 * 19612 * @since CURRENT 19613 */ getRightPaddingOffset()19614 protected int getRightPaddingOffset() { 19615 return 0; 19616 } 19617 19618 /** 19619 * Amount by which to extend the top fading region. Called only when 19620 * {@link #isPaddingOffsetRequired()} returns true. 19621 * 19622 * @return The top padding offset in pixels. 19623 * 19624 * @see #isPaddingOffsetRequired() 19625 * 19626 * @since CURRENT 19627 */ getTopPaddingOffset()19628 protected int getTopPaddingOffset() { 19629 return 0; 19630 } 19631 19632 /** 19633 * Amount by which to extend the bottom fading region. Called only when 19634 * {@link #isPaddingOffsetRequired()} returns true. 19635 * 19636 * @return The bottom padding offset in pixels. 19637 * 19638 * @see #isPaddingOffsetRequired() 19639 * 19640 * @since CURRENT 19641 */ getBottomPaddingOffset()19642 protected int getBottomPaddingOffset() { 19643 return 0; 19644 } 19645 19646 /** 19647 * @hide 19648 * @param offsetRequired 19649 */ getFadeTop(boolean offsetRequired)19650 protected int getFadeTop(boolean offsetRequired) { 19651 int top = mPaddingTop; 19652 if (offsetRequired) top += getTopPaddingOffset(); 19653 return top; 19654 } 19655 19656 /** 19657 * @hide 19658 * @param offsetRequired 19659 */ getFadeHeight(boolean offsetRequired)19660 protected int getFadeHeight(boolean offsetRequired) { 19661 int padding = mPaddingTop; 19662 if (offsetRequired) padding += getTopPaddingOffset(); 19663 return mBottom - mTop - mPaddingBottom - padding; 19664 } 19665 19666 /** 19667 * <p>Indicates whether this view is attached to a hardware accelerated 19668 * window or not.</p> 19669 * 19670 * <p>Even if this method returns true, it does not mean that every call 19671 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 19672 * accelerated {@link android.graphics.Canvas}. For instance, if this view 19673 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 19674 * window is hardware accelerated, 19675 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 19676 * return false, and this method will return true.</p> 19677 * 19678 * @return True if the view is attached to a window and the window is 19679 * hardware accelerated; false in any other case. 19680 */ 19681 @ViewDebug.ExportedProperty(category = "drawing") isHardwareAccelerated()19682 public boolean isHardwareAccelerated() { 19683 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 19684 } 19685 19686 /** 19687 * Sets a rectangular area on this view to which the view will be clipped 19688 * when it is drawn. Setting the value to null will remove the clip bounds 19689 * and the view will draw normally, using its full bounds. 19690 * 19691 * @param clipBounds The rectangular area, in the local coordinates of 19692 * this view, to which future drawing operations will be clipped. 19693 */ setClipBounds(Rect clipBounds)19694 public void setClipBounds(Rect clipBounds) { 19695 if (clipBounds == mClipBounds 19696 || (clipBounds != null && clipBounds.equals(mClipBounds))) { 19697 return; 19698 } 19699 if (clipBounds != null) { 19700 if (mClipBounds == null) { 19701 mClipBounds = new Rect(clipBounds); 19702 } else { 19703 mClipBounds.set(clipBounds); 19704 } 19705 } else { 19706 mClipBounds = null; 19707 } 19708 mRenderNode.setClipBounds(mClipBounds); 19709 invalidateViewProperty(false, false); 19710 } 19711 19712 /** 19713 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 19714 * 19715 * @return A copy of the current clip bounds if clip bounds are set, 19716 * otherwise null. 19717 */ getClipBounds()19718 public Rect getClipBounds() { 19719 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 19720 } 19721 19722 19723 /** 19724 * Populates an output rectangle with the clip bounds of the view, 19725 * returning {@code true} if successful or {@code false} if the view's 19726 * clip bounds are {@code null}. 19727 * 19728 * @param outRect rectangle in which to place the clip bounds of the view 19729 * @return {@code true} if successful or {@code false} if the view's 19730 * clip bounds are {@code null} 19731 */ getClipBounds(Rect outRect)19732 public boolean getClipBounds(Rect outRect) { 19733 if (mClipBounds != null) { 19734 outRect.set(mClipBounds); 19735 return true; 19736 } 19737 return false; 19738 } 19739 19740 /** 19741 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 19742 * case of an active Animation being run on the view. 19743 */ applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)19744 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, 19745 Animation a, boolean scalingRequired) { 19746 Transformation invalidationTransform; 19747 final int flags = parent.mGroupFlags; 19748 final boolean initialized = a.isInitialized(); 19749 if (!initialized) { 19750 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 19751 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 19752 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 19753 onAnimationStart(); 19754 } 19755 19756 final Transformation t = parent.getChildTransformation(); 19757 boolean more = a.getTransformation(drawingTime, t, 1f); 19758 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 19759 if (parent.mInvalidationTransformation == null) { 19760 parent.mInvalidationTransformation = new Transformation(); 19761 } 19762 invalidationTransform = parent.mInvalidationTransformation; 19763 a.getTransformation(drawingTime, invalidationTransform, 1f); 19764 } else { 19765 invalidationTransform = t; 19766 } 19767 19768 if (more) { 19769 if (!a.willChangeBounds()) { 19770 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 19771 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 19772 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 19773 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 19774 // The child need to draw an animation, potentially offscreen, so 19775 // make sure we do not cancel invalidate requests 19776 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 19777 parent.invalidate(mLeft, mTop, mRight, mBottom); 19778 } 19779 } else { 19780 if (parent.mInvalidateRegion == null) { 19781 parent.mInvalidateRegion = new RectF(); 19782 } 19783 final RectF region = parent.mInvalidateRegion; 19784 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 19785 invalidationTransform); 19786 19787 // The child need to draw an animation, potentially offscreen, so 19788 // make sure we do not cancel invalidate requests 19789 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 19790 19791 final int left = mLeft + (int) region.left; 19792 final int top = mTop + (int) region.top; 19793 parent.invalidate(left, top, left + (int) (region.width() + .5f), 19794 top + (int) (region.height() + .5f)); 19795 } 19796 } 19797 return more; 19798 } 19799 19800 /** 19801 * This method is called by getDisplayList() when a display list is recorded for a View. 19802 * It pushes any properties to the RenderNode that aren't managed by the RenderNode. 19803 */ setDisplayListProperties(RenderNode renderNode)19804 void setDisplayListProperties(RenderNode renderNode) { 19805 if (renderNode != null) { 19806 renderNode.setHasOverlappingRendering(getHasOverlappingRendering()); 19807 renderNode.setClipToBounds(mParent instanceof ViewGroup 19808 && ((ViewGroup) mParent).getClipChildren()); 19809 19810 float alpha = 1; 19811 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 19812 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 19813 ViewGroup parentVG = (ViewGroup) mParent; 19814 final Transformation t = parentVG.getChildTransformation(); 19815 if (parentVG.getChildStaticTransformation(this, t)) { 19816 final int transformType = t.getTransformationType(); 19817 if (transformType != Transformation.TYPE_IDENTITY) { 19818 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 19819 alpha = t.getAlpha(); 19820 } 19821 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 19822 renderNode.setStaticMatrix(t.getMatrix()); 19823 } 19824 } 19825 } 19826 } 19827 if (mTransformationInfo != null) { 19828 alpha *= getFinalAlpha(); 19829 if (alpha < 1) { 19830 final int multipliedAlpha = (int) (255 * alpha); 19831 if (onSetAlpha(multipliedAlpha)) { 19832 alpha = 1; 19833 } 19834 } 19835 renderNode.setAlpha(alpha); 19836 } else if (alpha < 1) { 19837 renderNode.setAlpha(alpha); 19838 } 19839 } 19840 } 19841 19842 /** 19843 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 19844 * 19845 * This is where the View specializes rendering behavior based on layer type, 19846 * and hardware acceleration. 19847 */ draw(Canvas canvas, ViewGroup parent, long drawingTime)19848 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 19849 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated(); 19850 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList. 19851 * 19852 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't 19853 * HW accelerated, it can't handle drawing RenderNodes. 19854 */ 19855 boolean drawingWithRenderNode = mAttachInfo != null 19856 && mAttachInfo.mHardwareAccelerated 19857 && hardwareAcceleratedCanvas; 19858 19859 boolean more = false; 19860 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 19861 final int parentFlags = parent.mGroupFlags; 19862 19863 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) { 19864 parent.getChildTransformation().clear(); 19865 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 19866 } 19867 19868 Transformation transformToApply = null; 19869 boolean concatMatrix = false; 19870 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired; 19871 final Animation a = getAnimation(); 19872 if (a != null) { 19873 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); 19874 concatMatrix = a.willChangeTransformationMatrix(); 19875 if (concatMatrix) { 19876 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 19877 } 19878 transformToApply = parent.getChildTransformation(); 19879 } else { 19880 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { 19881 // No longer animating: clear out old animation matrix 19882 mRenderNode.setAnimationMatrix(null); 19883 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 19884 } 19885 if (!drawingWithRenderNode 19886 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 19887 final Transformation t = parent.getChildTransformation(); 19888 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 19889 if (hasTransform) { 19890 final int transformType = t.getTransformationType(); 19891 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 19892 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 19893 } 19894 } 19895 } 19896 19897 concatMatrix |= !childHasIdentityMatrix; 19898 19899 // Sets the flag as early as possible to allow draw() implementations 19900 // to call invalidate() successfully when doing animations 19901 mPrivateFlags |= PFLAG_DRAWN; 19902 19903 if (!concatMatrix && 19904 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 19905 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 19906 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 19907 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 19908 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 19909 return more; 19910 } 19911 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 19912 19913 if (hardwareAcceleratedCanvas) { 19914 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 19915 // retain the flag's value temporarily in the mRecreateDisplayList flag 19916 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0; 19917 mPrivateFlags &= ~PFLAG_INVALIDATED; 19918 } 19919 19920 RenderNode renderNode = null; 19921 Bitmap cache = null; 19922 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local 19923 if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) { 19924 if (layerType != LAYER_TYPE_NONE) { 19925 // If not drawing with RenderNode, treat HW layers as SW 19926 layerType = LAYER_TYPE_SOFTWARE; 19927 buildDrawingCache(true); 19928 } 19929 cache = getDrawingCache(true); 19930 } 19931 19932 if (drawingWithRenderNode) { 19933 // Delay getting the display list until animation-driven alpha values are 19934 // set up and possibly passed on to the view 19935 renderNode = updateDisplayListIfDirty(); 19936 if (!renderNode.isValid()) { 19937 // Uncommon, but possible. If a view is removed from the hierarchy during the call 19938 // to getDisplayList(), the display list will be marked invalid and we should not 19939 // try to use it again. 19940 renderNode = null; 19941 drawingWithRenderNode = false; 19942 } 19943 } 19944 19945 int sx = 0; 19946 int sy = 0; 19947 if (!drawingWithRenderNode) { 19948 computeScroll(); 19949 sx = mScrollX; 19950 sy = mScrollY; 19951 } 19952 19953 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode; 19954 final boolean offsetForScroll = cache == null && !drawingWithRenderNode; 19955 19956 int restoreTo = -1; 19957 if (!drawingWithRenderNode || transformToApply != null) { 19958 restoreTo = canvas.save(); 19959 } 19960 if (offsetForScroll) { 19961 canvas.translate(mLeft - sx, mTop - sy); 19962 } else { 19963 if (!drawingWithRenderNode) { 19964 canvas.translate(mLeft, mTop); 19965 } 19966 if (scalingRequired) { 19967 if (drawingWithRenderNode) { 19968 // TODO: Might not need this if we put everything inside the DL 19969 restoreTo = canvas.save(); 19970 } 19971 // mAttachInfo cannot be null, otherwise scalingRequired == false 19972 final float scale = 1.0f / mAttachInfo.mApplicationScale; 19973 canvas.scale(scale, scale); 19974 } 19975 } 19976 19977 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha()); 19978 if (transformToApply != null 19979 || alpha < 1 19980 || !hasIdentityMatrix() 19981 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 19982 if (transformToApply != null || !childHasIdentityMatrix) { 19983 int transX = 0; 19984 int transY = 0; 19985 19986 if (offsetForScroll) { 19987 transX = -sx; 19988 transY = -sy; 19989 } 19990 19991 if (transformToApply != null) { 19992 if (concatMatrix) { 19993 if (drawingWithRenderNode) { 19994 renderNode.setAnimationMatrix(transformToApply.getMatrix()); 19995 } else { 19996 // Undo the scroll translation, apply the transformation matrix, 19997 // then redo the scroll translate to get the correct result. 19998 canvas.translate(-transX, -transY); 19999 canvas.concat(transformToApply.getMatrix()); 20000 canvas.translate(transX, transY); 20001 } 20002 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 20003 } 20004 20005 float transformAlpha = transformToApply.getAlpha(); 20006 if (transformAlpha < 1) { 20007 alpha *= transformAlpha; 20008 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 20009 } 20010 } 20011 20012 if (!childHasIdentityMatrix && !drawingWithRenderNode) { 20013 canvas.translate(-transX, -transY); 20014 canvas.concat(getMatrix()); 20015 canvas.translate(transX, transY); 20016 } 20017 } 20018 20019 // Deal with alpha if it is or used to be <1 20020 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 20021 if (alpha < 1) { 20022 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 20023 } else { 20024 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 20025 } 20026 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 20027 if (!drawingWithDrawingCache) { 20028 final int multipliedAlpha = (int) (255 * alpha); 20029 if (!onSetAlpha(multipliedAlpha)) { 20030 if (drawingWithRenderNode) { 20031 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 20032 } else if (layerType == LAYER_TYPE_NONE) { 20033 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), 20034 multipliedAlpha); 20035 } 20036 } else { 20037 // Alpha is handled by the child directly, clobber the layer's alpha 20038 mPrivateFlags |= PFLAG_ALPHA_SET; 20039 } 20040 } 20041 } 20042 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 20043 onSetAlpha(255); 20044 mPrivateFlags &= ~PFLAG_ALPHA_SET; 20045 } 20046 20047 if (!drawingWithRenderNode) { 20048 // apply clips directly, since RenderNode won't do it for this draw 20049 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) { 20050 if (offsetForScroll) { 20051 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight()); 20052 } else { 20053 if (!scalingRequired || cache == null) { 20054 canvas.clipRect(0, 0, getWidth(), getHeight()); 20055 } else { 20056 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 20057 } 20058 } 20059 } 20060 20061 if (mClipBounds != null) { 20062 // clip bounds ignore scroll 20063 canvas.clipRect(mClipBounds); 20064 } 20065 } 20066 20067 if (!drawingWithDrawingCache) { 20068 if (drawingWithRenderNode) { 20069 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 20070 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 20071 } else { 20072 // Fast path for layouts with no backgrounds 20073 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 20074 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 20075 dispatchDraw(canvas); 20076 } else { 20077 draw(canvas); 20078 } 20079 } 20080 } else if (cache != null) { 20081 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 20082 if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) { 20083 // no layer paint, use temporary paint to draw bitmap 20084 Paint cachePaint = parent.mCachePaint; 20085 if (cachePaint == null) { 20086 cachePaint = new Paint(); 20087 cachePaint.setDither(false); 20088 parent.mCachePaint = cachePaint; 20089 } 20090 cachePaint.setAlpha((int) (alpha * 255)); 20091 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 20092 } else { 20093 // use layer paint to draw the bitmap, merging the two alphas, but also restore 20094 int layerPaintAlpha = mLayerPaint.getAlpha(); 20095 if (alpha < 1) { 20096 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha)); 20097 } 20098 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint); 20099 if (alpha < 1) { 20100 mLayerPaint.setAlpha(layerPaintAlpha); 20101 } 20102 } 20103 } 20104 20105 if (restoreTo >= 0) { 20106 canvas.restoreToCount(restoreTo); 20107 } 20108 20109 if (a != null && !more) { 20110 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) { 20111 onSetAlpha(255); 20112 } 20113 parent.finishAnimatingView(this, a); 20114 } 20115 20116 if (more && hardwareAcceleratedCanvas) { 20117 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 20118 // alpha animations should cause the child to recreate its display list 20119 invalidate(true); 20120 } 20121 } 20122 20123 mRecreateDisplayList = false; 20124 20125 return more; 20126 } 20127 getDebugPaint()20128 static Paint getDebugPaint() { 20129 if (sDebugPaint == null) { 20130 sDebugPaint = new Paint(); 20131 sDebugPaint.setAntiAlias(false); 20132 } 20133 return sDebugPaint; 20134 } 20135 dipsToPixels(int dips)20136 final int dipsToPixels(int dips) { 20137 float scale = getContext().getResources().getDisplayMetrics().density; 20138 return (int) (dips * scale + 0.5f); 20139 } 20140 debugDrawFocus(Canvas canvas)20141 final private void debugDrawFocus(Canvas canvas) { 20142 if (isFocused()) { 20143 final int cornerSquareSize = dipsToPixels(DEBUG_CORNERS_SIZE_DIP); 20144 final int l = mScrollX; 20145 final int r = l + mRight - mLeft; 20146 final int t = mScrollY; 20147 final int b = t + mBottom - mTop; 20148 20149 final Paint paint = getDebugPaint(); 20150 paint.setColor(DEBUG_CORNERS_COLOR); 20151 20152 // Draw squares in corners. 20153 paint.setStyle(Paint.Style.FILL); 20154 canvas.drawRect(l, t, l + cornerSquareSize, t + cornerSquareSize, paint); 20155 canvas.drawRect(r - cornerSquareSize, t, r, t + cornerSquareSize, paint); 20156 canvas.drawRect(l, b - cornerSquareSize, l + cornerSquareSize, b, paint); 20157 canvas.drawRect(r - cornerSquareSize, b - cornerSquareSize, r, b, paint); 20158 20159 // Draw big X across the view. 20160 paint.setStyle(Paint.Style.STROKE); 20161 canvas.drawLine(l, t, r, b, paint); 20162 canvas.drawLine(l, b, r, t, paint); 20163 } 20164 } 20165 20166 /** 20167 * Manually render this view (and all of its children) to the given Canvas. 20168 * The view must have already done a full layout before this function is 20169 * called. When implementing a view, implement 20170 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 20171 * If you do need to override this method, call the superclass version. 20172 * 20173 * @param canvas The Canvas to which the View is rendered. 20174 */ 20175 @CallSuper draw(Canvas canvas)20176 public void draw(Canvas canvas) { 20177 final int privateFlags = mPrivateFlags; 20178 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 20179 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 20180 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 20181 20182 /* 20183 * Draw traversal performs several drawing steps which must be executed 20184 * in the appropriate order: 20185 * 20186 * 1. Draw the background 20187 * 2. If necessary, save the canvas' layers to prepare for fading 20188 * 3. Draw view's content 20189 * 4. Draw children 20190 * 5. If necessary, draw the fading edges and restore layers 20191 * 6. Draw decorations (scrollbars for instance) 20192 */ 20193 20194 // Step 1, draw the background, if needed 20195 int saveCount; 20196 20197 if (!dirtyOpaque) { 20198 drawBackground(canvas); 20199 } 20200 20201 // skip step 2 & 5 if possible (common case) 20202 final int viewFlags = mViewFlags; 20203 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 20204 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 20205 if (!verticalEdges && !horizontalEdges) { 20206 // Step 3, draw the content 20207 if (!dirtyOpaque) onDraw(canvas); 20208 20209 // Step 4, draw the children 20210 dispatchDraw(canvas); 20211 20212 drawAutofilledHighlight(canvas); 20213 20214 // Overlay is part of the content and draws beneath Foreground 20215 if (mOverlay != null && !mOverlay.isEmpty()) { 20216 mOverlay.getOverlayView().dispatchDraw(canvas); 20217 } 20218 20219 // Step 6, draw decorations (foreground, scrollbars) 20220 onDrawForeground(canvas); 20221 20222 // Step 7, draw the default focus highlight 20223 drawDefaultFocusHighlight(canvas); 20224 20225 if (debugDraw()) { 20226 debugDrawFocus(canvas); 20227 } 20228 20229 // we're done... 20230 return; 20231 } 20232 20233 /* 20234 * Here we do the full fledged routine... 20235 * (this is an uncommon case where speed matters less, 20236 * this is why we repeat some of the tests that have been 20237 * done above) 20238 */ 20239 20240 boolean drawTop = false; 20241 boolean drawBottom = false; 20242 boolean drawLeft = false; 20243 boolean drawRight = false; 20244 20245 float topFadeStrength = 0.0f; 20246 float bottomFadeStrength = 0.0f; 20247 float leftFadeStrength = 0.0f; 20248 float rightFadeStrength = 0.0f; 20249 20250 // Step 2, save the canvas' layers 20251 int paddingLeft = mPaddingLeft; 20252 20253 final boolean offsetRequired = isPaddingOffsetRequired(); 20254 if (offsetRequired) { 20255 paddingLeft += getLeftPaddingOffset(); 20256 } 20257 20258 int left = mScrollX + paddingLeft; 20259 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 20260 int top = mScrollY + getFadeTop(offsetRequired); 20261 int bottom = top + getFadeHeight(offsetRequired); 20262 20263 if (offsetRequired) { 20264 right += getRightPaddingOffset(); 20265 bottom += getBottomPaddingOffset(); 20266 } 20267 20268 final ScrollabilityCache scrollabilityCache = mScrollCache; 20269 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 20270 int length = (int) fadeHeight; 20271 20272 // clip the fade length if top and bottom fades overlap 20273 // overlapping fades produce odd-looking artifacts 20274 if (verticalEdges && (top + length > bottom - length)) { 20275 length = (bottom - top) / 2; 20276 } 20277 20278 // also clip horizontal fades if necessary 20279 if (horizontalEdges && (left + length > right - length)) { 20280 length = (right - left) / 2; 20281 } 20282 20283 if (verticalEdges) { 20284 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 20285 drawTop = topFadeStrength * fadeHeight > 1.0f; 20286 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 20287 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 20288 } 20289 20290 if (horizontalEdges) { 20291 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 20292 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 20293 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 20294 drawRight = rightFadeStrength * fadeHeight > 1.0f; 20295 } 20296 20297 saveCount = canvas.getSaveCount(); 20298 20299 int solidColor = getSolidColor(); 20300 if (solidColor == 0) { 20301 if (drawTop) { 20302 canvas.saveUnclippedLayer(left, top, right, top + length); 20303 } 20304 20305 if (drawBottom) { 20306 canvas.saveUnclippedLayer(left, bottom - length, right, bottom); 20307 } 20308 20309 if (drawLeft) { 20310 canvas.saveUnclippedLayer(left, top, left + length, bottom); 20311 } 20312 20313 if (drawRight) { 20314 canvas.saveUnclippedLayer(right - length, top, right, bottom); 20315 } 20316 } else { 20317 scrollabilityCache.setFadeColor(solidColor); 20318 } 20319 20320 // Step 3, draw the content 20321 if (!dirtyOpaque) onDraw(canvas); 20322 20323 // Step 4, draw the children 20324 dispatchDraw(canvas); 20325 20326 // Step 5, draw the fade effect and restore layers 20327 final Paint p = scrollabilityCache.paint; 20328 final Matrix matrix = scrollabilityCache.matrix; 20329 final Shader fade = scrollabilityCache.shader; 20330 20331 if (drawTop) { 20332 matrix.setScale(1, fadeHeight * topFadeStrength); 20333 matrix.postTranslate(left, top); 20334 fade.setLocalMatrix(matrix); 20335 p.setShader(fade); 20336 canvas.drawRect(left, top, right, top + length, p); 20337 } 20338 20339 if (drawBottom) { 20340 matrix.setScale(1, fadeHeight * bottomFadeStrength); 20341 matrix.postRotate(180); 20342 matrix.postTranslate(left, bottom); 20343 fade.setLocalMatrix(matrix); 20344 p.setShader(fade); 20345 canvas.drawRect(left, bottom - length, right, bottom, p); 20346 } 20347 20348 if (drawLeft) { 20349 matrix.setScale(1, fadeHeight * leftFadeStrength); 20350 matrix.postRotate(-90); 20351 matrix.postTranslate(left, top); 20352 fade.setLocalMatrix(matrix); 20353 p.setShader(fade); 20354 canvas.drawRect(left, top, left + length, bottom, p); 20355 } 20356 20357 if (drawRight) { 20358 matrix.setScale(1, fadeHeight * rightFadeStrength); 20359 matrix.postRotate(90); 20360 matrix.postTranslate(right, top); 20361 fade.setLocalMatrix(matrix); 20362 p.setShader(fade); 20363 canvas.drawRect(right - length, top, right, bottom, p); 20364 } 20365 20366 canvas.restoreToCount(saveCount); 20367 20368 drawAutofilledHighlight(canvas); 20369 20370 // Overlay is part of the content and draws beneath Foreground 20371 if (mOverlay != null && !mOverlay.isEmpty()) { 20372 mOverlay.getOverlayView().dispatchDraw(canvas); 20373 } 20374 20375 // Step 6, draw decorations (foreground, scrollbars) 20376 onDrawForeground(canvas); 20377 20378 if (debugDraw()) { 20379 debugDrawFocus(canvas); 20380 } 20381 } 20382 20383 /** 20384 * Draws the background onto the specified canvas. 20385 * 20386 * @param canvas Canvas on which to draw the background 20387 */ drawBackground(Canvas canvas)20388 private void drawBackground(Canvas canvas) { 20389 final Drawable background = mBackground; 20390 if (background == null) { 20391 return; 20392 } 20393 20394 setBackgroundBounds(); 20395 20396 // Attempt to use a display list if requested. 20397 if (canvas.isHardwareAccelerated() && mAttachInfo != null 20398 && mAttachInfo.mThreadedRenderer != null) { 20399 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); 20400 20401 final RenderNode renderNode = mBackgroundRenderNode; 20402 if (renderNode != null && renderNode.isValid()) { 20403 setBackgroundRenderNodeProperties(renderNode); 20404 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 20405 return; 20406 } 20407 } 20408 20409 final int scrollX = mScrollX; 20410 final int scrollY = mScrollY; 20411 if ((scrollX | scrollY) == 0) { 20412 background.draw(canvas); 20413 } else { 20414 canvas.translate(scrollX, scrollY); 20415 background.draw(canvas); 20416 canvas.translate(-scrollX, -scrollY); 20417 } 20418 } 20419 20420 /** 20421 * Sets the correct background bounds and rebuilds the outline, if needed. 20422 * <p/> 20423 * This is called by LayoutLib. 20424 */ setBackgroundBounds()20425 void setBackgroundBounds() { 20426 if (mBackgroundSizeChanged && mBackground != null) { 20427 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 20428 mBackgroundSizeChanged = false; 20429 rebuildOutline(); 20430 } 20431 } 20432 setBackgroundRenderNodeProperties(RenderNode renderNode)20433 private void setBackgroundRenderNodeProperties(RenderNode renderNode) { 20434 renderNode.setTranslationX(mScrollX); 20435 renderNode.setTranslationY(mScrollY); 20436 } 20437 20438 /** 20439 * Creates a new display list or updates the existing display list for the 20440 * specified Drawable. 20441 * 20442 * @param drawable Drawable for which to create a display list 20443 * @param renderNode Existing RenderNode, or {@code null} 20444 * @return A valid display list for the specified drawable 20445 */ getDrawableRenderNode(Drawable drawable, RenderNode renderNode)20446 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { 20447 if (renderNode == null) { 20448 renderNode = RenderNode.create(drawable.getClass().getName(), this); 20449 } 20450 20451 final Rect bounds = drawable.getBounds(); 20452 final int width = bounds.width(); 20453 final int height = bounds.height(); 20454 final DisplayListCanvas canvas = renderNode.start(width, height); 20455 20456 // Reverse left/top translation done by drawable canvas, which will 20457 // instead be applied by rendernode's LTRB bounds below. This way, the 20458 // drawable's bounds match with its rendernode bounds and its content 20459 // will lie within those bounds in the rendernode tree. 20460 canvas.translate(-bounds.left, -bounds.top); 20461 20462 try { 20463 drawable.draw(canvas); 20464 } finally { 20465 renderNode.end(canvas); 20466 } 20467 20468 // Set up drawable properties that are view-independent. 20469 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); 20470 renderNode.setProjectBackwards(drawable.isProjected()); 20471 renderNode.setProjectionReceiver(true); 20472 renderNode.setClipToBounds(false); 20473 return renderNode; 20474 } 20475 20476 /** 20477 * Returns the overlay for this view, creating it if it does not yet exist. 20478 * Adding drawables to the overlay will cause them to be displayed whenever 20479 * the view itself is redrawn. Objects in the overlay should be actively 20480 * managed: remove them when they should not be displayed anymore. The 20481 * overlay will always have the same size as its host view. 20482 * 20483 * <p>Note: Overlays do not currently work correctly with {@link 20484 * SurfaceView} or {@link TextureView}; contents in overlays for these 20485 * types of views may not display correctly.</p> 20486 * 20487 * @return The ViewOverlay object for this view. 20488 * @see ViewOverlay 20489 */ getOverlay()20490 public ViewOverlay getOverlay() { 20491 if (mOverlay == null) { 20492 mOverlay = new ViewOverlay(mContext, this); 20493 } 20494 return mOverlay; 20495 } 20496 20497 /** 20498 * Override this if your view is known to always be drawn on top of a solid color background, 20499 * and needs to draw fading edges. Returning a non-zero color enables the view system to 20500 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 20501 * should be set to 0xFF. 20502 * 20503 * @see #setVerticalFadingEdgeEnabled(boolean) 20504 * @see #setHorizontalFadingEdgeEnabled(boolean) 20505 * 20506 * @return The known solid color background for this view, or 0 if the color may vary 20507 */ 20508 @ViewDebug.ExportedProperty(category = "drawing") 20509 @ColorInt getSolidColor()20510 public int getSolidColor() { 20511 return 0; 20512 } 20513 20514 /** 20515 * Build a human readable string representation of the specified view flags. 20516 * 20517 * @param flags the view flags to convert to a string 20518 * @return a String representing the supplied flags 20519 */ printFlags(int flags)20520 private static String printFlags(int flags) { 20521 String output = ""; 20522 int numFlags = 0; 20523 if ((flags & FOCUSABLE) == FOCUSABLE) { 20524 output += "TAKES_FOCUS"; 20525 numFlags++; 20526 } 20527 20528 switch (flags & VISIBILITY_MASK) { 20529 case INVISIBLE: 20530 if (numFlags > 0) { 20531 output += " "; 20532 } 20533 output += "INVISIBLE"; 20534 // USELESS HERE numFlags++; 20535 break; 20536 case GONE: 20537 if (numFlags > 0) { 20538 output += " "; 20539 } 20540 output += "GONE"; 20541 // USELESS HERE numFlags++; 20542 break; 20543 default: 20544 break; 20545 } 20546 return output; 20547 } 20548 20549 /** 20550 * Build a human readable string representation of the specified private 20551 * view flags. 20552 * 20553 * @param privateFlags the private view flags to convert to a string 20554 * @return a String representing the supplied flags 20555 */ printPrivateFlags(int privateFlags)20556 private static String printPrivateFlags(int privateFlags) { 20557 String output = ""; 20558 int numFlags = 0; 20559 20560 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 20561 output += "WANTS_FOCUS"; 20562 numFlags++; 20563 } 20564 20565 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 20566 if (numFlags > 0) { 20567 output += " "; 20568 } 20569 output += "FOCUSED"; 20570 numFlags++; 20571 } 20572 20573 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 20574 if (numFlags > 0) { 20575 output += " "; 20576 } 20577 output += "SELECTED"; 20578 numFlags++; 20579 } 20580 20581 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 20582 if (numFlags > 0) { 20583 output += " "; 20584 } 20585 output += "IS_ROOT_NAMESPACE"; 20586 numFlags++; 20587 } 20588 20589 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 20590 if (numFlags > 0) { 20591 output += " "; 20592 } 20593 output += "HAS_BOUNDS"; 20594 numFlags++; 20595 } 20596 20597 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 20598 if (numFlags > 0) { 20599 output += " "; 20600 } 20601 output += "DRAWN"; 20602 // USELESS HERE numFlags++; 20603 } 20604 return output; 20605 } 20606 20607 /** 20608 * <p>Indicates whether or not this view's layout will be requested during 20609 * the next hierarchy layout pass.</p> 20610 * 20611 * @return true if the layout will be forced during next layout pass 20612 */ isLayoutRequested()20613 public boolean isLayoutRequested() { 20614 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 20615 } 20616 20617 /** 20618 * Return true if o is a ViewGroup that is laying out using optical bounds. 20619 * @hide 20620 */ isLayoutModeOptical(Object o)20621 public static boolean isLayoutModeOptical(Object o) { 20622 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 20623 } 20624 setOpticalFrame(int left, int top, int right, int bottom)20625 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 20626 Insets parentInsets = mParent instanceof View ? 20627 ((View) mParent).getOpticalInsets() : Insets.NONE; 20628 Insets childInsets = getOpticalInsets(); 20629 return setFrame( 20630 left + parentInsets.left - childInsets.left, 20631 top + parentInsets.top - childInsets.top, 20632 right + parentInsets.left + childInsets.right, 20633 bottom + parentInsets.top + childInsets.bottom); 20634 } 20635 20636 /** 20637 * Assign a size and position to a view and all of its 20638 * descendants 20639 * 20640 * <p>This is the second phase of the layout mechanism. 20641 * (The first is measuring). In this phase, each parent calls 20642 * layout on all of its children to position them. 20643 * This is typically done using the child measurements 20644 * that were stored in the measure pass().</p> 20645 * 20646 * <p>Derived classes should not override this method. 20647 * Derived classes with children should override 20648 * onLayout. In that method, they should 20649 * call layout on each of their children.</p> 20650 * 20651 * @param l Left position, relative to parent 20652 * @param t Top position, relative to parent 20653 * @param r Right position, relative to parent 20654 * @param b Bottom position, relative to parent 20655 */ 20656 @SuppressWarnings({"unchecked"}) layout(int l, int t, int r, int b)20657 public void layout(int l, int t, int r, int b) { 20658 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 20659 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 20660 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 20661 } 20662 20663 int oldL = mLeft; 20664 int oldT = mTop; 20665 int oldB = mBottom; 20666 int oldR = mRight; 20667 20668 boolean changed = isLayoutModeOptical(mParent) ? 20669 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 20670 20671 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 20672 onLayout(changed, l, t, r, b); 20673 20674 if (shouldDrawRoundScrollbar()) { 20675 if(mRoundScrollbarRenderer == null) { 20676 mRoundScrollbarRenderer = new RoundScrollbarRenderer(this); 20677 } 20678 } else { 20679 mRoundScrollbarRenderer = null; 20680 } 20681 20682 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 20683 20684 ListenerInfo li = mListenerInfo; 20685 if (li != null && li.mOnLayoutChangeListeners != null) { 20686 ArrayList<OnLayoutChangeListener> listenersCopy = 20687 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 20688 int numListeners = listenersCopy.size(); 20689 for (int i = 0; i < numListeners; ++i) { 20690 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 20691 } 20692 } 20693 } 20694 20695 final boolean wasLayoutValid = isLayoutValid(); 20696 20697 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 20698 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 20699 20700 if (!wasLayoutValid && isFocused()) { 20701 mPrivateFlags &= ~PFLAG_WANTS_FOCUS; 20702 if (canTakeFocus()) { 20703 // We have a robust focus, so parents should no longer be wanting focus. 20704 clearParentsWantFocus(); 20705 } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) { 20706 // This is a weird case. Most-likely the user, rather than ViewRootImpl, called 20707 // layout. In this case, there's no guarantee that parent layouts will be evaluated 20708 // and thus the safest action is to clear focus here. 20709 clearFocusInternal(null, /* propagate */ true, /* refocus */ false); 20710 clearParentsWantFocus(); 20711 } else if (!hasParentWantsFocus()) { 20712 // original requestFocus was likely on this view directly, so just clear focus 20713 clearFocusInternal(null, /* propagate */ true, /* refocus */ false); 20714 } 20715 // otherwise, we let parents handle re-assigning focus during their layout passes. 20716 } else if ((mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) { 20717 mPrivateFlags &= ~PFLAG_WANTS_FOCUS; 20718 View focused = findFocus(); 20719 if (focused != null) { 20720 // Try to restore focus as close as possible to our starting focus. 20721 if (!restoreDefaultFocus() && !hasParentWantsFocus()) { 20722 // Give up and clear focus once we've reached the top-most parent which wants 20723 // focus. 20724 focused.clearFocusInternal(null, /* propagate */ true, /* refocus */ false); 20725 } 20726 } 20727 } 20728 20729 if ((mPrivateFlags3 & PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT) != 0) { 20730 mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT; 20731 notifyEnterOrExitForAutoFillIfNeeded(true); 20732 } 20733 } 20734 hasParentWantsFocus()20735 private boolean hasParentWantsFocus() { 20736 ViewParent parent = mParent; 20737 while (parent instanceof ViewGroup) { 20738 ViewGroup pv = (ViewGroup) parent; 20739 if ((pv.mPrivateFlags & PFLAG_WANTS_FOCUS) != 0) { 20740 return true; 20741 } 20742 parent = pv.mParent; 20743 } 20744 return false; 20745 } 20746 20747 /** 20748 * Called from layout when this view should 20749 * assign a size and position to each of its children. 20750 * 20751 * Derived classes with children should override 20752 * this method and call layout on each of 20753 * their children. 20754 * @param changed This is a new size or position for this view 20755 * @param left Left position, relative to parent 20756 * @param top Top position, relative to parent 20757 * @param right Right position, relative to parent 20758 * @param bottom Bottom position, relative to parent 20759 */ onLayout(boolean changed, int left, int top, int right, int bottom)20760 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 20761 } 20762 20763 /** 20764 * Assign a size and position to this view. 20765 * 20766 * This is called from layout. 20767 * 20768 * @param left Left position, relative to parent 20769 * @param top Top position, relative to parent 20770 * @param right Right position, relative to parent 20771 * @param bottom Bottom position, relative to parent 20772 * @return true if the new size and position are different than the 20773 * previous ones 20774 * {@hide} 20775 */ setFrame(int left, int top, int right, int bottom)20776 protected boolean setFrame(int left, int top, int right, int bottom) { 20777 boolean changed = false; 20778 20779 if (DBG) { 20780 Log.d(VIEW_LOG_TAG, this + " View.setFrame(" + left + "," + top + "," 20781 + right + "," + bottom + ")"); 20782 } 20783 20784 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 20785 changed = true; 20786 20787 // Remember our drawn bit 20788 int drawn = mPrivateFlags & PFLAG_DRAWN; 20789 20790 int oldWidth = mRight - mLeft; 20791 int oldHeight = mBottom - mTop; 20792 int newWidth = right - left; 20793 int newHeight = bottom - top; 20794 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 20795 20796 // Invalidate our old position 20797 invalidate(sizeChanged); 20798 20799 mLeft = left; 20800 mTop = top; 20801 mRight = right; 20802 mBottom = bottom; 20803 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 20804 20805 mPrivateFlags |= PFLAG_HAS_BOUNDS; 20806 20807 20808 if (sizeChanged) { 20809 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 20810 } 20811 20812 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { 20813 // If we are visible, force the DRAWN bit to on so that 20814 // this invalidate will go through (at least to our parent). 20815 // This is because someone may have invalidated this view 20816 // before this call to setFrame came in, thereby clearing 20817 // the DRAWN bit. 20818 mPrivateFlags |= PFLAG_DRAWN; 20819 invalidate(sizeChanged); 20820 // parent display list may need to be recreated based on a change in the bounds 20821 // of any child 20822 invalidateParentCaches(); 20823 } 20824 20825 // Reset drawn bit to original value (invalidate turns it off) 20826 mPrivateFlags |= drawn; 20827 20828 mBackgroundSizeChanged = true; 20829 mDefaultFocusHighlightSizeChanged = true; 20830 if (mForegroundInfo != null) { 20831 mForegroundInfo.mBoundsChanged = true; 20832 } 20833 20834 notifySubtreeAccessibilityStateChangedIfNeeded(); 20835 } 20836 return changed; 20837 } 20838 20839 /** 20840 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}. 20841 * @hide 20842 */ setLeftTopRightBottom(int left, int top, int right, int bottom)20843 public void setLeftTopRightBottom(int left, int top, int right, int bottom) { 20844 setFrame(left, top, right, bottom); 20845 } 20846 sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)20847 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 20848 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 20849 if (mOverlay != null) { 20850 mOverlay.getOverlayView().setRight(newWidth); 20851 mOverlay.getOverlayView().setBottom(newHeight); 20852 } 20853 // If this isn't laid out yet, focus assignment will be handled during the "deferment/ 20854 // backtracking" of requestFocus during layout, so don't touch focus here. 20855 if (!sCanFocusZeroSized && isLayoutValid() 20856 // Don't touch focus if animating 20857 && !(mParent instanceof ViewGroup && ((ViewGroup) mParent).isLayoutSuppressed())) { 20858 if (newWidth <= 0 || newHeight <= 0) { 20859 if (hasFocus()) { 20860 clearFocus(); 20861 if (mParent instanceof ViewGroup) { 20862 ((ViewGroup) mParent).clearFocusedInCluster(); 20863 } 20864 } 20865 clearAccessibilityFocus(); 20866 } else if (oldWidth <= 0 || oldHeight <= 0) { 20867 if (mParent != null && canTakeFocus()) { 20868 mParent.focusableViewAvailable(this); 20869 } 20870 } 20871 } 20872 rebuildOutline(); 20873 } 20874 20875 /** 20876 * Finalize inflating a view from XML. This is called as the last phase 20877 * of inflation, after all child views have been added. 20878 * 20879 * <p>Even if the subclass overrides onFinishInflate, they should always be 20880 * sure to call the super method, so that we get called. 20881 */ 20882 @CallSuper onFinishInflate()20883 protected void onFinishInflate() { 20884 } 20885 20886 /** 20887 * Returns the resources associated with this view. 20888 * 20889 * @return Resources object. 20890 */ getResources()20891 public Resources getResources() { 20892 return mResources; 20893 } 20894 20895 /** 20896 * Invalidates the specified Drawable. 20897 * 20898 * @param drawable the drawable to invalidate 20899 */ 20900 @Override invalidateDrawable(@onNull Drawable drawable)20901 public void invalidateDrawable(@NonNull Drawable drawable) { 20902 if (verifyDrawable(drawable)) { 20903 final Rect dirty = drawable.getDirtyBounds(); 20904 final int scrollX = mScrollX; 20905 final int scrollY = mScrollY; 20906 20907 invalidate(dirty.left + scrollX, dirty.top + scrollY, 20908 dirty.right + scrollX, dirty.bottom + scrollY); 20909 rebuildOutline(); 20910 } 20911 } 20912 20913 /** 20914 * Schedules an action on a drawable to occur at a specified time. 20915 * 20916 * @param who the recipient of the action 20917 * @param what the action to run on the drawable 20918 * @param when the time at which the action must occur. Uses the 20919 * {@link SystemClock#uptimeMillis} timebase. 20920 */ 20921 @Override scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)20922 public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { 20923 if (verifyDrawable(who) && what != null) { 20924 final long delay = when - SystemClock.uptimeMillis(); 20925 if (mAttachInfo != null) { 20926 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 20927 Choreographer.CALLBACK_ANIMATION, what, who, 20928 Choreographer.subtractFrameDelay(delay)); 20929 } else { 20930 // Postpone the runnable until we know 20931 // on which thread it needs to run. 20932 getRunQueue().postDelayed(what, delay); 20933 } 20934 } 20935 } 20936 20937 /** 20938 * Cancels a scheduled action on a drawable. 20939 * 20940 * @param who the recipient of the action 20941 * @param what the action to cancel 20942 */ 20943 @Override unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)20944 public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { 20945 if (verifyDrawable(who) && what != null) { 20946 if (mAttachInfo != null) { 20947 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 20948 Choreographer.CALLBACK_ANIMATION, what, who); 20949 } 20950 getRunQueue().removeCallbacks(what); 20951 } 20952 } 20953 20954 /** 20955 * Unschedule any events associated with the given Drawable. This can be 20956 * used when selecting a new Drawable into a view, so that the previous 20957 * one is completely unscheduled. 20958 * 20959 * @param who The Drawable to unschedule. 20960 * 20961 * @see #drawableStateChanged 20962 */ unscheduleDrawable(Drawable who)20963 public void unscheduleDrawable(Drawable who) { 20964 if (mAttachInfo != null && who != null) { 20965 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 20966 Choreographer.CALLBACK_ANIMATION, null, who); 20967 } 20968 } 20969 20970 /** 20971 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 20972 * that the View directionality can and will be resolved before its Drawables. 20973 * 20974 * Will call {@link View#onResolveDrawables} when resolution is done. 20975 * 20976 * @hide 20977 */ resolveDrawables()20978 protected void resolveDrawables() { 20979 // Drawables resolution may need to happen before resolving the layout direction (which is 20980 // done only during the measure() call). 20981 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 20982 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 20983 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 20984 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 20985 // direction to be resolved as its resolved value will be the same as its raw value. 20986 if (!isLayoutDirectionResolved() && 20987 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 20988 return; 20989 } 20990 20991 final int layoutDirection = isLayoutDirectionResolved() ? 20992 getLayoutDirection() : getRawLayoutDirection(); 20993 20994 if (mBackground != null) { 20995 mBackground.setLayoutDirection(layoutDirection); 20996 } 20997 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 20998 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); 20999 } 21000 if (mDefaultFocusHighlight != null) { 21001 mDefaultFocusHighlight.setLayoutDirection(layoutDirection); 21002 } 21003 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 21004 onResolveDrawables(layoutDirection); 21005 } 21006 areDrawablesResolved()21007 boolean areDrawablesResolved() { 21008 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 21009 } 21010 21011 /** 21012 * Called when layout direction has been resolved. 21013 * 21014 * The default implementation does nothing. 21015 * 21016 * @param layoutDirection The resolved layout direction. 21017 * 21018 * @see #LAYOUT_DIRECTION_LTR 21019 * @see #LAYOUT_DIRECTION_RTL 21020 * 21021 * @hide 21022 */ onResolveDrawables(@esolvedLayoutDir int layoutDirection)21023 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 21024 } 21025 21026 /** 21027 * @hide 21028 */ resetResolvedDrawables()21029 protected void resetResolvedDrawables() { 21030 resetResolvedDrawablesInternal(); 21031 } 21032 resetResolvedDrawablesInternal()21033 void resetResolvedDrawablesInternal() { 21034 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 21035 } 21036 21037 /** 21038 * If your view subclass is displaying its own Drawable objects, it should 21039 * override this function and return true for any Drawable it is 21040 * displaying. This allows animations for those drawables to be 21041 * scheduled. 21042 * 21043 * <p>Be sure to call through to the super class when overriding this 21044 * function. 21045 * 21046 * @param who The Drawable to verify. Return true if it is one you are 21047 * displaying, else return the result of calling through to the 21048 * super class. 21049 * 21050 * @return boolean If true than the Drawable is being displayed in the 21051 * view; else false and it is not allowed to animate. 21052 * 21053 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 21054 * @see #drawableStateChanged() 21055 */ 21056 @CallSuper verifyDrawable(@onNull Drawable who)21057 protected boolean verifyDrawable(@NonNull Drawable who) { 21058 // Avoid verifying the scroll bar drawable so that we don't end up in 21059 // an invalidation loop. This effectively prevents the scroll bar 21060 // drawable from triggering invalidations and scheduling runnables. 21061 return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who) 21062 || (mDefaultFocusHighlight == who); 21063 } 21064 21065 /** 21066 * This function is called whenever the state of the view changes in such 21067 * a way that it impacts the state of drawables being shown. 21068 * <p> 21069 * If the View has a StateListAnimator, it will also be called to run necessary state 21070 * change animations. 21071 * <p> 21072 * Be sure to call through to the superclass when overriding this function. 21073 * 21074 * @see Drawable#setState(int[]) 21075 */ 21076 @CallSuper drawableStateChanged()21077 protected void drawableStateChanged() { 21078 final int[] state = getDrawableState(); 21079 boolean changed = false; 21080 21081 final Drawable bg = mBackground; 21082 if (bg != null && bg.isStateful()) { 21083 changed |= bg.setState(state); 21084 } 21085 21086 final Drawable hl = mDefaultFocusHighlight; 21087 if (hl != null && hl.isStateful()) { 21088 changed |= hl.setState(state); 21089 } 21090 21091 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 21092 if (fg != null && fg.isStateful()) { 21093 changed |= fg.setState(state); 21094 } 21095 21096 if (mScrollCache != null) { 21097 final Drawable scrollBar = mScrollCache.scrollBar; 21098 if (scrollBar != null && scrollBar.isStateful()) { 21099 changed |= scrollBar.setState(state) 21100 && mScrollCache.state != ScrollabilityCache.OFF; 21101 } 21102 } 21103 21104 if (mStateListAnimator != null) { 21105 mStateListAnimator.setState(state); 21106 } 21107 21108 if (changed) { 21109 invalidate(); 21110 } 21111 } 21112 21113 /** 21114 * This function is called whenever the view hotspot changes and needs to 21115 * be propagated to drawables or child views managed by the view. 21116 * <p> 21117 * Dispatching to child views is handled by 21118 * {@link #dispatchDrawableHotspotChanged(float, float)}. 21119 * <p> 21120 * Be sure to call through to the superclass when overriding this function. 21121 * 21122 * @param x hotspot x coordinate 21123 * @param y hotspot y coordinate 21124 */ 21125 @CallSuper drawableHotspotChanged(float x, float y)21126 public void drawableHotspotChanged(float x, float y) { 21127 if (mBackground != null) { 21128 mBackground.setHotspot(x, y); 21129 } 21130 if (mDefaultFocusHighlight != null) { 21131 mDefaultFocusHighlight.setHotspot(x, y); 21132 } 21133 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 21134 mForegroundInfo.mDrawable.setHotspot(x, y); 21135 } 21136 21137 dispatchDrawableHotspotChanged(x, y); 21138 } 21139 21140 /** 21141 * Dispatches drawableHotspotChanged to all of this View's children. 21142 * 21143 * @param x hotspot x coordinate 21144 * @param y hotspot y coordinate 21145 * @see #drawableHotspotChanged(float, float) 21146 */ dispatchDrawableHotspotChanged(float x, float y)21147 public void dispatchDrawableHotspotChanged(float x, float y) { 21148 } 21149 21150 /** 21151 * Call this to force a view to update its drawable state. This will cause 21152 * drawableStateChanged to be called on this view. Views that are interested 21153 * in the new state should call getDrawableState. 21154 * 21155 * @see #drawableStateChanged 21156 * @see #getDrawableState 21157 */ refreshDrawableState()21158 public void refreshDrawableState() { 21159 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 21160 drawableStateChanged(); 21161 21162 ViewParent parent = mParent; 21163 if (parent != null) { 21164 parent.childDrawableStateChanged(this); 21165 } 21166 } 21167 21168 /** 21169 * Create a default focus highlight if it doesn't exist. 21170 * @return a default focus highlight. 21171 */ getDefaultFocusHighlightDrawable()21172 private Drawable getDefaultFocusHighlightDrawable() { 21173 if (mDefaultFocusHighlightCache == null) { 21174 if (mContext != null) { 21175 final int[] attrs = new int[] { android.R.attr.selectableItemBackground }; 21176 final TypedArray ta = mContext.obtainStyledAttributes(attrs); 21177 mDefaultFocusHighlightCache = ta.getDrawable(0); 21178 ta.recycle(); 21179 } 21180 } 21181 return mDefaultFocusHighlightCache; 21182 } 21183 21184 /** 21185 * Set the current default focus highlight. 21186 * @param highlight the highlight drawable, or {@code null} if it's no longer needed. 21187 */ setDefaultFocusHighlight(Drawable highlight)21188 private void setDefaultFocusHighlight(Drawable highlight) { 21189 mDefaultFocusHighlight = highlight; 21190 mDefaultFocusHighlightSizeChanged = true; 21191 if (highlight != null) { 21192 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 21193 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 21194 } 21195 highlight.setLayoutDirection(getLayoutDirection()); 21196 if (highlight.isStateful()) { 21197 highlight.setState(getDrawableState()); 21198 } 21199 if (isAttachedToWindow()) { 21200 highlight.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 21201 } 21202 // Set callback last, since the view may still be initializing. 21203 highlight.setCallback(this); 21204 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null 21205 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { 21206 mPrivateFlags |= PFLAG_SKIP_DRAW; 21207 } 21208 invalidate(); 21209 } 21210 21211 /** 21212 * Check whether we need to draw a default focus highlight when this view gets focused, 21213 * which requires: 21214 * <ul> 21215 * <li>In both background and foreground, {@link android.R.attr#state_focused} 21216 * is not defined.</li> 21217 * <li>This view is not in touch mode.</li> 21218 * <li>This view doesn't opt out for a default focus highlight, via 21219 * {@link #setDefaultFocusHighlightEnabled(boolean)}.</li> 21220 * <li>This view is attached to window.</li> 21221 * </ul> 21222 * @return {@code true} if a default focus highlight is needed. 21223 * @hide 21224 */ 21225 @TestApi isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground)21226 public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) { 21227 final boolean lackFocusState = (background == null || !background.isStateful() 21228 || !background.hasFocusStateSpecified()) 21229 && (foreground == null || !foreground.isStateful() 21230 || !foreground.hasFocusStateSpecified()); 21231 return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState 21232 && isAttachedToWindow() && sUseDefaultFocusHighlight; 21233 } 21234 21235 /** 21236 * When this view is focused, switches on/off the default focused highlight. 21237 * <p> 21238 * This always happens when this view is focused, and only at this moment the default focus 21239 * highlight can be visible. 21240 */ switchDefaultFocusHighlight()21241 private void switchDefaultFocusHighlight() { 21242 if (isFocused()) { 21243 final boolean needed = isDefaultFocusHighlightNeeded(mBackground, 21244 mForegroundInfo == null ? null : mForegroundInfo.mDrawable); 21245 final boolean active = mDefaultFocusHighlight != null; 21246 if (needed && !active) { 21247 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable()); 21248 } else if (!needed && active) { 21249 // The highlight is no longer needed, so tear it down. 21250 setDefaultFocusHighlight(null); 21251 } 21252 } 21253 } 21254 21255 /** 21256 * Draw the default focus highlight onto the canvas. 21257 * @param canvas the canvas where we're drawing the highlight. 21258 */ drawDefaultFocusHighlight(Canvas canvas)21259 private void drawDefaultFocusHighlight(Canvas canvas) { 21260 if (mDefaultFocusHighlight != null) { 21261 if (mDefaultFocusHighlightSizeChanged) { 21262 mDefaultFocusHighlightSizeChanged = false; 21263 final int l = mScrollX; 21264 final int r = l + mRight - mLeft; 21265 final int t = mScrollY; 21266 final int b = t + mBottom - mTop; 21267 mDefaultFocusHighlight.setBounds(l, t, r, b); 21268 } 21269 mDefaultFocusHighlight.draw(canvas); 21270 } 21271 } 21272 21273 /** 21274 * Return an array of resource IDs of the drawable states representing the 21275 * current state of the view. 21276 * 21277 * @return The current drawable state 21278 * 21279 * @see Drawable#setState(int[]) 21280 * @see #drawableStateChanged() 21281 * @see #onCreateDrawableState(int) 21282 */ getDrawableState()21283 public final int[] getDrawableState() { 21284 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 21285 return mDrawableState; 21286 } else { 21287 mDrawableState = onCreateDrawableState(0); 21288 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 21289 return mDrawableState; 21290 } 21291 } 21292 21293 /** 21294 * Generate the new {@link android.graphics.drawable.Drawable} state for 21295 * this view. This is called by the view 21296 * system when the cached Drawable state is determined to be invalid. To 21297 * retrieve the current state, you should use {@link #getDrawableState}. 21298 * 21299 * @param extraSpace if non-zero, this is the number of extra entries you 21300 * would like in the returned array in which you can place your own 21301 * states. 21302 * 21303 * @return Returns an array holding the current {@link Drawable} state of 21304 * the view. 21305 * 21306 * @see #mergeDrawableStates(int[], int[]) 21307 */ onCreateDrawableState(int extraSpace)21308 protected int[] onCreateDrawableState(int extraSpace) { 21309 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 21310 mParent instanceof View) { 21311 return ((View) mParent).onCreateDrawableState(extraSpace); 21312 } 21313 21314 int[] drawableState; 21315 21316 int privateFlags = mPrivateFlags; 21317 21318 int viewStateIndex = 0; 21319 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED; 21320 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED; 21321 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED; 21322 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED; 21323 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED; 21324 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED; 21325 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 21326 ThreadedRenderer.isAvailable()) { 21327 // This is set if HW acceleration is requested, even if the current 21328 // process doesn't allow it. This is just to allow app preview 21329 // windows to better match their app. 21330 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED; 21331 } 21332 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED; 21333 21334 final int privateFlags2 = mPrivateFlags2; 21335 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) { 21336 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT; 21337 } 21338 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) { 21339 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED; 21340 } 21341 21342 drawableState = StateSet.get(viewStateIndex); 21343 21344 //noinspection ConstantIfStatement 21345 if (false) { 21346 Log.i("View", "drawableStateIndex=" + viewStateIndex); 21347 Log.i("View", toString() 21348 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 21349 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 21350 + " fo=" + hasFocus() 21351 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 21352 + " wf=" + hasWindowFocus() 21353 + ": " + Arrays.toString(drawableState)); 21354 } 21355 21356 if (extraSpace == 0) { 21357 return drawableState; 21358 } 21359 21360 final int[] fullState; 21361 if (drawableState != null) { 21362 fullState = new int[drawableState.length + extraSpace]; 21363 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 21364 } else { 21365 fullState = new int[extraSpace]; 21366 } 21367 21368 return fullState; 21369 } 21370 21371 /** 21372 * Merge your own state values in <var>additionalState</var> into the base 21373 * state values <var>baseState</var> that were returned by 21374 * {@link #onCreateDrawableState(int)}. 21375 * 21376 * @param baseState The base state values returned by 21377 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 21378 * own additional state values. 21379 * 21380 * @param additionalState The additional state values you would like 21381 * added to <var>baseState</var>; this array is not modified. 21382 * 21383 * @return As a convenience, the <var>baseState</var> array you originally 21384 * passed into the function is returned. 21385 * 21386 * @see #onCreateDrawableState(int) 21387 */ mergeDrawableStates(int[] baseState, int[] additionalState)21388 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 21389 final int N = baseState.length; 21390 int i = N - 1; 21391 while (i >= 0 && baseState[i] == 0) { 21392 i--; 21393 } 21394 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 21395 return baseState; 21396 } 21397 21398 /** 21399 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 21400 * on all Drawable objects associated with this view. 21401 * <p> 21402 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator 21403 * attached to this view. 21404 */ 21405 @CallSuper jumpDrawablesToCurrentState()21406 public void jumpDrawablesToCurrentState() { 21407 if (mBackground != null) { 21408 mBackground.jumpToCurrentState(); 21409 } 21410 if (mStateListAnimator != null) { 21411 mStateListAnimator.jumpToCurrentState(); 21412 } 21413 if (mDefaultFocusHighlight != null) { 21414 mDefaultFocusHighlight.jumpToCurrentState(); 21415 } 21416 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 21417 mForegroundInfo.mDrawable.jumpToCurrentState(); 21418 } 21419 } 21420 21421 /** 21422 * Sets the background color for this view. 21423 * @param color the color of the background 21424 */ 21425 @RemotableViewMethod setBackgroundColor(@olorInt int color)21426 public void setBackgroundColor(@ColorInt int color) { 21427 if (mBackground instanceof ColorDrawable) { 21428 ((ColorDrawable) mBackground.mutate()).setColor(color); 21429 computeOpaqueFlags(); 21430 mBackgroundResource = 0; 21431 } else { 21432 setBackground(new ColorDrawable(color)); 21433 } 21434 } 21435 21436 /** 21437 * Set the background to a given resource. The resource should refer to 21438 * a Drawable object or 0 to remove the background. 21439 * @param resid The identifier of the resource. 21440 * 21441 * @attr ref android.R.styleable#View_background 21442 */ 21443 @RemotableViewMethod setBackgroundResource(@rawableRes int resid)21444 public void setBackgroundResource(@DrawableRes int resid) { 21445 if (resid != 0 && resid == mBackgroundResource) { 21446 return; 21447 } 21448 21449 Drawable d = null; 21450 if (resid != 0) { 21451 d = mContext.getDrawable(resid); 21452 } 21453 setBackground(d); 21454 21455 mBackgroundResource = resid; 21456 } 21457 21458 /** 21459 * Set the background to a given Drawable, or remove the background. If the 21460 * background has padding, this View's padding is set to the background's 21461 * padding. However, when a background is removed, this View's padding isn't 21462 * touched. If setting the padding is desired, please use 21463 * {@link #setPadding(int, int, int, int)}. 21464 * 21465 * @param background The Drawable to use as the background, or null to remove the 21466 * background 21467 */ setBackground(Drawable background)21468 public void setBackground(Drawable background) { 21469 //noinspection deprecation 21470 setBackgroundDrawable(background); 21471 } 21472 21473 /** 21474 * @deprecated use {@link #setBackground(Drawable)} instead 21475 */ 21476 @Deprecated setBackgroundDrawable(Drawable background)21477 public void setBackgroundDrawable(Drawable background) { 21478 computeOpaqueFlags(); 21479 21480 if (background == mBackground) { 21481 return; 21482 } 21483 21484 boolean requestLayout = false; 21485 21486 mBackgroundResource = 0; 21487 21488 /* 21489 * Regardless of whether we're setting a new background or not, we want 21490 * to clear the previous drawable. setVisible first while we still have the callback set. 21491 */ 21492 if (mBackground != null) { 21493 if (isAttachedToWindow()) { 21494 mBackground.setVisible(false, false); 21495 } 21496 mBackground.setCallback(null); 21497 unscheduleDrawable(mBackground); 21498 } 21499 21500 if (background != null) { 21501 Rect padding = sThreadLocal.get(); 21502 if (padding == null) { 21503 padding = new Rect(); 21504 sThreadLocal.set(padding); 21505 } 21506 resetResolvedDrawablesInternal(); 21507 background.setLayoutDirection(getLayoutDirection()); 21508 if (background.getPadding(padding)) { 21509 resetResolvedPaddingInternal(); 21510 switch (background.getLayoutDirection()) { 21511 case LAYOUT_DIRECTION_RTL: 21512 mUserPaddingLeftInitial = padding.right; 21513 mUserPaddingRightInitial = padding.left; 21514 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 21515 break; 21516 case LAYOUT_DIRECTION_LTR: 21517 default: 21518 mUserPaddingLeftInitial = padding.left; 21519 mUserPaddingRightInitial = padding.right; 21520 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 21521 } 21522 mLeftPaddingDefined = false; 21523 mRightPaddingDefined = false; 21524 } 21525 21526 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 21527 // if it has a different minimum size, we should layout again 21528 if (mBackground == null 21529 || mBackground.getMinimumHeight() != background.getMinimumHeight() 21530 || mBackground.getMinimumWidth() != background.getMinimumWidth()) { 21531 requestLayout = true; 21532 } 21533 21534 // Set mBackground before we set this as the callback and start making other 21535 // background drawable state change calls. In particular, the setVisible call below 21536 // can result in drawables attempting to start animations or otherwise invalidate, 21537 // which requires the view set as the callback (us) to recognize the drawable as 21538 // belonging to it as per verifyDrawable. 21539 mBackground = background; 21540 if (background.isStateful()) { 21541 background.setState(getDrawableState()); 21542 } 21543 if (isAttachedToWindow()) { 21544 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 21545 } 21546 21547 applyBackgroundTint(); 21548 21549 // Set callback last, since the view may still be initializing. 21550 background.setCallback(this); 21551 21552 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 21553 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 21554 requestLayout = true; 21555 } 21556 } else { 21557 /* Remove the background */ 21558 mBackground = null; 21559 if ((mViewFlags & WILL_NOT_DRAW) != 0 21560 && (mDefaultFocusHighlight == null) 21561 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { 21562 mPrivateFlags |= PFLAG_SKIP_DRAW; 21563 } 21564 21565 /* 21566 * When the background is set, we try to apply its padding to this 21567 * View. When the background is removed, we don't touch this View's 21568 * padding. This is noted in the Javadocs. Hence, we don't need to 21569 * requestLayout(), the invalidate() below is sufficient. 21570 */ 21571 21572 // The old background's minimum size could have affected this 21573 // View's layout, so let's requestLayout 21574 requestLayout = true; 21575 } 21576 21577 computeOpaqueFlags(); 21578 21579 if (requestLayout) { 21580 requestLayout(); 21581 } 21582 21583 mBackgroundSizeChanged = true; 21584 invalidate(true); 21585 invalidateOutline(); 21586 } 21587 21588 /** 21589 * Gets the background drawable 21590 * 21591 * @return The drawable used as the background for this view, if any. 21592 * 21593 * @see #setBackground(Drawable) 21594 * 21595 * @attr ref android.R.styleable#View_background 21596 */ getBackground()21597 public Drawable getBackground() { 21598 return mBackground; 21599 } 21600 21601 /** 21602 * Applies a tint to the background drawable. Does not modify the current tint 21603 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 21604 * <p> 21605 * Subsequent calls to {@link #setBackground(Drawable)} will automatically 21606 * mutate the drawable and apply the specified tint and tint mode using 21607 * {@link Drawable#setTintList(ColorStateList)}. 21608 * 21609 * @param tint the tint to apply, may be {@code null} to clear tint 21610 * 21611 * @attr ref android.R.styleable#View_backgroundTint 21612 * @see #getBackgroundTintList() 21613 * @see Drawable#setTintList(ColorStateList) 21614 */ setBackgroundTintList(@ullable ColorStateList tint)21615 public void setBackgroundTintList(@Nullable ColorStateList tint) { 21616 if (mBackgroundTint == null) { 21617 mBackgroundTint = new TintInfo(); 21618 } 21619 mBackgroundTint.mTintList = tint; 21620 mBackgroundTint.mHasTintList = true; 21621 21622 applyBackgroundTint(); 21623 } 21624 21625 /** 21626 * Return the tint applied to the background drawable, if specified. 21627 * 21628 * @return the tint applied to the background drawable 21629 * @attr ref android.R.styleable#View_backgroundTint 21630 * @see #setBackgroundTintList(ColorStateList) 21631 */ 21632 @Nullable getBackgroundTintList()21633 public ColorStateList getBackgroundTintList() { 21634 return mBackgroundTint != null ? mBackgroundTint.mTintList : null; 21635 } 21636 21637 /** 21638 * Specifies the blending mode used to apply the tint specified by 21639 * {@link #setBackgroundTintList(ColorStateList)}} to the background 21640 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 21641 * 21642 * @param tintMode the blending mode used to apply the tint, may be 21643 * {@code null} to clear tint 21644 * @attr ref android.R.styleable#View_backgroundTintMode 21645 * @see #getBackgroundTintMode() 21646 * @see Drawable#setTintMode(PorterDuff.Mode) 21647 */ setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)21648 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { 21649 if (mBackgroundTint == null) { 21650 mBackgroundTint = new TintInfo(); 21651 } 21652 mBackgroundTint.mTintMode = tintMode; 21653 mBackgroundTint.mHasTintMode = true; 21654 21655 applyBackgroundTint(); 21656 } 21657 21658 /** 21659 * Return the blending mode used to apply the tint to the background 21660 * drawable, if specified. 21661 * 21662 * @return the blending mode used to apply the tint to the background 21663 * drawable 21664 * @attr ref android.R.styleable#View_backgroundTintMode 21665 * @see #setBackgroundTintMode(PorterDuff.Mode) 21666 */ 21667 @Nullable getBackgroundTintMode()21668 public PorterDuff.Mode getBackgroundTintMode() { 21669 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; 21670 } 21671 applyBackgroundTint()21672 private void applyBackgroundTint() { 21673 if (mBackground != null && mBackgroundTint != null) { 21674 final TintInfo tintInfo = mBackgroundTint; 21675 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 21676 mBackground = mBackground.mutate(); 21677 21678 if (tintInfo.mHasTintList) { 21679 mBackground.setTintList(tintInfo.mTintList); 21680 } 21681 21682 if (tintInfo.mHasTintMode) { 21683 mBackground.setTintMode(tintInfo.mTintMode); 21684 } 21685 21686 // The drawable (or one of its children) may not have been 21687 // stateful before applying the tint, so let's try again. 21688 if (mBackground.isStateful()) { 21689 mBackground.setState(getDrawableState()); 21690 } 21691 } 21692 } 21693 } 21694 21695 /** 21696 * Returns the drawable used as the foreground of this View. The 21697 * foreground drawable, if non-null, is always drawn on top of the view's content. 21698 * 21699 * @return a Drawable or null if no foreground was set 21700 * 21701 * @see #onDrawForeground(Canvas) 21702 */ getForeground()21703 public Drawable getForeground() { 21704 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 21705 } 21706 21707 /** 21708 * Supply a Drawable that is to be rendered on top of all of the content in the view. 21709 * 21710 * @param foreground the Drawable to be drawn on top of the children 21711 * 21712 * @attr ref android.R.styleable#View_foreground 21713 */ setForeground(Drawable foreground)21714 public void setForeground(Drawable foreground) { 21715 if (mForegroundInfo == null) { 21716 if (foreground == null) { 21717 // Nothing to do. 21718 return; 21719 } 21720 mForegroundInfo = new ForegroundInfo(); 21721 } 21722 21723 if (foreground == mForegroundInfo.mDrawable) { 21724 // Nothing to do 21725 return; 21726 } 21727 21728 if (mForegroundInfo.mDrawable != null) { 21729 if (isAttachedToWindow()) { 21730 mForegroundInfo.mDrawable.setVisible(false, false); 21731 } 21732 mForegroundInfo.mDrawable.setCallback(null); 21733 unscheduleDrawable(mForegroundInfo.mDrawable); 21734 } 21735 21736 mForegroundInfo.mDrawable = foreground; 21737 mForegroundInfo.mBoundsChanged = true; 21738 if (foreground != null) { 21739 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 21740 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 21741 } 21742 foreground.setLayoutDirection(getLayoutDirection()); 21743 if (foreground.isStateful()) { 21744 foreground.setState(getDrawableState()); 21745 } 21746 applyForegroundTint(); 21747 if (isAttachedToWindow()) { 21748 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 21749 } 21750 // Set callback last, since the view may still be initializing. 21751 foreground.setCallback(this); 21752 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null 21753 && (mDefaultFocusHighlight == null)) { 21754 mPrivateFlags |= PFLAG_SKIP_DRAW; 21755 } 21756 requestLayout(); 21757 invalidate(); 21758 } 21759 21760 /** 21761 * Magic bit used to support features of framework-internal window decor implementation details. 21762 * This used to live exclusively in FrameLayout. 21763 * 21764 * @return true if the foreground should draw inside the padding region or false 21765 * if it should draw inset by the view's padding 21766 * @hide internal use only; only used by FrameLayout and internal screen layouts. 21767 */ isForegroundInsidePadding()21768 public boolean isForegroundInsidePadding() { 21769 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true; 21770 } 21771 21772 /** 21773 * Describes how the foreground is positioned. 21774 * 21775 * @return foreground gravity. 21776 * 21777 * @see #setForegroundGravity(int) 21778 * 21779 * @attr ref android.R.styleable#View_foregroundGravity 21780 */ getForegroundGravity()21781 public int getForegroundGravity() { 21782 return mForegroundInfo != null ? mForegroundInfo.mGravity 21783 : Gravity.START | Gravity.TOP; 21784 } 21785 21786 /** 21787 * Describes how the foreground is positioned. Defaults to START and TOP. 21788 * 21789 * @param gravity see {@link android.view.Gravity} 21790 * 21791 * @see #getForegroundGravity() 21792 * 21793 * @attr ref android.R.styleable#View_foregroundGravity 21794 */ setForegroundGravity(int gravity)21795 public void setForegroundGravity(int gravity) { 21796 if (mForegroundInfo == null) { 21797 mForegroundInfo = new ForegroundInfo(); 21798 } 21799 21800 if (mForegroundInfo.mGravity != gravity) { 21801 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { 21802 gravity |= Gravity.START; 21803 } 21804 21805 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { 21806 gravity |= Gravity.TOP; 21807 } 21808 21809 mForegroundInfo.mGravity = gravity; 21810 requestLayout(); 21811 } 21812 } 21813 21814 /** 21815 * Applies a tint to the foreground drawable. Does not modify the current tint 21816 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 21817 * <p> 21818 * Subsequent calls to {@link #setForeground(Drawable)} will automatically 21819 * mutate the drawable and apply the specified tint and tint mode using 21820 * {@link Drawable#setTintList(ColorStateList)}. 21821 * 21822 * @param tint the tint to apply, may be {@code null} to clear tint 21823 * 21824 * @attr ref android.R.styleable#View_foregroundTint 21825 * @see #getForegroundTintList() 21826 * @see Drawable#setTintList(ColorStateList) 21827 */ setForegroundTintList(@ullable ColorStateList tint)21828 public void setForegroundTintList(@Nullable ColorStateList tint) { 21829 if (mForegroundInfo == null) { 21830 mForegroundInfo = new ForegroundInfo(); 21831 } 21832 if (mForegroundInfo.mTintInfo == null) { 21833 mForegroundInfo.mTintInfo = new TintInfo(); 21834 } 21835 mForegroundInfo.mTintInfo.mTintList = tint; 21836 mForegroundInfo.mTintInfo.mHasTintList = true; 21837 21838 applyForegroundTint(); 21839 } 21840 21841 /** 21842 * Return the tint applied to the foreground drawable, if specified. 21843 * 21844 * @return the tint applied to the foreground drawable 21845 * @attr ref android.R.styleable#View_foregroundTint 21846 * @see #setForegroundTintList(ColorStateList) 21847 */ 21848 @Nullable getForegroundTintList()21849 public ColorStateList getForegroundTintList() { 21850 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 21851 ? mForegroundInfo.mTintInfo.mTintList : null; 21852 } 21853 21854 /** 21855 * Specifies the blending mode used to apply the tint specified by 21856 * {@link #setForegroundTintList(ColorStateList)}} to the background 21857 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 21858 * 21859 * @param tintMode the blending mode used to apply the tint, may be 21860 * {@code null} to clear tint 21861 * @attr ref android.R.styleable#View_foregroundTintMode 21862 * @see #getForegroundTintMode() 21863 * @see Drawable#setTintMode(PorterDuff.Mode) 21864 */ setForegroundTintMode(@ullable PorterDuff.Mode tintMode)21865 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { 21866 if (mForegroundInfo == null) { 21867 mForegroundInfo = new ForegroundInfo(); 21868 } 21869 if (mForegroundInfo.mTintInfo == null) { 21870 mForegroundInfo.mTintInfo = new TintInfo(); 21871 } 21872 mForegroundInfo.mTintInfo.mTintMode = tintMode; 21873 mForegroundInfo.mTintInfo.mHasTintMode = true; 21874 21875 applyForegroundTint(); 21876 } 21877 21878 /** 21879 * Return the blending mode used to apply the tint to the foreground 21880 * drawable, if specified. 21881 * 21882 * @return the blending mode used to apply the tint to the foreground 21883 * drawable 21884 * @attr ref android.R.styleable#View_foregroundTintMode 21885 * @see #setForegroundTintMode(PorterDuff.Mode) 21886 */ 21887 @Nullable getForegroundTintMode()21888 public PorterDuff.Mode getForegroundTintMode() { 21889 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 21890 ? mForegroundInfo.mTintInfo.mTintMode : null; 21891 } 21892 applyForegroundTint()21893 private void applyForegroundTint() { 21894 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 21895 && mForegroundInfo.mTintInfo != null) { 21896 final TintInfo tintInfo = mForegroundInfo.mTintInfo; 21897 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 21898 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); 21899 21900 if (tintInfo.mHasTintList) { 21901 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); 21902 } 21903 21904 if (tintInfo.mHasTintMode) { 21905 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); 21906 } 21907 21908 // The drawable (or one of its children) may not have been 21909 // stateful before applying the tint, so let's try again. 21910 if (mForegroundInfo.mDrawable.isStateful()) { 21911 mForegroundInfo.mDrawable.setState(getDrawableState()); 21912 } 21913 } 21914 } 21915 } 21916 21917 /** 21918 * Get the drawable to be overlayed when a view is autofilled 21919 * 21920 * @return The drawable 21921 * 21922 * @throws IllegalStateException if the drawable could not be found. 21923 */ getAutofilledDrawable()21924 @Nullable private Drawable getAutofilledDrawable() { 21925 if (mAttachInfo == null) { 21926 return null; 21927 } 21928 // Lazily load the isAutofilled drawable. 21929 if (mAttachInfo.mAutofilledDrawable == null) { 21930 Context rootContext = getRootView().getContext(); 21931 TypedArray a = rootContext.getTheme().obtainStyledAttributes(AUTOFILL_HIGHLIGHT_ATTR); 21932 int attributeResourceId = a.getResourceId(0, 0); 21933 mAttachInfo.mAutofilledDrawable = rootContext.getDrawable(attributeResourceId); 21934 a.recycle(); 21935 } 21936 21937 return mAttachInfo.mAutofilledDrawable; 21938 } 21939 21940 /** 21941 * Draw {@link View#isAutofilled()} highlight over view if the view is autofilled. 21942 * 21943 * @param canvas The canvas to draw on 21944 */ drawAutofilledHighlight(@onNull Canvas canvas)21945 private void drawAutofilledHighlight(@NonNull Canvas canvas) { 21946 if (isAutofilled()) { 21947 Drawable autofilledHighlight = getAutofilledDrawable(); 21948 21949 if (autofilledHighlight != null) { 21950 autofilledHighlight.setBounds(0, 0, getWidth(), getHeight()); 21951 autofilledHighlight.draw(canvas); 21952 } 21953 } 21954 } 21955 21956 /** 21957 * Draw any foreground content for this view. 21958 * 21959 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground} 21960 * drawable or other view-specific decorations. The foreground is drawn on top of the 21961 * primary view content.</p> 21962 * 21963 * @param canvas canvas to draw into 21964 */ onDrawForeground(Canvas canvas)21965 public void onDrawForeground(Canvas canvas) { 21966 onDrawScrollIndicators(canvas); 21967 onDrawScrollBars(canvas); 21968 21969 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 21970 if (foreground != null) { 21971 if (mForegroundInfo.mBoundsChanged) { 21972 mForegroundInfo.mBoundsChanged = false; 21973 final Rect selfBounds = mForegroundInfo.mSelfBounds; 21974 final Rect overlayBounds = mForegroundInfo.mOverlayBounds; 21975 21976 if (mForegroundInfo.mInsidePadding) { 21977 selfBounds.set(0, 0, getWidth(), getHeight()); 21978 } else { 21979 selfBounds.set(getPaddingLeft(), getPaddingTop(), 21980 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); 21981 } 21982 21983 final int ld = getLayoutDirection(); 21984 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), 21985 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); 21986 foreground.setBounds(overlayBounds); 21987 } 21988 21989 foreground.draw(canvas); 21990 } 21991 } 21992 21993 /** 21994 * Sets the padding. The view may add on the space required to display 21995 * the scrollbars, depending on the style and visibility of the scrollbars. 21996 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 21997 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 21998 * from the values set in this call. 21999 * 22000 * @attr ref android.R.styleable#View_padding 22001 * @attr ref android.R.styleable#View_paddingBottom 22002 * @attr ref android.R.styleable#View_paddingLeft 22003 * @attr ref android.R.styleable#View_paddingRight 22004 * @attr ref android.R.styleable#View_paddingTop 22005 * @param left the left padding in pixels 22006 * @param top the top padding in pixels 22007 * @param right the right padding in pixels 22008 * @param bottom the bottom padding in pixels 22009 */ setPadding(int left, int top, int right, int bottom)22010 public void setPadding(int left, int top, int right, int bottom) { 22011 resetResolvedPaddingInternal(); 22012 22013 mUserPaddingStart = UNDEFINED_PADDING; 22014 mUserPaddingEnd = UNDEFINED_PADDING; 22015 22016 mUserPaddingLeftInitial = left; 22017 mUserPaddingRightInitial = right; 22018 22019 mLeftPaddingDefined = true; 22020 mRightPaddingDefined = true; 22021 22022 internalSetPadding(left, top, right, bottom); 22023 } 22024 22025 /** 22026 * @hide 22027 */ internalSetPadding(int left, int top, int right, int bottom)22028 protected void internalSetPadding(int left, int top, int right, int bottom) { 22029 mUserPaddingLeft = left; 22030 mUserPaddingRight = right; 22031 mUserPaddingBottom = bottom; 22032 22033 final int viewFlags = mViewFlags; 22034 boolean changed = false; 22035 22036 // Common case is there are no scroll bars. 22037 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 22038 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 22039 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 22040 ? 0 : getVerticalScrollbarWidth(); 22041 switch (mVerticalScrollbarPosition) { 22042 case SCROLLBAR_POSITION_DEFAULT: 22043 if (isLayoutRtl()) { 22044 left += offset; 22045 } else { 22046 right += offset; 22047 } 22048 break; 22049 case SCROLLBAR_POSITION_RIGHT: 22050 right += offset; 22051 break; 22052 case SCROLLBAR_POSITION_LEFT: 22053 left += offset; 22054 break; 22055 } 22056 } 22057 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 22058 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 22059 ? 0 : getHorizontalScrollbarHeight(); 22060 } 22061 } 22062 22063 if (mPaddingLeft != left) { 22064 changed = true; 22065 mPaddingLeft = left; 22066 } 22067 if (mPaddingTop != top) { 22068 changed = true; 22069 mPaddingTop = top; 22070 } 22071 if (mPaddingRight != right) { 22072 changed = true; 22073 mPaddingRight = right; 22074 } 22075 if (mPaddingBottom != bottom) { 22076 changed = true; 22077 mPaddingBottom = bottom; 22078 } 22079 22080 if (changed) { 22081 requestLayout(); 22082 invalidateOutline(); 22083 } 22084 } 22085 22086 /** 22087 * Sets the relative padding. The view may add on the space required to display 22088 * the scrollbars, depending on the style and visibility of the scrollbars. 22089 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 22090 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 22091 * from the values set in this call. 22092 * 22093 * @attr ref android.R.styleable#View_padding 22094 * @attr ref android.R.styleable#View_paddingBottom 22095 * @attr ref android.R.styleable#View_paddingStart 22096 * @attr ref android.R.styleable#View_paddingEnd 22097 * @attr ref android.R.styleable#View_paddingTop 22098 * @param start the start padding in pixels 22099 * @param top the top padding in pixels 22100 * @param end the end padding in pixels 22101 * @param bottom the bottom padding in pixels 22102 */ setPaddingRelative(int start, int top, int end, int bottom)22103 public void setPaddingRelative(int start, int top, int end, int bottom) { 22104 resetResolvedPaddingInternal(); 22105 22106 mUserPaddingStart = start; 22107 mUserPaddingEnd = end; 22108 mLeftPaddingDefined = true; 22109 mRightPaddingDefined = true; 22110 22111 switch(getLayoutDirection()) { 22112 case LAYOUT_DIRECTION_RTL: 22113 mUserPaddingLeftInitial = end; 22114 mUserPaddingRightInitial = start; 22115 internalSetPadding(end, top, start, bottom); 22116 break; 22117 case LAYOUT_DIRECTION_LTR: 22118 default: 22119 mUserPaddingLeftInitial = start; 22120 mUserPaddingRightInitial = end; 22121 internalSetPadding(start, top, end, bottom); 22122 } 22123 } 22124 22125 /** 22126 * Returns the top padding of this view. 22127 * 22128 * @return the top padding in pixels 22129 */ getPaddingTop()22130 public int getPaddingTop() { 22131 return mPaddingTop; 22132 } 22133 22134 /** 22135 * Returns the bottom padding of this view. If there are inset and enabled 22136 * scrollbars, this value may include the space required to display the 22137 * scrollbars as well. 22138 * 22139 * @return the bottom padding in pixels 22140 */ getPaddingBottom()22141 public int getPaddingBottom() { 22142 return mPaddingBottom; 22143 } 22144 22145 /** 22146 * Returns the left padding of this view. If there are inset and enabled 22147 * scrollbars, this value may include the space required to display the 22148 * scrollbars as well. 22149 * 22150 * @return the left padding in pixels 22151 */ getPaddingLeft()22152 public int getPaddingLeft() { 22153 if (!isPaddingResolved()) { 22154 resolvePadding(); 22155 } 22156 return mPaddingLeft; 22157 } 22158 22159 /** 22160 * Returns the start padding of this view depending on its resolved layout direction. 22161 * If there are inset and enabled scrollbars, this value may include the space 22162 * required to display the scrollbars as well. 22163 * 22164 * @return the start padding in pixels 22165 */ getPaddingStart()22166 public int getPaddingStart() { 22167 if (!isPaddingResolved()) { 22168 resolvePadding(); 22169 } 22170 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 22171 mPaddingRight : mPaddingLeft; 22172 } 22173 22174 /** 22175 * Returns the right padding of this view. If there are inset and enabled 22176 * scrollbars, this value may include the space required to display the 22177 * scrollbars as well. 22178 * 22179 * @return the right padding in pixels 22180 */ getPaddingRight()22181 public int getPaddingRight() { 22182 if (!isPaddingResolved()) { 22183 resolvePadding(); 22184 } 22185 return mPaddingRight; 22186 } 22187 22188 /** 22189 * Returns the end padding of this view depending on its resolved layout direction. 22190 * If there are inset and enabled scrollbars, this value may include the space 22191 * required to display the scrollbars as well. 22192 * 22193 * @return the end padding in pixels 22194 */ getPaddingEnd()22195 public int getPaddingEnd() { 22196 if (!isPaddingResolved()) { 22197 resolvePadding(); 22198 } 22199 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 22200 mPaddingLeft : mPaddingRight; 22201 } 22202 22203 /** 22204 * Return if the padding has been set through relative values 22205 * {@link #setPaddingRelative(int, int, int, int)} or through 22206 * @attr ref android.R.styleable#View_paddingStart or 22207 * @attr ref android.R.styleable#View_paddingEnd 22208 * 22209 * @return true if the padding is relative or false if it is not. 22210 */ isPaddingRelative()22211 public boolean isPaddingRelative() { 22212 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 22213 } 22214 computeOpticalInsets()22215 Insets computeOpticalInsets() { 22216 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 22217 } 22218 22219 /** 22220 * @hide 22221 */ resetPaddingToInitialValues()22222 public void resetPaddingToInitialValues() { 22223 if (isRtlCompatibilityMode()) { 22224 mPaddingLeft = mUserPaddingLeftInitial; 22225 mPaddingRight = mUserPaddingRightInitial; 22226 return; 22227 } 22228 if (isLayoutRtl()) { 22229 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 22230 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 22231 } else { 22232 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 22233 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 22234 } 22235 } 22236 22237 /** 22238 * @hide 22239 */ getOpticalInsets()22240 public Insets getOpticalInsets() { 22241 if (mLayoutInsets == null) { 22242 mLayoutInsets = computeOpticalInsets(); 22243 } 22244 return mLayoutInsets; 22245 } 22246 22247 /** 22248 * Set this view's optical insets. 22249 * 22250 * <p>This method should be treated similarly to setMeasuredDimension and not as a general 22251 * property. Views that compute their own optical insets should call it as part of measurement. 22252 * This method does not request layout. If you are setting optical insets outside of 22253 * measure/layout itself you will want to call requestLayout() yourself. 22254 * </p> 22255 * @hide 22256 */ setOpticalInsets(Insets insets)22257 public void setOpticalInsets(Insets insets) { 22258 mLayoutInsets = insets; 22259 } 22260 22261 /** 22262 * Changes the selection state of this view. A view can be selected or not. 22263 * Note that selection is not the same as focus. Views are typically 22264 * selected in the context of an AdapterView like ListView or GridView; 22265 * the selected view is the view that is highlighted. 22266 * 22267 * @param selected true if the view must be selected, false otherwise 22268 */ setSelected(boolean selected)22269 public void setSelected(boolean selected) { 22270 //noinspection DoubleNegation 22271 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 22272 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 22273 if (!selected) resetPressedState(); 22274 invalidate(true); 22275 refreshDrawableState(); 22276 dispatchSetSelected(selected); 22277 if (selected) { 22278 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 22279 } else { 22280 notifyViewAccessibilityStateChangedIfNeeded( 22281 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 22282 } 22283 } 22284 } 22285 22286 /** 22287 * Dispatch setSelected to all of this View's children. 22288 * 22289 * @see #setSelected(boolean) 22290 * 22291 * @param selected The new selected state 22292 */ dispatchSetSelected(boolean selected)22293 protected void dispatchSetSelected(boolean selected) { 22294 } 22295 22296 /** 22297 * Indicates the selection state of this view. 22298 * 22299 * @return true if the view is selected, false otherwise 22300 */ 22301 @ViewDebug.ExportedProperty isSelected()22302 public boolean isSelected() { 22303 return (mPrivateFlags & PFLAG_SELECTED) != 0; 22304 } 22305 22306 /** 22307 * Changes the activated state of this view. A view can be activated or not. 22308 * Note that activation is not the same as selection. Selection is 22309 * a transient property, representing the view (hierarchy) the user is 22310 * currently interacting with. Activation is a longer-term state that the 22311 * user can move views in and out of. For example, in a list view with 22312 * single or multiple selection enabled, the views in the current selection 22313 * set are activated. (Um, yeah, we are deeply sorry about the terminology 22314 * here.) The activated state is propagated down to children of the view it 22315 * is set on. 22316 * 22317 * @param activated true if the view must be activated, false otherwise 22318 */ setActivated(boolean activated)22319 public void setActivated(boolean activated) { 22320 //noinspection DoubleNegation 22321 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 22322 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 22323 invalidate(true); 22324 refreshDrawableState(); 22325 dispatchSetActivated(activated); 22326 } 22327 } 22328 22329 /** 22330 * Dispatch setActivated to all of this View's children. 22331 * 22332 * @see #setActivated(boolean) 22333 * 22334 * @param activated The new activated state 22335 */ dispatchSetActivated(boolean activated)22336 protected void dispatchSetActivated(boolean activated) { 22337 } 22338 22339 /** 22340 * Indicates the activation state of this view. 22341 * 22342 * @return true if the view is activated, false otherwise 22343 */ 22344 @ViewDebug.ExportedProperty isActivated()22345 public boolean isActivated() { 22346 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 22347 } 22348 22349 /** 22350 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 22351 * observer can be used to get notifications when global events, like 22352 * layout, happen. 22353 * 22354 * The returned ViewTreeObserver observer is not guaranteed to remain 22355 * valid for the lifetime of this View. If the caller of this method keeps 22356 * a long-lived reference to ViewTreeObserver, it should always check for 22357 * the return value of {@link ViewTreeObserver#isAlive()}. 22358 * 22359 * @return The ViewTreeObserver for this view's hierarchy. 22360 */ getViewTreeObserver()22361 public ViewTreeObserver getViewTreeObserver() { 22362 if (mAttachInfo != null) { 22363 return mAttachInfo.mTreeObserver; 22364 } 22365 if (mFloatingTreeObserver == null) { 22366 mFloatingTreeObserver = new ViewTreeObserver(mContext); 22367 } 22368 return mFloatingTreeObserver; 22369 } 22370 22371 /** 22372 * <p>Finds the topmost view in the current view hierarchy.</p> 22373 * 22374 * @return the topmost view containing this view 22375 */ getRootView()22376 public View getRootView() { 22377 if (mAttachInfo != null) { 22378 final View v = mAttachInfo.mRootView; 22379 if (v != null) { 22380 return v; 22381 } 22382 } 22383 22384 View parent = this; 22385 22386 while (parent.mParent != null && parent.mParent instanceof View) { 22387 parent = (View) parent.mParent; 22388 } 22389 22390 return parent; 22391 } 22392 22393 /** 22394 * Transforms a motion event from view-local coordinates to on-screen 22395 * coordinates. 22396 * 22397 * @param ev the view-local motion event 22398 * @return false if the transformation could not be applied 22399 * @hide 22400 */ toGlobalMotionEvent(MotionEvent ev)22401 public boolean toGlobalMotionEvent(MotionEvent ev) { 22402 final AttachInfo info = mAttachInfo; 22403 if (info == null) { 22404 return false; 22405 } 22406 22407 final Matrix m = info.mTmpMatrix; 22408 m.set(Matrix.IDENTITY_MATRIX); 22409 transformMatrixToGlobal(m); 22410 ev.transform(m); 22411 return true; 22412 } 22413 22414 /** 22415 * Transforms a motion event from on-screen coordinates to view-local 22416 * coordinates. 22417 * 22418 * @param ev the on-screen motion event 22419 * @return false if the transformation could not be applied 22420 * @hide 22421 */ toLocalMotionEvent(MotionEvent ev)22422 public boolean toLocalMotionEvent(MotionEvent ev) { 22423 final AttachInfo info = mAttachInfo; 22424 if (info == null) { 22425 return false; 22426 } 22427 22428 final Matrix m = info.mTmpMatrix; 22429 m.set(Matrix.IDENTITY_MATRIX); 22430 transformMatrixToLocal(m); 22431 ev.transform(m); 22432 return true; 22433 } 22434 22435 /** 22436 * Modifies the input matrix such that it maps view-local coordinates to 22437 * on-screen coordinates. 22438 * 22439 * @param m input matrix to modify 22440 * @hide 22441 */ transformMatrixToGlobal(Matrix m)22442 public void transformMatrixToGlobal(Matrix m) { 22443 final ViewParent parent = mParent; 22444 if (parent instanceof View) { 22445 final View vp = (View) parent; 22446 vp.transformMatrixToGlobal(m); 22447 m.preTranslate(-vp.mScrollX, -vp.mScrollY); 22448 } else if (parent instanceof ViewRootImpl) { 22449 final ViewRootImpl vr = (ViewRootImpl) parent; 22450 vr.transformMatrixToGlobal(m); 22451 m.preTranslate(0, -vr.mCurScrollY); 22452 } 22453 22454 m.preTranslate(mLeft, mTop); 22455 22456 if (!hasIdentityMatrix()) { 22457 m.preConcat(getMatrix()); 22458 } 22459 } 22460 22461 /** 22462 * Modifies the input matrix such that it maps on-screen coordinates to 22463 * view-local coordinates. 22464 * 22465 * @param m input matrix to modify 22466 * @hide 22467 */ transformMatrixToLocal(Matrix m)22468 public void transformMatrixToLocal(Matrix m) { 22469 final ViewParent parent = mParent; 22470 if (parent instanceof View) { 22471 final View vp = (View) parent; 22472 vp.transformMatrixToLocal(m); 22473 m.postTranslate(vp.mScrollX, vp.mScrollY); 22474 } else if (parent instanceof ViewRootImpl) { 22475 final ViewRootImpl vr = (ViewRootImpl) parent; 22476 vr.transformMatrixToLocal(m); 22477 m.postTranslate(0, vr.mCurScrollY); 22478 } 22479 22480 m.postTranslate(-mLeft, -mTop); 22481 22482 if (!hasIdentityMatrix()) { 22483 m.postConcat(getInverseMatrix()); 22484 } 22485 } 22486 22487 /** 22488 * @hide 22489 */ 22490 @ViewDebug.ExportedProperty(category = "layout", indexMapping = { 22491 @ViewDebug.IntToString(from = 0, to = "x"), 22492 @ViewDebug.IntToString(from = 1, to = "y") 22493 }) getLocationOnScreen()22494 public int[] getLocationOnScreen() { 22495 int[] location = new int[2]; 22496 getLocationOnScreen(location); 22497 return location; 22498 } 22499 22500 /** 22501 * <p>Computes the coordinates of this view on the screen. The argument 22502 * must be an array of two integers. After the method returns, the array 22503 * contains the x and y location in that order.</p> 22504 * 22505 * @param outLocation an array of two integers in which to hold the coordinates 22506 */ getLocationOnScreen(@ize2) int[] outLocation)22507 public void getLocationOnScreen(@Size(2) int[] outLocation) { 22508 getLocationInWindow(outLocation); 22509 22510 final AttachInfo info = mAttachInfo; 22511 if (info != null) { 22512 outLocation[0] += info.mWindowLeft; 22513 outLocation[1] += info.mWindowTop; 22514 } 22515 } 22516 22517 /** 22518 * <p>Computes the coordinates of this view in its window. The argument 22519 * must be an array of two integers. After the method returns, the array 22520 * contains the x and y location in that order.</p> 22521 * 22522 * @param outLocation an array of two integers in which to hold the coordinates 22523 */ getLocationInWindow(@ize2) int[] outLocation)22524 public void getLocationInWindow(@Size(2) int[] outLocation) { 22525 if (outLocation == null || outLocation.length < 2) { 22526 throw new IllegalArgumentException("outLocation must be an array of two integers"); 22527 } 22528 22529 outLocation[0] = 0; 22530 outLocation[1] = 0; 22531 22532 transformFromViewToWindowSpace(outLocation); 22533 } 22534 22535 /** @hide */ transformFromViewToWindowSpace(@ize2) int[] inOutLocation)22536 public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) { 22537 if (inOutLocation == null || inOutLocation.length < 2) { 22538 throw new IllegalArgumentException("inOutLocation must be an array of two integers"); 22539 } 22540 22541 if (mAttachInfo == null) { 22542 // When the view is not attached to a window, this method does not make sense 22543 inOutLocation[0] = inOutLocation[1] = 0; 22544 return; 22545 } 22546 22547 float position[] = mAttachInfo.mTmpTransformLocation; 22548 position[0] = inOutLocation[0]; 22549 position[1] = inOutLocation[1]; 22550 22551 if (!hasIdentityMatrix()) { 22552 getMatrix().mapPoints(position); 22553 } 22554 22555 position[0] += mLeft; 22556 position[1] += mTop; 22557 22558 ViewParent viewParent = mParent; 22559 while (viewParent instanceof View) { 22560 final View view = (View) viewParent; 22561 22562 position[0] -= view.mScrollX; 22563 position[1] -= view.mScrollY; 22564 22565 if (!view.hasIdentityMatrix()) { 22566 view.getMatrix().mapPoints(position); 22567 } 22568 22569 position[0] += view.mLeft; 22570 position[1] += view.mTop; 22571 22572 viewParent = view.mParent; 22573 } 22574 22575 if (viewParent instanceof ViewRootImpl) { 22576 // *cough* 22577 final ViewRootImpl vr = (ViewRootImpl) viewParent; 22578 position[1] -= vr.mCurScrollY; 22579 } 22580 22581 inOutLocation[0] = Math.round(position[0]); 22582 inOutLocation[1] = Math.round(position[1]); 22583 } 22584 22585 /** 22586 * @param id the id of the view to be found 22587 * @return the view of the specified id, null if cannot be found 22588 * @hide 22589 */ findViewTraversal(@dRes int id)22590 protected <T extends View> T findViewTraversal(@IdRes int id) { 22591 if (id == mID) { 22592 return (T) this; 22593 } 22594 return null; 22595 } 22596 22597 /** 22598 * @param tag the tag of the view to be found 22599 * @return the view of specified tag, null if cannot be found 22600 * @hide 22601 */ findViewWithTagTraversal(Object tag)22602 protected <T extends View> T findViewWithTagTraversal(Object tag) { 22603 if (tag != null && tag.equals(mTag)) { 22604 return (T) this; 22605 } 22606 return null; 22607 } 22608 22609 /** 22610 * @param predicate The predicate to evaluate. 22611 * @param childToSkip If not null, ignores this child during the recursive traversal. 22612 * @return The first view that matches the predicate or null. 22613 * @hide 22614 */ findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)22615 protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate, 22616 View childToSkip) { 22617 if (predicate.test(this)) { 22618 return (T) this; 22619 } 22620 return null; 22621 } 22622 22623 /** 22624 * Finds the first descendant view with the given ID, the view itself if 22625 * the ID matches {@link #getId()}, or {@code null} if the ID is invalid 22626 * (< 0) or there is no matching view in the hierarchy. 22627 * <p> 22628 * <strong>Note:</strong> In most cases -- depending on compiler support -- 22629 * the resulting view is automatically cast to the target class type. If 22630 * the target class type is unconstrained, an explicit cast may be 22631 * necessary. 22632 * 22633 * @param id the ID to search for 22634 * @return a view with given ID if found, or {@code null} otherwise 22635 * @see View#requireViewById(int) 22636 */ 22637 @Nullable findViewById(@dRes int id)22638 public final <T extends View> T findViewById(@IdRes int id) { 22639 if (id == NO_ID) { 22640 return null; 22641 } 22642 return findViewTraversal(id); 22643 } 22644 22645 /** 22646 * Finds the first descendant view with the given ID, the view itself if the ID matches 22647 * {@link #getId()}, or throws an IllegalArgumentException if the ID is invalid or there is no 22648 * matching view in the hierarchy. 22649 * <p> 22650 * <strong>Note:</strong> In most cases -- depending on compiler support -- 22651 * the resulting view is automatically cast to the target class type. If 22652 * the target class type is unconstrained, an explicit cast may be 22653 * necessary. 22654 * 22655 * @param id the ID to search for 22656 * @return a view with given ID 22657 * @see View#findViewById(int) 22658 */ 22659 @NonNull requireViewById(@dRes int id)22660 public final <T extends View> T requireViewById(@IdRes int id) { 22661 T view = findViewById(id); 22662 if (view == null) { 22663 throw new IllegalArgumentException("ID does not reference a View inside this View"); 22664 } 22665 return view; 22666 } 22667 22668 /** 22669 * Finds a view by its unuque and stable accessibility id. 22670 * 22671 * @param accessibilityId The searched accessibility id. 22672 * @return The found view. 22673 */ findViewByAccessibilityId(int accessibilityId)22674 final <T extends View> T findViewByAccessibilityId(int accessibilityId) { 22675 if (accessibilityId < 0) { 22676 return null; 22677 } 22678 T view = findViewByAccessibilityIdTraversal(accessibilityId); 22679 if (view != null) { 22680 return view.includeForAccessibility() ? view : null; 22681 } 22682 return null; 22683 } 22684 22685 /** 22686 * Performs the traversal to find a view by its unique and stable accessibility id. 22687 * 22688 * <strong>Note:</strong>This method does not stop at the root namespace 22689 * boundary since the user can touch the screen at an arbitrary location 22690 * potentially crossing the root namespace boundary which will send an 22691 * accessibility event to accessibility services and they should be able 22692 * to obtain the event source. Also accessibility ids are guaranteed to be 22693 * unique in the window. 22694 * 22695 * @param accessibilityId The accessibility id. 22696 * @return The found view. 22697 * @hide 22698 */ findViewByAccessibilityIdTraversal(int accessibilityId)22699 public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) { 22700 if (getAccessibilityViewId() == accessibilityId) { 22701 return (T) this; 22702 } 22703 return null; 22704 } 22705 22706 /** 22707 * Performs the traversal to find a view by its autofill id. 22708 * 22709 * <strong>Note:</strong>This method does not stop at the root namespace 22710 * boundary. 22711 * 22712 * @param autofillId The autofill id. 22713 * @return The found view. 22714 * @hide 22715 */ findViewByAutofillIdTraversal(int autofillId)22716 public <T extends View> T findViewByAutofillIdTraversal(int autofillId) { 22717 if (getAutofillViewId() == autofillId) { 22718 return (T) this; 22719 } 22720 return null; 22721 } 22722 22723 /** 22724 * Look for a child view with the given tag. If this view has the given 22725 * tag, return this view. 22726 * 22727 * @param tag The tag to search for, using "tag.equals(getTag())". 22728 * @return The View that has the given tag in the hierarchy or null 22729 */ findViewWithTag(Object tag)22730 public final <T extends View> T findViewWithTag(Object tag) { 22731 if (tag == null) { 22732 return null; 22733 } 22734 return findViewWithTagTraversal(tag); 22735 } 22736 22737 /** 22738 * Look for a child view that matches the specified predicate. 22739 * If this view matches the predicate, return this view. 22740 * 22741 * @param predicate The predicate to evaluate. 22742 * @return The first view that matches the predicate or null. 22743 * @hide 22744 */ findViewByPredicate(Predicate<View> predicate)22745 public final <T extends View> T findViewByPredicate(Predicate<View> predicate) { 22746 return findViewByPredicateTraversal(predicate, null); 22747 } 22748 22749 /** 22750 * Look for a child view that matches the specified predicate, 22751 * starting with the specified view and its descendents and then 22752 * recusively searching the ancestors and siblings of that view 22753 * until this view is reached. 22754 * 22755 * This method is useful in cases where the predicate does not match 22756 * a single unique view (perhaps multiple views use the same id) 22757 * and we are trying to find the view that is "closest" in scope to the 22758 * starting view. 22759 * 22760 * @param start The view to start from. 22761 * @param predicate The predicate to evaluate. 22762 * @return The first view that matches the predicate or null. 22763 * @hide 22764 */ findViewByPredicateInsideOut( View start, Predicate<View> predicate)22765 public final <T extends View> T findViewByPredicateInsideOut( 22766 View start, Predicate<View> predicate) { 22767 View childToSkip = null; 22768 for (;;) { 22769 T view = start.findViewByPredicateTraversal(predicate, childToSkip); 22770 if (view != null || start == this) { 22771 return view; 22772 } 22773 22774 ViewParent parent = start.getParent(); 22775 if (parent == null || !(parent instanceof View)) { 22776 return null; 22777 } 22778 22779 childToSkip = start; 22780 start = (View) parent; 22781 } 22782 } 22783 22784 /** 22785 * Sets the identifier for this view. The identifier does not have to be 22786 * unique in this view's hierarchy. The identifier should be a positive 22787 * number. 22788 * 22789 * @see #NO_ID 22790 * @see #getId() 22791 * @see #findViewById(int) 22792 * 22793 * @param id a number used to identify the view 22794 * 22795 * @attr ref android.R.styleable#View_id 22796 */ setId(@dRes int id)22797 public void setId(@IdRes int id) { 22798 mID = id; 22799 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 22800 mID = generateViewId(); 22801 } 22802 } 22803 22804 /** 22805 * {@hide} 22806 * 22807 * @param isRoot true if the view belongs to the root namespace, false 22808 * otherwise 22809 */ setIsRootNamespace(boolean isRoot)22810 public void setIsRootNamespace(boolean isRoot) { 22811 if (isRoot) { 22812 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 22813 } else { 22814 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 22815 } 22816 } 22817 22818 /** 22819 * {@hide} 22820 * 22821 * @return true if the view belongs to the root namespace, false otherwise 22822 */ isRootNamespace()22823 public boolean isRootNamespace() { 22824 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 22825 } 22826 22827 /** 22828 * Returns this view's identifier. 22829 * 22830 * @return a positive integer used to identify the view or {@link #NO_ID} 22831 * if the view has no ID 22832 * 22833 * @see #setId(int) 22834 * @see #findViewById(int) 22835 * @attr ref android.R.styleable#View_id 22836 */ 22837 @IdRes 22838 @ViewDebug.CapturedViewProperty getId()22839 public int getId() { 22840 return mID; 22841 } 22842 22843 /** 22844 * Returns this view's tag. 22845 * 22846 * @return the Object stored in this view as a tag, or {@code null} if not 22847 * set 22848 * 22849 * @see #setTag(Object) 22850 * @see #getTag(int) 22851 */ 22852 @ViewDebug.ExportedProperty getTag()22853 public Object getTag() { 22854 return mTag; 22855 } 22856 22857 /** 22858 * Sets the tag associated with this view. A tag can be used to mark 22859 * a view in its hierarchy and does not have to be unique within the 22860 * hierarchy. Tags can also be used to store data within a view without 22861 * resorting to another data structure. 22862 * 22863 * @param tag an Object to tag the view with 22864 * 22865 * @see #getTag() 22866 * @see #setTag(int, Object) 22867 */ setTag(final Object tag)22868 public void setTag(final Object tag) { 22869 mTag = tag; 22870 } 22871 22872 /** 22873 * Returns the tag associated with this view and the specified key. 22874 * 22875 * @param key The key identifying the tag 22876 * 22877 * @return the Object stored in this view as a tag, or {@code null} if not 22878 * set 22879 * 22880 * @see #setTag(int, Object) 22881 * @see #getTag() 22882 */ getTag(int key)22883 public Object getTag(int key) { 22884 if (mKeyedTags != null) return mKeyedTags.get(key); 22885 return null; 22886 } 22887 22888 /** 22889 * Sets a tag associated with this view and a key. A tag can be used 22890 * to mark a view in its hierarchy and does not have to be unique within 22891 * the hierarchy. Tags can also be used to store data within a view 22892 * without resorting to another data structure. 22893 * 22894 * The specified key should be an id declared in the resources of the 22895 * application to ensure it is unique (see the <a 22896 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 22897 * Keys identified as belonging to 22898 * the Android framework or not associated with any package will cause 22899 * an {@link IllegalArgumentException} to be thrown. 22900 * 22901 * @param key The key identifying the tag 22902 * @param tag An Object to tag the view with 22903 * 22904 * @throws IllegalArgumentException If they specified key is not valid 22905 * 22906 * @see #setTag(Object) 22907 * @see #getTag(int) 22908 */ setTag(int key, final Object tag)22909 public void setTag(int key, final Object tag) { 22910 // If the package id is 0x00 or 0x01, it's either an undefined package 22911 // or a framework id 22912 if ((key >>> 24) < 2) { 22913 throw new IllegalArgumentException("The key must be an application-specific " 22914 + "resource id."); 22915 } 22916 22917 setKeyedTag(key, tag); 22918 } 22919 22920 /** 22921 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 22922 * framework id. 22923 * 22924 * @hide 22925 */ setTagInternal(int key, Object tag)22926 public void setTagInternal(int key, Object tag) { 22927 if ((key >>> 24) != 0x1) { 22928 throw new IllegalArgumentException("The key must be a framework-specific " 22929 + "resource id."); 22930 } 22931 22932 setKeyedTag(key, tag); 22933 } 22934 setKeyedTag(int key, Object tag)22935 private void setKeyedTag(int key, Object tag) { 22936 if (mKeyedTags == null) { 22937 mKeyedTags = new SparseArray<Object>(2); 22938 } 22939 22940 mKeyedTags.put(key, tag); 22941 } 22942 22943 /** 22944 * Prints information about this view in the log output, with the tag 22945 * {@link #VIEW_LOG_TAG}. 22946 * 22947 * @hide 22948 */ debug()22949 public void debug() { 22950 debug(0); 22951 } 22952 22953 /** 22954 * Prints information about this view in the log output, with the tag 22955 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 22956 * indentation defined by the <code>depth</code>. 22957 * 22958 * @param depth the indentation level 22959 * 22960 * @hide 22961 */ debug(int depth)22962 protected void debug(int depth) { 22963 String output = debugIndent(depth - 1); 22964 22965 output += "+ " + this; 22966 int id = getId(); 22967 if (id != -1) { 22968 output += " (id=" + id + ")"; 22969 } 22970 Object tag = getTag(); 22971 if (tag != null) { 22972 output += " (tag=" + tag + ")"; 22973 } 22974 Log.d(VIEW_LOG_TAG, output); 22975 22976 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 22977 output = debugIndent(depth) + " FOCUSED"; 22978 Log.d(VIEW_LOG_TAG, output); 22979 } 22980 22981 output = debugIndent(depth); 22982 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 22983 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 22984 + "} "; 22985 Log.d(VIEW_LOG_TAG, output); 22986 22987 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 22988 || mPaddingBottom != 0) { 22989 output = debugIndent(depth); 22990 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 22991 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 22992 Log.d(VIEW_LOG_TAG, output); 22993 } 22994 22995 output = debugIndent(depth); 22996 output += "mMeasureWidth=" + mMeasuredWidth + 22997 " mMeasureHeight=" + mMeasuredHeight; 22998 Log.d(VIEW_LOG_TAG, output); 22999 23000 output = debugIndent(depth); 23001 if (mLayoutParams == null) { 23002 output += "BAD! no layout params"; 23003 } else { 23004 output = mLayoutParams.debug(output); 23005 } 23006 Log.d(VIEW_LOG_TAG, output); 23007 23008 output = debugIndent(depth); 23009 output += "flags={"; 23010 output += View.printFlags(mViewFlags); 23011 output += "}"; 23012 Log.d(VIEW_LOG_TAG, output); 23013 23014 output = debugIndent(depth); 23015 output += "privateFlags={"; 23016 output += View.printPrivateFlags(mPrivateFlags); 23017 output += "}"; 23018 Log.d(VIEW_LOG_TAG, output); 23019 } 23020 23021 /** 23022 * Creates a string of whitespaces used for indentation. 23023 * 23024 * @param depth the indentation level 23025 * @return a String containing (depth * 2 + 3) * 2 white spaces 23026 * 23027 * @hide 23028 */ debugIndent(int depth)23029 protected static String debugIndent(int depth) { 23030 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 23031 for (int i = 0; i < (depth * 2) + 3; i++) { 23032 spaces.append(' ').append(' '); 23033 } 23034 return spaces.toString(); 23035 } 23036 23037 /** 23038 * <p>Return the offset of the widget's text baseline from the widget's top 23039 * boundary. If this widget does not support baseline alignment, this 23040 * method returns -1. </p> 23041 * 23042 * @return the offset of the baseline within the widget's bounds or -1 23043 * if baseline alignment is not supported 23044 */ 23045 @ViewDebug.ExportedProperty(category = "layout") getBaseline()23046 public int getBaseline() { 23047 return -1; 23048 } 23049 23050 /** 23051 * Returns whether the view hierarchy is currently undergoing a layout pass. This 23052 * information is useful to avoid situations such as calling {@link #requestLayout()} during 23053 * a layout pass. 23054 * 23055 * @return whether the view hierarchy is currently undergoing a layout pass 23056 */ isInLayout()23057 public boolean isInLayout() { 23058 ViewRootImpl viewRoot = getViewRootImpl(); 23059 return (viewRoot != null && viewRoot.isInLayout()); 23060 } 23061 23062 /** 23063 * Call this when something has changed which has invalidated the 23064 * layout of this view. This will schedule a layout pass of the view 23065 * tree. This should not be called while the view hierarchy is currently in a layout 23066 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 23067 * end of the current layout pass (and then layout will run again) or after the current 23068 * frame is drawn and the next layout occurs. 23069 * 23070 * <p>Subclasses which override this method should call the superclass method to 23071 * handle possible request-during-layout errors correctly.</p> 23072 */ 23073 @CallSuper requestLayout()23074 public void requestLayout() { 23075 if (mMeasureCache != null) mMeasureCache.clear(); 23076 23077 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 23078 // Only trigger request-during-layout logic if this is the view requesting it, 23079 // not the views in its parent hierarchy 23080 ViewRootImpl viewRoot = getViewRootImpl(); 23081 if (viewRoot != null && viewRoot.isInLayout()) { 23082 if (!viewRoot.requestLayoutDuringLayout(this)) { 23083 return; 23084 } 23085 } 23086 mAttachInfo.mViewRequestingLayout = this; 23087 } 23088 23089 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 23090 mPrivateFlags |= PFLAG_INVALIDATED; 23091 23092 if (mParent != null && !mParent.isLayoutRequested()) { 23093 mParent.requestLayout(); 23094 } 23095 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 23096 mAttachInfo.mViewRequestingLayout = null; 23097 } 23098 } 23099 23100 /** 23101 * Forces this view to be laid out during the next layout pass. 23102 * This method does not call requestLayout() or forceLayout() 23103 * on the parent. 23104 */ forceLayout()23105 public void forceLayout() { 23106 if (mMeasureCache != null) mMeasureCache.clear(); 23107 23108 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 23109 mPrivateFlags |= PFLAG_INVALIDATED; 23110 } 23111 23112 /** 23113 * <p> 23114 * This is called to find out how big a view should be. The parent 23115 * supplies constraint information in the width and height parameters. 23116 * </p> 23117 * 23118 * <p> 23119 * The actual measurement work of a view is performed in 23120 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 23121 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 23122 * </p> 23123 * 23124 * 23125 * @param widthMeasureSpec Horizontal space requirements as imposed by the 23126 * parent 23127 * @param heightMeasureSpec Vertical space requirements as imposed by the 23128 * parent 23129 * 23130 * @see #onMeasure(int, int) 23131 */ measure(int widthMeasureSpec, int heightMeasureSpec)23132 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 23133 boolean optical = isLayoutModeOptical(this); 23134 if (optical != isLayoutModeOptical(mParent)) { 23135 Insets insets = getOpticalInsets(); 23136 int oWidth = insets.left + insets.right; 23137 int oHeight = insets.top + insets.bottom; 23138 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 23139 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 23140 } 23141 23142 // Suppress sign extension for the low bytes 23143 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 23144 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 23145 23146 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 23147 23148 // Optimize layout by avoiding an extra EXACTLY pass when the view is 23149 // already measured as the correct size. In API 23 and below, this 23150 // extra pass is required to make LinearLayout re-distribute weight. 23151 final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec 23152 || heightMeasureSpec != mOldHeightMeasureSpec; 23153 final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY 23154 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; 23155 final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) 23156 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); 23157 final boolean needsLayout = specChanged 23158 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize); 23159 23160 if (forceLayout || needsLayout) { 23161 // first clears the measured dimension flag 23162 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 23163 23164 resolveRtlPropertiesIfNeeded(); 23165 23166 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); 23167 if (cacheIndex < 0 || sIgnoreMeasureCache) { 23168 // measure ourselves, this should set the measured dimension flag back 23169 onMeasure(widthMeasureSpec, heightMeasureSpec); 23170 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 23171 } else { 23172 long value = mMeasureCache.valueAt(cacheIndex); 23173 // Casting a long to int drops the high 32 bits, no mask needed 23174 setMeasuredDimensionRaw((int) (value >> 32), (int) value); 23175 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 23176 } 23177 23178 // flag not set, setMeasuredDimension() was not invoked, we raise 23179 // an exception to warn the developer 23180 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 23181 throw new IllegalStateException("View with id " + getId() + ": " 23182 + getClass().getName() + "#onMeasure() did not set the" 23183 + " measured dimension by calling" 23184 + " setMeasuredDimension()"); 23185 } 23186 23187 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 23188 } 23189 23190 mOldWidthMeasureSpec = widthMeasureSpec; 23191 mOldHeightMeasureSpec = heightMeasureSpec; 23192 23193 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 23194 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 23195 } 23196 23197 /** 23198 * <p> 23199 * Measure the view and its content to determine the measured width and the 23200 * measured height. This method is invoked by {@link #measure(int, int)} and 23201 * should be overridden by subclasses to provide accurate and efficient 23202 * measurement of their contents. 23203 * </p> 23204 * 23205 * <p> 23206 * <strong>CONTRACT:</strong> When overriding this method, you 23207 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 23208 * measured width and height of this view. Failure to do so will trigger an 23209 * <code>IllegalStateException</code>, thrown by 23210 * {@link #measure(int, int)}. Calling the superclass' 23211 * {@link #onMeasure(int, int)} is a valid use. 23212 * </p> 23213 * 23214 * <p> 23215 * The base class implementation of measure defaults to the background size, 23216 * unless a larger size is allowed by the MeasureSpec. Subclasses should 23217 * override {@link #onMeasure(int, int)} to provide better measurements of 23218 * their content. 23219 * </p> 23220 * 23221 * <p> 23222 * If this method is overridden, it is the subclass's responsibility to make 23223 * sure the measured height and width are at least the view's minimum height 23224 * and width ({@link #getSuggestedMinimumHeight()} and 23225 * {@link #getSuggestedMinimumWidth()}). 23226 * </p> 23227 * 23228 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 23229 * The requirements are encoded with 23230 * {@link android.view.View.MeasureSpec}. 23231 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 23232 * The requirements are encoded with 23233 * {@link android.view.View.MeasureSpec}. 23234 * 23235 * @see #getMeasuredWidth() 23236 * @see #getMeasuredHeight() 23237 * @see #setMeasuredDimension(int, int) 23238 * @see #getSuggestedMinimumHeight() 23239 * @see #getSuggestedMinimumWidth() 23240 * @see android.view.View.MeasureSpec#getMode(int) 23241 * @see android.view.View.MeasureSpec#getSize(int) 23242 */ onMeasure(int widthMeasureSpec, int heightMeasureSpec)23243 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 23244 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 23245 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 23246 } 23247 23248 /** 23249 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 23250 * measured width and measured height. Failing to do so will trigger an 23251 * exception at measurement time.</p> 23252 * 23253 * @param measuredWidth The measured width of this view. May be a complex 23254 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 23255 * {@link #MEASURED_STATE_TOO_SMALL}. 23256 * @param measuredHeight The measured height of this view. May be a complex 23257 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 23258 * {@link #MEASURED_STATE_TOO_SMALL}. 23259 */ setMeasuredDimension(int measuredWidth, int measuredHeight)23260 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 23261 boolean optical = isLayoutModeOptical(this); 23262 if (optical != isLayoutModeOptical(mParent)) { 23263 Insets insets = getOpticalInsets(); 23264 int opticalWidth = insets.left + insets.right; 23265 int opticalHeight = insets.top + insets.bottom; 23266 23267 measuredWidth += optical ? opticalWidth : -opticalWidth; 23268 measuredHeight += optical ? opticalHeight : -opticalHeight; 23269 } 23270 setMeasuredDimensionRaw(measuredWidth, measuredHeight); 23271 } 23272 23273 /** 23274 * Sets the measured dimension without extra processing for things like optical bounds. 23275 * Useful for reapplying consistent values that have already been cooked with adjustments 23276 * for optical bounds, etc. such as those from the measurement cache. 23277 * 23278 * @param measuredWidth The measured width of this view. May be a complex 23279 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 23280 * {@link #MEASURED_STATE_TOO_SMALL}. 23281 * @param measuredHeight The measured height of this view. May be a complex 23282 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 23283 * {@link #MEASURED_STATE_TOO_SMALL}. 23284 */ setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)23285 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { 23286 mMeasuredWidth = measuredWidth; 23287 mMeasuredHeight = measuredHeight; 23288 23289 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 23290 } 23291 23292 /** 23293 * Merge two states as returned by {@link #getMeasuredState()}. 23294 * @param curState The current state as returned from a view or the result 23295 * of combining multiple views. 23296 * @param newState The new view state to combine. 23297 * @return Returns a new integer reflecting the combination of the two 23298 * states. 23299 */ combineMeasuredStates(int curState, int newState)23300 public static int combineMeasuredStates(int curState, int newState) { 23301 return curState | newState; 23302 } 23303 23304 /** 23305 * Version of {@link #resolveSizeAndState(int, int, int)} 23306 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 23307 */ resolveSize(int size, int measureSpec)23308 public static int resolveSize(int size, int measureSpec) { 23309 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 23310 } 23311 23312 /** 23313 * Utility to reconcile a desired size and state, with constraints imposed 23314 * by a MeasureSpec. Will take the desired size, unless a different size 23315 * is imposed by the constraints. The returned value is a compound integer, 23316 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 23317 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the 23318 * resulting size is smaller than the size the view wants to be. 23319 * 23320 * @param size How big the view wants to be. 23321 * @param measureSpec Constraints imposed by the parent. 23322 * @param childMeasuredState Size information bit mask for the view's 23323 * children. 23324 * @return Size information bit mask as defined by 23325 * {@link #MEASURED_SIZE_MASK} and 23326 * {@link #MEASURED_STATE_TOO_SMALL}. 23327 */ resolveSizeAndState(int size, int measureSpec, int childMeasuredState)23328 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 23329 final int specMode = MeasureSpec.getMode(measureSpec); 23330 final int specSize = MeasureSpec.getSize(measureSpec); 23331 final int result; 23332 switch (specMode) { 23333 case MeasureSpec.AT_MOST: 23334 if (specSize < size) { 23335 result = specSize | MEASURED_STATE_TOO_SMALL; 23336 } else { 23337 result = size; 23338 } 23339 break; 23340 case MeasureSpec.EXACTLY: 23341 result = specSize; 23342 break; 23343 case MeasureSpec.UNSPECIFIED: 23344 default: 23345 result = size; 23346 } 23347 return result | (childMeasuredState & MEASURED_STATE_MASK); 23348 } 23349 23350 /** 23351 * Utility to return a default size. Uses the supplied size if the 23352 * MeasureSpec imposed no constraints. Will get larger if allowed 23353 * by the MeasureSpec. 23354 * 23355 * @param size Default size for this view 23356 * @param measureSpec Constraints imposed by the parent 23357 * @return The size this view should be. 23358 */ getDefaultSize(int size, int measureSpec)23359 public static int getDefaultSize(int size, int measureSpec) { 23360 int result = size; 23361 int specMode = MeasureSpec.getMode(measureSpec); 23362 int specSize = MeasureSpec.getSize(measureSpec); 23363 23364 switch (specMode) { 23365 case MeasureSpec.UNSPECIFIED: 23366 result = size; 23367 break; 23368 case MeasureSpec.AT_MOST: 23369 case MeasureSpec.EXACTLY: 23370 result = specSize; 23371 break; 23372 } 23373 return result; 23374 } 23375 23376 /** 23377 * Returns the suggested minimum height that the view should use. This 23378 * returns the maximum of the view's minimum height 23379 * and the background's minimum height 23380 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 23381 * <p> 23382 * When being used in {@link #onMeasure(int, int)}, the caller should still 23383 * ensure the returned height is within the requirements of the parent. 23384 * 23385 * @return The suggested minimum height of the view. 23386 */ getSuggestedMinimumHeight()23387 protected int getSuggestedMinimumHeight() { 23388 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 23389 23390 } 23391 23392 /** 23393 * Returns the suggested minimum width that the view should use. This 23394 * returns the maximum of the view's minimum width 23395 * and the background's minimum width 23396 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 23397 * <p> 23398 * When being used in {@link #onMeasure(int, int)}, the caller should still 23399 * ensure the returned width is within the requirements of the parent. 23400 * 23401 * @return The suggested minimum width of the view. 23402 */ getSuggestedMinimumWidth()23403 protected int getSuggestedMinimumWidth() { 23404 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 23405 } 23406 23407 /** 23408 * Returns the minimum height of the view. 23409 * 23410 * @return the minimum height the view will try to be, in pixels 23411 * 23412 * @see #setMinimumHeight(int) 23413 * 23414 * @attr ref android.R.styleable#View_minHeight 23415 */ getMinimumHeight()23416 public int getMinimumHeight() { 23417 return mMinHeight; 23418 } 23419 23420 /** 23421 * Sets the minimum height of the view. It is not guaranteed the view will 23422 * be able to achieve this minimum height (for example, if its parent layout 23423 * constrains it with less available height). 23424 * 23425 * @param minHeight The minimum height the view will try to be, in pixels 23426 * 23427 * @see #getMinimumHeight() 23428 * 23429 * @attr ref android.R.styleable#View_minHeight 23430 */ 23431 @RemotableViewMethod setMinimumHeight(int minHeight)23432 public void setMinimumHeight(int minHeight) { 23433 mMinHeight = minHeight; 23434 requestLayout(); 23435 } 23436 23437 /** 23438 * Returns the minimum width of the view. 23439 * 23440 * @return the minimum width the view will try to be, in pixels 23441 * 23442 * @see #setMinimumWidth(int) 23443 * 23444 * @attr ref android.R.styleable#View_minWidth 23445 */ getMinimumWidth()23446 public int getMinimumWidth() { 23447 return mMinWidth; 23448 } 23449 23450 /** 23451 * Sets the minimum width of the view. It is not guaranteed the view will 23452 * be able to achieve this minimum width (for example, if its parent layout 23453 * constrains it with less available width). 23454 * 23455 * @param minWidth The minimum width the view will try to be, in pixels 23456 * 23457 * @see #getMinimumWidth() 23458 * 23459 * @attr ref android.R.styleable#View_minWidth 23460 */ setMinimumWidth(int minWidth)23461 public void setMinimumWidth(int minWidth) { 23462 mMinWidth = minWidth; 23463 requestLayout(); 23464 23465 } 23466 23467 /** 23468 * Get the animation currently associated with this view. 23469 * 23470 * @return The animation that is currently playing or 23471 * scheduled to play for this view. 23472 */ getAnimation()23473 public Animation getAnimation() { 23474 return mCurrentAnimation; 23475 } 23476 23477 /** 23478 * Start the specified animation now. 23479 * 23480 * @param animation the animation to start now 23481 */ startAnimation(Animation animation)23482 public void startAnimation(Animation animation) { 23483 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 23484 setAnimation(animation); 23485 invalidateParentCaches(); 23486 invalidate(true); 23487 } 23488 23489 /** 23490 * Cancels any animations for this view. 23491 */ clearAnimation()23492 public void clearAnimation() { 23493 if (mCurrentAnimation != null) { 23494 mCurrentAnimation.detach(); 23495 } 23496 mCurrentAnimation = null; 23497 invalidateParentIfNeeded(); 23498 } 23499 23500 /** 23501 * Sets the next animation to play for this view. 23502 * If you want the animation to play immediately, use 23503 * {@link #startAnimation(android.view.animation.Animation)} instead. 23504 * This method provides allows fine-grained 23505 * control over the start time and invalidation, but you 23506 * must make sure that 1) the animation has a start time set, and 23507 * 2) the view's parent (which controls animations on its children) 23508 * will be invalidated when the animation is supposed to 23509 * start. 23510 * 23511 * @param animation The next animation, or null. 23512 */ setAnimation(Animation animation)23513 public void setAnimation(Animation animation) { 23514 mCurrentAnimation = animation; 23515 23516 if (animation != null) { 23517 // If the screen is off assume the animation start time is now instead of 23518 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 23519 // would cause the animation to start when the screen turns back on 23520 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF 23521 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 23522 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 23523 } 23524 animation.reset(); 23525 } 23526 } 23527 23528 /** 23529 * Invoked by a parent ViewGroup to notify the start of the animation 23530 * currently associated with this view. If you override this method, 23531 * always call super.onAnimationStart(); 23532 * 23533 * @see #setAnimation(android.view.animation.Animation) 23534 * @see #getAnimation() 23535 */ 23536 @CallSuper onAnimationStart()23537 protected void onAnimationStart() { 23538 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 23539 } 23540 23541 /** 23542 * Invoked by a parent ViewGroup to notify the end of the animation 23543 * currently associated with this view. If you override this method, 23544 * always call super.onAnimationEnd(); 23545 * 23546 * @see #setAnimation(android.view.animation.Animation) 23547 * @see #getAnimation() 23548 */ 23549 @CallSuper onAnimationEnd()23550 protected void onAnimationEnd() { 23551 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 23552 } 23553 23554 /** 23555 * Invoked if there is a Transform that involves alpha. Subclass that can 23556 * draw themselves with the specified alpha should return true, and then 23557 * respect that alpha when their onDraw() is called. If this returns false 23558 * then the view may be redirected to draw into an offscreen buffer to 23559 * fulfill the request, which will look fine, but may be slower than if the 23560 * subclass handles it internally. The default implementation returns false. 23561 * 23562 * @param alpha The alpha (0..255) to apply to the view's drawing 23563 * @return true if the view can draw with the specified alpha. 23564 */ onSetAlpha(int alpha)23565 protected boolean onSetAlpha(int alpha) { 23566 return false; 23567 } 23568 23569 /** 23570 * This is used by the RootView to perform an optimization when 23571 * the view hierarchy contains one or several SurfaceView. 23572 * SurfaceView is always considered transparent, but its children are not, 23573 * therefore all View objects remove themselves from the global transparent 23574 * region (passed as a parameter to this function). 23575 * 23576 * @param region The transparent region for this ViewAncestor (window). 23577 * 23578 * @return Returns true if the effective visibility of the view at this 23579 * point is opaque, regardless of the transparent region; returns false 23580 * if it is possible for underlying windows to be seen behind the view. 23581 * 23582 * {@hide} 23583 */ gatherTransparentRegion(Region region)23584 public boolean gatherTransparentRegion(Region region) { 23585 final AttachInfo attachInfo = mAttachInfo; 23586 if (region != null && attachInfo != null) { 23587 final int pflags = mPrivateFlags; 23588 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 23589 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 23590 // remove it from the transparent region. 23591 final int[] location = attachInfo.mTransparentLocation; 23592 getLocationInWindow(location); 23593 // When a view has Z value, then it will be better to leave some area below the view 23594 // for drawing shadow. The shadow outset is proportional to the Z value. Note that 23595 // the bottom part needs more offset than the left, top and right parts due to the 23596 // spot light effects. 23597 int shadowOffset = getZ() > 0 ? (int) getZ() : 0; 23598 region.op(location[0] - shadowOffset, location[1] - shadowOffset, 23599 location[0] + mRight - mLeft + shadowOffset, 23600 location[1] + mBottom - mTop + (shadowOffset * 3), Region.Op.DIFFERENCE); 23601 } else { 23602 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) { 23603 // The SKIP_DRAW flag IS set and the background drawable exists, we remove 23604 // the background drawable's non-transparent parts from this transparent region. 23605 applyDrawableToTransparentRegion(mBackground, region); 23606 } 23607 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 23608 && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) { 23609 // Similarly, we remove the foreground drawable's non-transparent parts. 23610 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region); 23611 } 23612 if (mDefaultFocusHighlight != null 23613 && mDefaultFocusHighlight.getOpacity() != PixelFormat.TRANSPARENT) { 23614 // Similarly, we remove the default focus highlight's non-transparent parts. 23615 applyDrawableToTransparentRegion(mDefaultFocusHighlight, region); 23616 } 23617 } 23618 } 23619 return true; 23620 } 23621 23622 /** 23623 * Play a sound effect for this view. 23624 * 23625 * <p>The framework will play sound effects for some built in actions, such as 23626 * clicking, but you may wish to play these effects in your widget, 23627 * for instance, for internal navigation. 23628 * 23629 * <p>The sound effect will only be played if sound effects are enabled by the user, and 23630 * {@link #isSoundEffectsEnabled()} is true. 23631 * 23632 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 23633 */ playSoundEffect(int soundConstant)23634 public void playSoundEffect(int soundConstant) { 23635 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 23636 return; 23637 } 23638 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 23639 } 23640 23641 /** 23642 * BZZZTT!!1! 23643 * 23644 * <p>Provide haptic feedback to the user for this view. 23645 * 23646 * <p>The framework will provide haptic feedback for some built in actions, 23647 * such as long presses, but you may wish to provide feedback for your 23648 * own widget. 23649 * 23650 * <p>The feedback will only be performed if 23651 * {@link #isHapticFeedbackEnabled()} is true. 23652 * 23653 * @param feedbackConstant One of the constants defined in 23654 * {@link HapticFeedbackConstants} 23655 */ performHapticFeedback(int feedbackConstant)23656 public boolean performHapticFeedback(int feedbackConstant) { 23657 return performHapticFeedback(feedbackConstant, 0); 23658 } 23659 23660 /** 23661 * BZZZTT!!1! 23662 * 23663 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 23664 * 23665 * @param feedbackConstant One of the constants defined in 23666 * {@link HapticFeedbackConstants} 23667 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 23668 */ performHapticFeedback(int feedbackConstant, int flags)23669 public boolean performHapticFeedback(int feedbackConstant, int flags) { 23670 if (mAttachInfo == null) { 23671 return false; 23672 } 23673 //noinspection SimplifiableIfStatement 23674 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 23675 && !isHapticFeedbackEnabled()) { 23676 return false; 23677 } 23678 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 23679 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 23680 } 23681 23682 /** 23683 * Request that the visibility of the status bar or other screen/window 23684 * decorations be changed. 23685 * 23686 * <p>This method is used to put the over device UI into temporary modes 23687 * where the user's attention is focused more on the application content, 23688 * by dimming or hiding surrounding system affordances. This is typically 23689 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 23690 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 23691 * to be placed behind the action bar (and with these flags other system 23692 * affordances) so that smooth transitions between hiding and showing them 23693 * can be done. 23694 * 23695 * <p>Two representative examples of the use of system UI visibility is 23696 * implementing a content browsing application (like a magazine reader) 23697 * and a video playing application. 23698 * 23699 * <p>The first code shows a typical implementation of a View in a content 23700 * browsing application. In this implementation, the application goes 23701 * into a content-oriented mode by hiding the status bar and action bar, 23702 * and putting the navigation elements into lights out mode. The user can 23703 * then interact with content while in this mode. Such an application should 23704 * provide an easy way for the user to toggle out of the mode (such as to 23705 * check information in the status bar or access notifications). In the 23706 * implementation here, this is done simply by tapping on the content. 23707 * 23708 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 23709 * content} 23710 * 23711 * <p>This second code sample shows a typical implementation of a View 23712 * in a video playing application. In this situation, while the video is 23713 * playing the application would like to go into a complete full-screen mode, 23714 * to use as much of the display as possible for the video. When in this state 23715 * the user can not interact with the application; the system intercepts 23716 * touching on the screen to pop the UI out of full screen mode. See 23717 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 23718 * 23719 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 23720 * content} 23721 * 23722 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 23723 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 23724 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 23725 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 23726 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 23727 */ setSystemUiVisibility(int visibility)23728 public void setSystemUiVisibility(int visibility) { 23729 if (visibility != mSystemUiVisibility) { 23730 mSystemUiVisibility = visibility; 23731 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 23732 mParent.recomputeViewAttributes(this); 23733 } 23734 } 23735 } 23736 23737 /** 23738 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 23739 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 23740 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 23741 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 23742 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 23743 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 23744 */ getSystemUiVisibility()23745 public int getSystemUiVisibility() { 23746 return mSystemUiVisibility; 23747 } 23748 23749 /** 23750 * Returns the current system UI visibility that is currently set for 23751 * the entire window. This is the combination of the 23752 * {@link #setSystemUiVisibility(int)} values supplied by all of the 23753 * views in the window. 23754 */ getWindowSystemUiVisibility()23755 public int getWindowSystemUiVisibility() { 23756 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 23757 } 23758 23759 /** 23760 * Override to find out when the window's requested system UI visibility 23761 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 23762 * This is different from the callbacks received through 23763 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 23764 * in that this is only telling you about the local request of the window, 23765 * not the actual values applied by the system. 23766 */ onWindowSystemUiVisibilityChanged(int visible)23767 public void onWindowSystemUiVisibilityChanged(int visible) { 23768 } 23769 23770 /** 23771 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 23772 * the view hierarchy. 23773 */ dispatchWindowSystemUiVisiblityChanged(int visible)23774 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 23775 onWindowSystemUiVisibilityChanged(visible); 23776 } 23777 23778 /** 23779 * Set a listener to receive callbacks when the visibility of the system bar changes. 23780 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 23781 */ setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)23782 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 23783 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 23784 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 23785 mParent.recomputeViewAttributes(this); 23786 } 23787 } 23788 23789 /** 23790 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 23791 * the view hierarchy. 23792 */ dispatchSystemUiVisibilityChanged(int visibility)23793 public void dispatchSystemUiVisibilityChanged(int visibility) { 23794 ListenerInfo li = mListenerInfo; 23795 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 23796 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 23797 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 23798 } 23799 } 23800 updateLocalSystemUiVisibility(int localValue, int localChanges)23801 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 23802 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 23803 if (val != mSystemUiVisibility) { 23804 setSystemUiVisibility(val); 23805 return true; 23806 } 23807 return false; 23808 } 23809 23810 /** @hide */ setDisabledSystemUiVisibility(int flags)23811 public void setDisabledSystemUiVisibility(int flags) { 23812 if (mAttachInfo != null) { 23813 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 23814 mAttachInfo.mDisabledSystemUiVisibility = flags; 23815 if (mParent != null) { 23816 mParent.recomputeViewAttributes(this); 23817 } 23818 } 23819 } 23820 } 23821 23822 /** 23823 * Creates an image that the system displays during the drag and drop 23824 * operation. This is called a "drag shadow". The default implementation 23825 * for a DragShadowBuilder based on a View returns an image that has exactly the same 23826 * appearance as the given View. The default also positions the center of the drag shadow 23827 * directly under the touch point. If no View is provided (the constructor with no parameters 23828 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 23829 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the 23830 * default is an invisible drag shadow. 23831 * <p> 23832 * You are not required to use the View you provide to the constructor as the basis of the 23833 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 23834 * anything you want as the drag shadow. 23835 * </p> 23836 * <p> 23837 * You pass a DragShadowBuilder object to the system when you start the drag. The system 23838 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 23839 * size and position of the drag shadow. It uses this data to construct a 23840 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 23841 * so that your application can draw the shadow image in the Canvas. 23842 * </p> 23843 * 23844 * <div class="special reference"> 23845 * <h3>Developer Guides</h3> 23846 * <p>For a guide to implementing drag and drop features, read the 23847 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 23848 * </div> 23849 */ 23850 public static class DragShadowBuilder { 23851 private final WeakReference<View> mView; 23852 23853 /** 23854 * Constructs a shadow image builder based on a View. By default, the resulting drag 23855 * shadow will have the same appearance and dimensions as the View, with the touch point 23856 * over the center of the View. 23857 * @param view A View. Any View in scope can be used. 23858 */ DragShadowBuilder(View view)23859 public DragShadowBuilder(View view) { 23860 mView = new WeakReference<View>(view); 23861 } 23862 23863 /** 23864 * Construct a shadow builder object with no associated View. This 23865 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 23866 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 23867 * to supply the drag shadow's dimensions and appearance without 23868 * reference to any View object. 23869 */ DragShadowBuilder()23870 public DragShadowBuilder() { 23871 mView = new WeakReference<View>(null); 23872 } 23873 23874 /** 23875 * Returns the View object that had been passed to the 23876 * {@link #View.DragShadowBuilder(View)} 23877 * constructor. If that View parameter was {@code null} or if the 23878 * {@link #View.DragShadowBuilder()} 23879 * constructor was used to instantiate the builder object, this method will return 23880 * null. 23881 * 23882 * @return The View object associate with this builder object. 23883 */ 23884 @SuppressWarnings({"JavadocReference"}) getView()23885 final public View getView() { 23886 return mView.get(); 23887 } 23888 23889 /** 23890 * Provides the metrics for the shadow image. These include the dimensions of 23891 * the shadow image, and the point within that shadow that should 23892 * be centered under the touch location while dragging. 23893 * <p> 23894 * The default implementation sets the dimensions of the shadow to be the 23895 * same as the dimensions of the View itself and centers the shadow under 23896 * the touch point. 23897 * </p> 23898 * 23899 * @param outShadowSize A {@link android.graphics.Point} containing the width and height 23900 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 23901 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 23902 * image. 23903 * 23904 * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the 23905 * shadow image that should be underneath the touch point during the drag and drop 23906 * operation. Your application must set {@link android.graphics.Point#x} to the 23907 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 23908 */ onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)23909 public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { 23910 final View view = mView.get(); 23911 if (view != null) { 23912 outShadowSize.set(view.getWidth(), view.getHeight()); 23913 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2); 23914 } else { 23915 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 23916 } 23917 } 23918 23919 /** 23920 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 23921 * based on the dimensions it received from the 23922 * {@link #onProvideShadowMetrics(Point, Point)} callback. 23923 * 23924 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 23925 */ onDrawShadow(Canvas canvas)23926 public void onDrawShadow(Canvas canvas) { 23927 final View view = mView.get(); 23928 if (view != null) { 23929 view.draw(canvas); 23930 } else { 23931 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 23932 } 23933 } 23934 } 23935 23936 /** 23937 * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) 23938 * startDragAndDrop()} for newer platform versions. 23939 */ 23940 @Deprecated startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)23941 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 23942 Object myLocalState, int flags) { 23943 return startDragAndDrop(data, shadowBuilder, myLocalState, flags); 23944 } 23945 23946 /** 23947 * Starts a drag and drop operation. When your application calls this method, it passes a 23948 * {@link android.view.View.DragShadowBuilder} object to the system. The 23949 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 23950 * to get metrics for the drag shadow, and then calls the object's 23951 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 23952 * <p> 23953 * Once the system has the drag shadow, it begins the drag and drop operation by sending 23954 * drag events to all the View objects in your application that are currently visible. It does 23955 * this either by calling the View object's drag listener (an implementation of 23956 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 23957 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 23958 * Both are passed a {@link android.view.DragEvent} object that has a 23959 * {@link android.view.DragEvent#getAction()} value of 23960 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 23961 * </p> 23962 * <p> 23963 * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, 23964 * int) startDragAndDrop()} on any attached View object. The View object does not need to be 23965 * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related 23966 * to the View the user selected for dragging. 23967 * </p> 23968 * @param data A {@link android.content.ClipData} object pointing to the data to be 23969 * transferred by the drag and drop operation. 23970 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 23971 * drag shadow. 23972 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 23973 * drop operation. When dispatching drag events to views in the same activity this object 23974 * will be available through {@link android.view.DragEvent#getLocalState()}. Views in other 23975 * activities will not have access to this data ({@link android.view.DragEvent#getLocalState()} 23976 * will return null). 23977 * <p> 23978 * myLocalState is a lightweight mechanism for the sending information from the dragged View 23979 * to the target Views. For example, it can contain flags that differentiate between a 23980 * a copy operation and a move operation. 23981 * </p> 23982 * @param flags Flags that control the drag and drop operation. This can be set to 0 for no 23983 * flags, or any combination of the following: 23984 * <ul> 23985 * <li>{@link #DRAG_FLAG_GLOBAL}</li> 23986 * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li> 23987 * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> 23988 * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li> 23989 * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li> 23990 * <li>{@link #DRAG_FLAG_OPAQUE}</li> 23991 * </ul> 23992 * @return {@code true} if the method completes successfully, or 23993 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 23994 * do a drag, and so no drag operation is in progress. 23995 */ startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)23996 public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, 23997 Object myLocalState, int flags) { 23998 if (ViewDebug.DEBUG_DRAG) { 23999 Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags); 24000 } 24001 if (mAttachInfo == null) { 24002 Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view."); 24003 return false; 24004 } 24005 24006 if (data != null) { 24007 data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0); 24008 } 24009 24010 Point shadowSize = new Point(); 24011 Point shadowTouchPoint = new Point(); 24012 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 24013 24014 if ((shadowSize.x < 0) || (shadowSize.y < 0) 24015 || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 24016 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 24017 } 24018 24019 // Create 1x1 surface when zero surface size is specified because SurfaceControl.Builder 24020 // does not accept zero size surface. 24021 if (shadowSize.x == 0 || shadowSize.y == 0) { 24022 if (!sAcceptZeroSizeDragShadow) { 24023 throw new IllegalStateException("Drag shadow dimensions must be positive"); 24024 } 24025 shadowSize.x = 1; 24026 shadowSize.y = 1; 24027 } 24028 24029 if (ViewDebug.DEBUG_DRAG) { 24030 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 24031 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 24032 } 24033 if (mAttachInfo.mDragSurface != null) { 24034 mAttachInfo.mDragSurface.release(); 24035 } 24036 mAttachInfo.mDragSurface = new Surface(); 24037 mAttachInfo.mDragToken = null; 24038 24039 final ViewRootImpl root = mAttachInfo.mViewRootImpl; 24040 final SurfaceSession session = new SurfaceSession(root.mSurface); 24041 final SurfaceControl surface = new SurfaceControl.Builder(session) 24042 .setName("drag surface") 24043 .setSize(shadowSize.x, shadowSize.y) 24044 .setFormat(PixelFormat.TRANSLUCENT) 24045 .build(); 24046 try { 24047 mAttachInfo.mDragSurface.copyFrom(surface); 24048 final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 24049 try { 24050 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 24051 shadowBuilder.onDrawShadow(canvas); 24052 } finally { 24053 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 24054 } 24055 24056 // Cache the local state object for delivery with DragEvents 24057 root.setLocalDragState(myLocalState); 24058 24059 // repurpose 'shadowSize' for the last touch point 24060 root.getLastTouchPoint(shadowSize); 24061 24062 mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag( 24063 mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(), 24064 shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); 24065 if (ViewDebug.DEBUG_DRAG) { 24066 Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken); 24067 } 24068 24069 return mAttachInfo.mDragToken != null; 24070 } catch (Exception e) { 24071 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 24072 return false; 24073 } finally { 24074 if (mAttachInfo.mDragToken == null) { 24075 mAttachInfo.mDragSurface.destroy(); 24076 mAttachInfo.mDragSurface = null; 24077 root.setLocalDragState(null); 24078 } 24079 session.kill(); 24080 } 24081 } 24082 24083 /** 24084 * Cancels an ongoing drag and drop operation. 24085 * <p> 24086 * A {@link android.view.DragEvent} object with 24087 * {@link android.view.DragEvent#getAction()} value of 24088 * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and 24089 * {@link android.view.DragEvent#getResult()} value of {@code false} 24090 * will be sent to every 24091 * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED} 24092 * even if they are not currently visible. 24093 * </p> 24094 * <p> 24095 * This method can be called on any View in the same window as the View on which 24096 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop} 24097 * was called. 24098 * </p> 24099 */ cancelDragAndDrop()24100 public final void cancelDragAndDrop() { 24101 if (ViewDebug.DEBUG_DRAG) { 24102 Log.d(VIEW_LOG_TAG, "cancelDragAndDrop"); 24103 } 24104 if (mAttachInfo == null) { 24105 Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view."); 24106 return; 24107 } 24108 if (mAttachInfo.mDragToken != null) { 24109 try { 24110 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken); 24111 } catch (Exception e) { 24112 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e); 24113 } 24114 mAttachInfo.mDragToken = null; 24115 } else { 24116 Log.e(VIEW_LOG_TAG, "No active drag to cancel"); 24117 } 24118 } 24119 24120 /** 24121 * Updates the drag shadow for the ongoing drag and drop operation. 24122 * 24123 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 24124 * new drag shadow. 24125 */ updateDragShadow(DragShadowBuilder shadowBuilder)24126 public final void updateDragShadow(DragShadowBuilder shadowBuilder) { 24127 if (ViewDebug.DEBUG_DRAG) { 24128 Log.d(VIEW_LOG_TAG, "updateDragShadow"); 24129 } 24130 if (mAttachInfo == null) { 24131 Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view."); 24132 return; 24133 } 24134 if (mAttachInfo.mDragToken != null) { 24135 try { 24136 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 24137 try { 24138 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 24139 shadowBuilder.onDrawShadow(canvas); 24140 } finally { 24141 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 24142 } 24143 } catch (Exception e) { 24144 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e); 24145 } 24146 } else { 24147 Log.e(VIEW_LOG_TAG, "No active drag"); 24148 } 24149 } 24150 24151 /** 24152 * Starts a move from {startX, startY}, the amount of the movement will be the offset 24153 * between {startX, startY} and the new cursor positon. 24154 * @param startX horizontal coordinate where the move started. 24155 * @param startY vertical coordinate where the move started. 24156 * @return whether moving was started successfully. 24157 * @hide 24158 */ startMovingTask(float startX, float startY)24159 public final boolean startMovingTask(float startX, float startY) { 24160 if (ViewDebug.DEBUG_POSITIONING) { 24161 Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}"); 24162 } 24163 try { 24164 return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY); 24165 } catch (RemoteException e) { 24166 Log.e(VIEW_LOG_TAG, "Unable to start moving", e); 24167 } 24168 return false; 24169 } 24170 24171 /** 24172 * Handles drag events sent by the system following a call to 24173 * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int) 24174 * startDragAndDrop()}. 24175 *<p> 24176 * When the system calls this method, it passes a 24177 * {@link android.view.DragEvent} object. A call to 24178 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 24179 * in DragEvent. The method uses these to determine what is happening in the drag and drop 24180 * operation. 24181 * @param event The {@link android.view.DragEvent} sent by the system. 24182 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 24183 * in DragEvent, indicating the type of drag event represented by this object. 24184 * @return {@code true} if the method was successful, otherwise {@code false}. 24185 * <p> 24186 * The method should return {@code true} in response to an action type of 24187 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 24188 * operation. 24189 * </p> 24190 * <p> 24191 * The method should also return {@code true} in response to an action type of 24192 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 24193 * {@code false} if it didn't. 24194 * </p> 24195 * <p> 24196 * For all other events, the return value is ignored. 24197 * </p> 24198 */ onDragEvent(DragEvent event)24199 public boolean onDragEvent(DragEvent event) { 24200 return false; 24201 } 24202 24203 // Dispatches ACTION_DRAG_ENTERED and ACTION_DRAG_EXITED events for pre-Nougat apps. dispatchDragEnterExitInPreN(DragEvent event)24204 boolean dispatchDragEnterExitInPreN(DragEvent event) { 24205 return callDragEventHandler(event); 24206 } 24207 24208 /** 24209 * Detects if this View is enabled and has a drag event listener. 24210 * If both are true, then it calls the drag event listener with the 24211 * {@link android.view.DragEvent} it received. If the drag event listener returns 24212 * {@code true}, then dispatchDragEvent() returns {@code true}. 24213 * <p> 24214 * For all other cases, the method calls the 24215 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 24216 * method and returns its result. 24217 * </p> 24218 * <p> 24219 * This ensures that a drag event is always consumed, even if the View does not have a drag 24220 * event listener. However, if the View has a listener and the listener returns true, then 24221 * onDragEvent() is not called. 24222 * </p> 24223 */ dispatchDragEvent(DragEvent event)24224 public boolean dispatchDragEvent(DragEvent event) { 24225 event.mEventHandlerWasCalled = true; 24226 if (event.mAction == DragEvent.ACTION_DRAG_LOCATION || 24227 event.mAction == DragEvent.ACTION_DROP) { 24228 // About to deliver an event with coordinates to this view. Notify that now this view 24229 // has drag focus. This will send exit/enter events as needed. 24230 getViewRootImpl().setDragFocus(this, event); 24231 } 24232 return callDragEventHandler(event); 24233 } 24234 callDragEventHandler(DragEvent event)24235 final boolean callDragEventHandler(DragEvent event) { 24236 final boolean result; 24237 24238 ListenerInfo li = mListenerInfo; 24239 //noinspection SimplifiableIfStatement 24240 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 24241 && li.mOnDragListener.onDrag(this, event)) { 24242 result = true; 24243 } else { 24244 result = onDragEvent(event); 24245 } 24246 24247 switch (event.mAction) { 24248 case DragEvent.ACTION_DRAG_ENTERED: { 24249 mPrivateFlags2 |= View.PFLAG2_DRAG_HOVERED; 24250 refreshDrawableState(); 24251 } break; 24252 case DragEvent.ACTION_DRAG_EXITED: { 24253 mPrivateFlags2 &= ~View.PFLAG2_DRAG_HOVERED; 24254 refreshDrawableState(); 24255 } break; 24256 case DragEvent.ACTION_DRAG_ENDED: { 24257 mPrivateFlags2 &= ~View.DRAG_MASK; 24258 refreshDrawableState(); 24259 } break; 24260 } 24261 24262 return result; 24263 } 24264 canAcceptDrag()24265 boolean canAcceptDrag() { 24266 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 24267 } 24268 24269 /** 24270 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 24271 * it is ever exposed at all. 24272 * @hide 24273 */ onCloseSystemDialogs(String reason)24274 public void onCloseSystemDialogs(String reason) { 24275 } 24276 24277 /** 24278 * Given a Drawable whose bounds have been set to draw into this view, 24279 * update a Region being computed for 24280 * {@link #gatherTransparentRegion(android.graphics.Region)} so 24281 * that any non-transparent parts of the Drawable are removed from the 24282 * given transparent region. 24283 * 24284 * @param dr The Drawable whose transparency is to be applied to the region. 24285 * @param region A Region holding the current transparency information, 24286 * where any parts of the region that are set are considered to be 24287 * transparent. On return, this region will be modified to have the 24288 * transparency information reduced by the corresponding parts of the 24289 * Drawable that are not transparent. 24290 * {@hide} 24291 */ applyDrawableToTransparentRegion(Drawable dr, Region region)24292 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 24293 if (DBG) { 24294 Log.i("View", "Getting transparent region for: " + this); 24295 } 24296 final Region r = dr.getTransparentRegion(); 24297 final Rect db = dr.getBounds(); 24298 final AttachInfo attachInfo = mAttachInfo; 24299 if (r != null && attachInfo != null) { 24300 final int w = getRight()-getLeft(); 24301 final int h = getBottom()-getTop(); 24302 if (db.left > 0) { 24303 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 24304 r.op(0, 0, db.left, h, Region.Op.UNION); 24305 } 24306 if (db.right < w) { 24307 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 24308 r.op(db.right, 0, w, h, Region.Op.UNION); 24309 } 24310 if (db.top > 0) { 24311 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 24312 r.op(0, 0, w, db.top, Region.Op.UNION); 24313 } 24314 if (db.bottom < h) { 24315 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 24316 r.op(0, db.bottom, w, h, Region.Op.UNION); 24317 } 24318 final int[] location = attachInfo.mTransparentLocation; 24319 getLocationInWindow(location); 24320 r.translate(location[0], location[1]); 24321 region.op(r, Region.Op.INTERSECT); 24322 } else { 24323 region.op(db, Region.Op.DIFFERENCE); 24324 } 24325 } 24326 checkForLongClick(int delayOffset, float x, float y)24327 private void checkForLongClick(int delayOffset, float x, float y) { 24328 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) { 24329 mHasPerformedLongPress = false; 24330 24331 if (mPendingCheckForLongPress == null) { 24332 mPendingCheckForLongPress = new CheckForLongPress(); 24333 } 24334 mPendingCheckForLongPress.setAnchor(x, y); 24335 mPendingCheckForLongPress.rememberWindowAttachCount(); 24336 mPendingCheckForLongPress.rememberPressedState(); 24337 postDelayed(mPendingCheckForLongPress, 24338 ViewConfiguration.getLongPressTimeout() - delayOffset); 24339 } 24340 } 24341 24342 /** 24343 * Inflate a view from an XML resource. This convenience method wraps the {@link 24344 * LayoutInflater} class, which provides a full range of options for view inflation. 24345 * 24346 * @param context The Context object for your activity or application. 24347 * @param resource The resource ID to inflate 24348 * @param root A view group that will be the parent. Used to properly inflate the 24349 * layout_* parameters. 24350 * @see LayoutInflater 24351 */ inflate(Context context, @LayoutRes int resource, ViewGroup root)24352 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { 24353 LayoutInflater factory = LayoutInflater.from(context); 24354 return factory.inflate(resource, root); 24355 } 24356 24357 /** 24358 * Scroll the view with standard behavior for scrolling beyond the normal 24359 * content boundaries. Views that call this method should override 24360 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 24361 * results of an over-scroll operation. 24362 * 24363 * Views can use this method to handle any touch or fling-based scrolling. 24364 * 24365 * @param deltaX Change in X in pixels 24366 * @param deltaY Change in Y in pixels 24367 * @param scrollX Current X scroll value in pixels before applying deltaX 24368 * @param scrollY Current Y scroll value in pixels before applying deltaY 24369 * @param scrollRangeX Maximum content scroll range along the X axis 24370 * @param scrollRangeY Maximum content scroll range along the Y axis 24371 * @param maxOverScrollX Number of pixels to overscroll by in either direction 24372 * along the X axis. 24373 * @param maxOverScrollY Number of pixels to overscroll by in either direction 24374 * along the Y axis. 24375 * @param isTouchEvent true if this scroll operation is the result of a touch event. 24376 * @return true if scrolling was clamped to an over-scroll boundary along either 24377 * axis, false otherwise. 24378 */ 24379 @SuppressWarnings({"UnusedParameters"}) overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)24380 protected boolean overScrollBy(int deltaX, int deltaY, 24381 int scrollX, int scrollY, 24382 int scrollRangeX, int scrollRangeY, 24383 int maxOverScrollX, int maxOverScrollY, 24384 boolean isTouchEvent) { 24385 final int overScrollMode = mOverScrollMode; 24386 final boolean canScrollHorizontal = 24387 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 24388 final boolean canScrollVertical = 24389 computeVerticalScrollRange() > computeVerticalScrollExtent(); 24390 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 24391 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 24392 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 24393 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 24394 24395 int newScrollX = scrollX + deltaX; 24396 if (!overScrollHorizontal) { 24397 maxOverScrollX = 0; 24398 } 24399 24400 int newScrollY = scrollY + deltaY; 24401 if (!overScrollVertical) { 24402 maxOverScrollY = 0; 24403 } 24404 24405 // Clamp values if at the limits and record 24406 final int left = -maxOverScrollX; 24407 final int right = maxOverScrollX + scrollRangeX; 24408 final int top = -maxOverScrollY; 24409 final int bottom = maxOverScrollY + scrollRangeY; 24410 24411 boolean clampedX = false; 24412 if (newScrollX > right) { 24413 newScrollX = right; 24414 clampedX = true; 24415 } else if (newScrollX < left) { 24416 newScrollX = left; 24417 clampedX = true; 24418 } 24419 24420 boolean clampedY = false; 24421 if (newScrollY > bottom) { 24422 newScrollY = bottom; 24423 clampedY = true; 24424 } else if (newScrollY < top) { 24425 newScrollY = top; 24426 clampedY = true; 24427 } 24428 24429 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 24430 24431 return clampedX || clampedY; 24432 } 24433 24434 /** 24435 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 24436 * respond to the results of an over-scroll operation. 24437 * 24438 * @param scrollX New X scroll value in pixels 24439 * @param scrollY New Y scroll value in pixels 24440 * @param clampedX True if scrollX was clamped to an over-scroll boundary 24441 * @param clampedY True if scrollY was clamped to an over-scroll boundary 24442 */ onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)24443 protected void onOverScrolled(int scrollX, int scrollY, 24444 boolean clampedX, boolean clampedY) { 24445 // Intentionally empty. 24446 } 24447 24448 /** 24449 * Returns the over-scroll mode for this view. The result will be 24450 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 24451 * (allow over-scrolling only if the view content is larger than the container), 24452 * or {@link #OVER_SCROLL_NEVER}. 24453 * 24454 * @return This view's over-scroll mode. 24455 */ getOverScrollMode()24456 public int getOverScrollMode() { 24457 return mOverScrollMode; 24458 } 24459 24460 /** 24461 * Set the over-scroll mode for this view. Valid over-scroll modes are 24462 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 24463 * (allow over-scrolling only if the view content is larger than the container), 24464 * or {@link #OVER_SCROLL_NEVER}. 24465 * 24466 * Setting the over-scroll mode of a view will have an effect only if the 24467 * view is capable of scrolling. 24468 * 24469 * @param overScrollMode The new over-scroll mode for this view. 24470 */ setOverScrollMode(int overScrollMode)24471 public void setOverScrollMode(int overScrollMode) { 24472 if (overScrollMode != OVER_SCROLL_ALWAYS && 24473 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 24474 overScrollMode != OVER_SCROLL_NEVER) { 24475 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 24476 } 24477 mOverScrollMode = overScrollMode; 24478 } 24479 24480 /** 24481 * Enable or disable nested scrolling for this view. 24482 * 24483 * <p>If this property is set to true the view will be permitted to initiate nested 24484 * scrolling operations with a compatible parent view in the current hierarchy. If this 24485 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling 24486 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping} 24487 * the nested scroll.</p> 24488 * 24489 * @param enabled true to enable nested scrolling, false to disable 24490 * 24491 * @see #isNestedScrollingEnabled() 24492 */ setNestedScrollingEnabled(boolean enabled)24493 public void setNestedScrollingEnabled(boolean enabled) { 24494 if (enabled) { 24495 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED; 24496 } else { 24497 stopNestedScroll(); 24498 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED; 24499 } 24500 } 24501 24502 /** 24503 * Returns true if nested scrolling is enabled for this view. 24504 * 24505 * <p>If nested scrolling is enabled and this View class implementation supports it, 24506 * this view will act as a nested scrolling child view when applicable, forwarding data 24507 * about the scroll operation in progress to a compatible and cooperating nested scrolling 24508 * parent.</p> 24509 * 24510 * @return true if nested scrolling is enabled 24511 * 24512 * @see #setNestedScrollingEnabled(boolean) 24513 */ isNestedScrollingEnabled()24514 public boolean isNestedScrollingEnabled() { 24515 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) == 24516 PFLAG3_NESTED_SCROLLING_ENABLED; 24517 } 24518 24519 /** 24520 * Begin a nestable scroll operation along the given axes. 24521 * 24522 * <p>A view starting a nested scroll promises to abide by the following contract:</p> 24523 * 24524 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case 24525 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}. 24526 * In the case of touch scrolling the nested scroll will be terminated automatically in 24527 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}. 24528 * In the event of programmatic scrolling the caller must explicitly call 24529 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p> 24530 * 24531 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found. 24532 * If it returns false the caller may ignore the rest of this contract until the next scroll. 24533 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p> 24534 * 24535 * <p>At each incremental step of the scroll the caller should invoke 24536 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} 24537 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling 24538 * parent at least partially consumed the scroll and the caller should adjust the amount it 24539 * scrolls by.</p> 24540 * 24541 * <p>After applying the remainder of the scroll delta the caller should invoke 24542 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing 24543 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat 24544 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}. 24545 * </p> 24546 * 24547 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or 24548 * {@link #SCROLL_AXIS_VERTICAL}. 24549 * @return true if a cooperative parent was found and nested scrolling has been enabled for 24550 * the current gesture. 24551 * 24552 * @see #stopNestedScroll() 24553 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 24554 * @see #dispatchNestedScroll(int, int, int, int, int[]) 24555 */ startNestedScroll(int axes)24556 public boolean startNestedScroll(int axes) { 24557 if (hasNestedScrollingParent()) { 24558 // Already in progress 24559 return true; 24560 } 24561 if (isNestedScrollingEnabled()) { 24562 ViewParent p = getParent(); 24563 View child = this; 24564 while (p != null) { 24565 try { 24566 if (p.onStartNestedScroll(child, this, axes)) { 24567 mNestedScrollingParent = p; 24568 p.onNestedScrollAccepted(child, this, axes); 24569 return true; 24570 } 24571 } catch (AbstractMethodError e) { 24572 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " + 24573 "method onStartNestedScroll", e); 24574 // Allow the search upward to continue 24575 } 24576 if (p instanceof View) { 24577 child = (View) p; 24578 } 24579 p = p.getParent(); 24580 } 24581 } 24582 return false; 24583 } 24584 24585 /** 24586 * Stop a nested scroll in progress. 24587 * 24588 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p> 24589 * 24590 * @see #startNestedScroll(int) 24591 */ stopNestedScroll()24592 public void stopNestedScroll() { 24593 if (mNestedScrollingParent != null) { 24594 mNestedScrollingParent.onStopNestedScroll(this); 24595 mNestedScrollingParent = null; 24596 } 24597 } 24598 24599 /** 24600 * Returns true if this view has a nested scrolling parent. 24601 * 24602 * <p>The presence of a nested scrolling parent indicates that this view has initiated 24603 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p> 24604 * 24605 * @return whether this view has a nested scrolling parent 24606 */ hasNestedScrollingParent()24607 public boolean hasNestedScrollingParent() { 24608 return mNestedScrollingParent != null; 24609 } 24610 24611 /** 24612 * Dispatch one step of a nested scroll in progress. 24613 * 24614 * <p>Implementations of views that support nested scrolling should call this to report 24615 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll 24616 * is not currently in progress or nested scrolling is not 24617 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p> 24618 * 24619 * <p>Compatible View implementations should also call 24620 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before 24621 * consuming a component of the scroll event themselves.</p> 24622 * 24623 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step 24624 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step 24625 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view 24626 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view 24627 * @param offsetInWindow Optional. If not null, on return this will contain the offset 24628 * in local view coordinates of this view from before this operation 24629 * to after it completes. View implementations may use this to adjust 24630 * expected input coordinate tracking. 24631 * @return true if the event was dispatched, false if it could not be dispatched. 24632 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 24633 */ dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)24634 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 24635 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) { 24636 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 24637 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 24638 int startX = 0; 24639 int startY = 0; 24640 if (offsetInWindow != null) { 24641 getLocationInWindow(offsetInWindow); 24642 startX = offsetInWindow[0]; 24643 startY = offsetInWindow[1]; 24644 } 24645 24646 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed, 24647 dxUnconsumed, dyUnconsumed); 24648 24649 if (offsetInWindow != null) { 24650 getLocationInWindow(offsetInWindow); 24651 offsetInWindow[0] -= startX; 24652 offsetInWindow[1] -= startY; 24653 } 24654 return true; 24655 } else if (offsetInWindow != null) { 24656 // No motion, no dispatch. Keep offsetInWindow up to date. 24657 offsetInWindow[0] = 0; 24658 offsetInWindow[1] = 0; 24659 } 24660 } 24661 return false; 24662 } 24663 24664 /** 24665 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it. 24666 * 24667 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch. 24668 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested 24669 * scrolling operation to consume some or all of the scroll operation before the child view 24670 * consumes it.</p> 24671 * 24672 * @param dx Horizontal scroll distance in pixels 24673 * @param dy Vertical scroll distance in pixels 24674 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx 24675 * and consumed[1] the consumed dy. 24676 * @param offsetInWindow Optional. If not null, on return this will contain the offset 24677 * in local view coordinates of this view from before this operation 24678 * to after it completes. View implementations may use this to adjust 24679 * expected input coordinate tracking. 24680 * @return true if the parent consumed some or all of the scroll delta 24681 * @see #dispatchNestedScroll(int, int, int, int, int[]) 24682 */ dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)24683 public boolean dispatchNestedPreScroll(int dx, int dy, 24684 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) { 24685 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 24686 if (dx != 0 || dy != 0) { 24687 int startX = 0; 24688 int startY = 0; 24689 if (offsetInWindow != null) { 24690 getLocationInWindow(offsetInWindow); 24691 startX = offsetInWindow[0]; 24692 startY = offsetInWindow[1]; 24693 } 24694 24695 if (consumed == null) { 24696 if (mTempNestedScrollConsumed == null) { 24697 mTempNestedScrollConsumed = new int[2]; 24698 } 24699 consumed = mTempNestedScrollConsumed; 24700 } 24701 consumed[0] = 0; 24702 consumed[1] = 0; 24703 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed); 24704 24705 if (offsetInWindow != null) { 24706 getLocationInWindow(offsetInWindow); 24707 offsetInWindow[0] -= startX; 24708 offsetInWindow[1] -= startY; 24709 } 24710 return consumed[0] != 0 || consumed[1] != 0; 24711 } else if (offsetInWindow != null) { 24712 offsetInWindow[0] = 0; 24713 offsetInWindow[1] = 0; 24714 } 24715 } 24716 return false; 24717 } 24718 24719 /** 24720 * Dispatch a fling to a nested scrolling parent. 24721 * 24722 * <p>This method should be used to indicate that a nested scrolling child has detected 24723 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a 24724 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 24725 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 24726 * along a scrollable axis.</p> 24727 * 24728 * <p>If a nested scrolling child view would normally fling but it is at the edge of 24729 * its own content, it can use this method to delegate the fling to its nested scrolling 24730 * parent instead. The parent may optionally consume the fling or observe a child fling.</p> 24731 * 24732 * @param velocityX Horizontal fling velocity in pixels per second 24733 * @param velocityY Vertical fling velocity in pixels per second 24734 * @param consumed true if the child consumed the fling, false otherwise 24735 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling 24736 */ dispatchNestedFling(float velocityX, float velocityY, boolean consumed)24737 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 24738 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 24739 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed); 24740 } 24741 return false; 24742 } 24743 24744 /** 24745 * Dispatch a fling to a nested scrolling parent before it is processed by this view. 24746 * 24747 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch 24748 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code> 24749 * offsets an opportunity for the parent view in a nested fling to fully consume the fling 24750 * before the child view consumes it. If this method returns <code>true</code>, a nested 24751 * parent view consumed the fling and this view should not scroll as a result.</p> 24752 * 24753 * <p>For a better user experience, only one view in a nested scrolling chain should consume 24754 * the fling at a time. If a parent view consumed the fling this method will return false. 24755 * Custom view implementations should account for this in two ways:</p> 24756 * 24757 * <ul> 24758 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not 24759 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid 24760 * position regardless.</li> 24761 * <li>If a nested parent does consume the fling, this view should not scroll at all, 24762 * even to settle back to a valid idle position.</li> 24763 * </ul> 24764 * 24765 * <p>Views should also not offer fling velocities to nested parent views along an axis 24766 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView} 24767 * should not offer a horizontal fling velocity to its parents since scrolling along that 24768 * axis is not permitted and carrying velocity along that motion does not make sense.</p> 24769 * 24770 * @param velocityX Horizontal fling velocity in pixels per second 24771 * @param velocityY Vertical fling velocity in pixels per second 24772 * @return true if a nested scrolling parent consumed the fling 24773 */ dispatchNestedPreFling(float velocityX, float velocityY)24774 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 24775 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 24776 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY); 24777 } 24778 return false; 24779 } 24780 24781 /** 24782 * Gets a scale factor that determines the distance the view should scroll 24783 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 24784 * @return The vertical scroll scale factor. 24785 * @hide 24786 */ getVerticalScrollFactor()24787 protected float getVerticalScrollFactor() { 24788 if (mVerticalScrollFactor == 0) { 24789 TypedValue outValue = new TypedValue(); 24790 if (!mContext.getTheme().resolveAttribute( 24791 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 24792 throw new IllegalStateException( 24793 "Expected theme to define listPreferredItemHeight."); 24794 } 24795 mVerticalScrollFactor = outValue.getDimension( 24796 mContext.getResources().getDisplayMetrics()); 24797 } 24798 return mVerticalScrollFactor; 24799 } 24800 24801 /** 24802 * Gets a scale factor that determines the distance the view should scroll 24803 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 24804 * @return The horizontal scroll scale factor. 24805 * @hide 24806 */ getHorizontalScrollFactor()24807 protected float getHorizontalScrollFactor() { 24808 // TODO: Should use something else. 24809 return getVerticalScrollFactor(); 24810 } 24811 24812 /** 24813 * Return the value specifying the text direction or policy that was set with 24814 * {@link #setTextDirection(int)}. 24815 * 24816 * @return the defined text direction. It can be one of: 24817 * 24818 * {@link #TEXT_DIRECTION_INHERIT}, 24819 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 24820 * {@link #TEXT_DIRECTION_ANY_RTL}, 24821 * {@link #TEXT_DIRECTION_LTR}, 24822 * {@link #TEXT_DIRECTION_RTL}, 24823 * {@link #TEXT_DIRECTION_LOCALE}, 24824 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 24825 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 24826 * 24827 * @attr ref android.R.styleable#View_textDirection 24828 * 24829 * @hide 24830 */ 24831 @ViewDebug.ExportedProperty(category = "text", mapping = { 24832 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 24833 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 24834 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 24835 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 24836 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 24837 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 24838 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 24839 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 24840 }) getRawTextDirection()24841 public int getRawTextDirection() { 24842 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 24843 } 24844 24845 /** 24846 * Set the text direction. 24847 * 24848 * @param textDirection the direction to set. Should be one of: 24849 * 24850 * {@link #TEXT_DIRECTION_INHERIT}, 24851 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 24852 * {@link #TEXT_DIRECTION_ANY_RTL}, 24853 * {@link #TEXT_DIRECTION_LTR}, 24854 * {@link #TEXT_DIRECTION_RTL}, 24855 * {@link #TEXT_DIRECTION_LOCALE} 24856 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 24857 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}, 24858 * 24859 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 24860 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 24861 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 24862 * 24863 * @attr ref android.R.styleable#View_textDirection 24864 */ setTextDirection(int textDirection)24865 public void setTextDirection(int textDirection) { 24866 if (getRawTextDirection() != textDirection) { 24867 // Reset the current text direction and the resolved one 24868 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 24869 resetResolvedTextDirection(); 24870 // Set the new text direction 24871 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 24872 // Do resolution 24873 resolveTextDirection(); 24874 // Notify change 24875 onRtlPropertiesChanged(getLayoutDirection()); 24876 // Refresh 24877 requestLayout(); 24878 invalidate(true); 24879 } 24880 } 24881 24882 /** 24883 * Return the resolved text direction. 24884 * 24885 * @return the resolved text direction. Returns one of: 24886 * 24887 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 24888 * {@link #TEXT_DIRECTION_ANY_RTL}, 24889 * {@link #TEXT_DIRECTION_LTR}, 24890 * {@link #TEXT_DIRECTION_RTL}, 24891 * {@link #TEXT_DIRECTION_LOCALE}, 24892 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 24893 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 24894 * 24895 * @attr ref android.R.styleable#View_textDirection 24896 */ 24897 @ViewDebug.ExportedProperty(category = "text", mapping = { 24898 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 24899 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 24900 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 24901 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 24902 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 24903 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 24904 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 24905 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 24906 }) getTextDirection()24907 public int getTextDirection() { 24908 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 24909 } 24910 24911 /** 24912 * Resolve the text direction. 24913 * 24914 * @return true if resolution has been done, false otherwise. 24915 * 24916 * @hide 24917 */ resolveTextDirection()24918 public boolean resolveTextDirection() { 24919 // Reset any previous text direction resolution 24920 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 24921 24922 if (hasRtlSupport()) { 24923 // Set resolved text direction flag depending on text direction flag 24924 final int textDirection = getRawTextDirection(); 24925 switch(textDirection) { 24926 case TEXT_DIRECTION_INHERIT: 24927 if (!canResolveTextDirection()) { 24928 // We cannot do the resolution if there is no parent, so use the default one 24929 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24930 // Resolution will need to happen again later 24931 return false; 24932 } 24933 24934 // Parent has not yet resolved, so we still return the default 24935 try { 24936 if (!mParent.isTextDirectionResolved()) { 24937 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24938 // Resolution will need to happen again later 24939 return false; 24940 } 24941 } catch (AbstractMethodError e) { 24942 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 24943 " does not fully implement ViewParent", e); 24944 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 24945 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24946 return true; 24947 } 24948 24949 // Set current resolved direction to the same value as the parent's one 24950 int parentResolvedDirection; 24951 try { 24952 parentResolvedDirection = mParent.getTextDirection(); 24953 } catch (AbstractMethodError e) { 24954 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 24955 " does not fully implement ViewParent", e); 24956 parentResolvedDirection = TEXT_DIRECTION_LTR; 24957 } 24958 switch (parentResolvedDirection) { 24959 case TEXT_DIRECTION_FIRST_STRONG: 24960 case TEXT_DIRECTION_ANY_RTL: 24961 case TEXT_DIRECTION_LTR: 24962 case TEXT_DIRECTION_RTL: 24963 case TEXT_DIRECTION_LOCALE: 24964 case TEXT_DIRECTION_FIRST_STRONG_LTR: 24965 case TEXT_DIRECTION_FIRST_STRONG_RTL: 24966 mPrivateFlags2 |= 24967 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 24968 break; 24969 default: 24970 // Default resolved direction is "first strong" heuristic 24971 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24972 } 24973 break; 24974 case TEXT_DIRECTION_FIRST_STRONG: 24975 case TEXT_DIRECTION_ANY_RTL: 24976 case TEXT_DIRECTION_LTR: 24977 case TEXT_DIRECTION_RTL: 24978 case TEXT_DIRECTION_LOCALE: 24979 case TEXT_DIRECTION_FIRST_STRONG_LTR: 24980 case TEXT_DIRECTION_FIRST_STRONG_RTL: 24981 // Resolved direction is the same as text direction 24982 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 24983 break; 24984 default: 24985 // Default resolved direction is "first strong" heuristic 24986 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24987 } 24988 } else { 24989 // Default resolved direction is "first strong" heuristic 24990 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 24991 } 24992 24993 // Set to resolved 24994 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 24995 return true; 24996 } 24997 24998 /** 24999 * Check if text direction resolution can be done. 25000 * 25001 * @return true if text direction resolution can be done otherwise return false. 25002 */ canResolveTextDirection()25003 public boolean canResolveTextDirection() { 25004 switch (getRawTextDirection()) { 25005 case TEXT_DIRECTION_INHERIT: 25006 if (mParent != null) { 25007 try { 25008 return mParent.canResolveTextDirection(); 25009 } catch (AbstractMethodError e) { 25010 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 25011 " does not fully implement ViewParent", e); 25012 } 25013 } 25014 return false; 25015 25016 default: 25017 return true; 25018 } 25019 } 25020 25021 /** 25022 * Reset resolved text direction. Text direction will be resolved during a call to 25023 * {@link #onMeasure(int, int)}. 25024 * 25025 * @hide 25026 */ resetResolvedTextDirection()25027 public void resetResolvedTextDirection() { 25028 // Reset any previous text direction resolution 25029 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 25030 // Set to default value 25031 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 25032 } 25033 25034 /** 25035 * @return true if text direction is inherited. 25036 * 25037 * @hide 25038 */ isTextDirectionInherited()25039 public boolean isTextDirectionInherited() { 25040 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 25041 } 25042 25043 /** 25044 * @return true if text direction is resolved. 25045 */ isTextDirectionResolved()25046 public boolean isTextDirectionResolved() { 25047 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 25048 } 25049 25050 /** 25051 * Return the value specifying the text alignment or policy that was set with 25052 * {@link #setTextAlignment(int)}. 25053 * 25054 * @return the defined text alignment. It can be one of: 25055 * 25056 * {@link #TEXT_ALIGNMENT_INHERIT}, 25057 * {@link #TEXT_ALIGNMENT_GRAVITY}, 25058 * {@link #TEXT_ALIGNMENT_CENTER}, 25059 * {@link #TEXT_ALIGNMENT_TEXT_START}, 25060 * {@link #TEXT_ALIGNMENT_TEXT_END}, 25061 * {@link #TEXT_ALIGNMENT_VIEW_START}, 25062 * {@link #TEXT_ALIGNMENT_VIEW_END} 25063 * 25064 * @attr ref android.R.styleable#View_textAlignment 25065 * 25066 * @hide 25067 */ 25068 @ViewDebug.ExportedProperty(category = "text", mapping = { 25069 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 25070 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 25071 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 25072 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 25073 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 25074 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 25075 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 25076 }) 25077 @TextAlignment getRawTextAlignment()25078 public int getRawTextAlignment() { 25079 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 25080 } 25081 25082 /** 25083 * Set the text alignment. 25084 * 25085 * @param textAlignment The text alignment to set. Should be one of 25086 * 25087 * {@link #TEXT_ALIGNMENT_INHERIT}, 25088 * {@link #TEXT_ALIGNMENT_GRAVITY}, 25089 * {@link #TEXT_ALIGNMENT_CENTER}, 25090 * {@link #TEXT_ALIGNMENT_TEXT_START}, 25091 * {@link #TEXT_ALIGNMENT_TEXT_END}, 25092 * {@link #TEXT_ALIGNMENT_VIEW_START}, 25093 * {@link #TEXT_ALIGNMENT_VIEW_END} 25094 * 25095 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 25096 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 25097 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 25098 * 25099 * @attr ref android.R.styleable#View_textAlignment 25100 */ setTextAlignment(@extAlignment int textAlignment)25101 public void setTextAlignment(@TextAlignment int textAlignment) { 25102 if (textAlignment != getRawTextAlignment()) { 25103 // Reset the current and resolved text alignment 25104 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 25105 resetResolvedTextAlignment(); 25106 // Set the new text alignment 25107 mPrivateFlags2 |= 25108 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 25109 // Do resolution 25110 resolveTextAlignment(); 25111 // Notify change 25112 onRtlPropertiesChanged(getLayoutDirection()); 25113 // Refresh 25114 requestLayout(); 25115 invalidate(true); 25116 } 25117 } 25118 25119 /** 25120 * Return the resolved text alignment. 25121 * 25122 * @return the resolved text alignment. Returns one of: 25123 * 25124 * {@link #TEXT_ALIGNMENT_GRAVITY}, 25125 * {@link #TEXT_ALIGNMENT_CENTER}, 25126 * {@link #TEXT_ALIGNMENT_TEXT_START}, 25127 * {@link #TEXT_ALIGNMENT_TEXT_END}, 25128 * {@link #TEXT_ALIGNMENT_VIEW_START}, 25129 * {@link #TEXT_ALIGNMENT_VIEW_END} 25130 * 25131 * @attr ref android.R.styleable#View_textAlignment 25132 */ 25133 @ViewDebug.ExportedProperty(category = "text", mapping = { 25134 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 25135 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 25136 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 25137 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 25138 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 25139 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 25140 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 25141 }) 25142 @TextAlignment getTextAlignment()25143 public int getTextAlignment() { 25144 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 25145 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 25146 } 25147 25148 /** 25149 * Resolve the text alignment. 25150 * 25151 * @return true if resolution has been done, false otherwise. 25152 * 25153 * @hide 25154 */ resolveTextAlignment()25155 public boolean resolveTextAlignment() { 25156 // Reset any previous text alignment resolution 25157 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 25158 25159 if (hasRtlSupport()) { 25160 // Set resolved text alignment flag depending on text alignment flag 25161 final int textAlignment = getRawTextAlignment(); 25162 switch (textAlignment) { 25163 case TEXT_ALIGNMENT_INHERIT: 25164 // Check if we can resolve the text alignment 25165 if (!canResolveTextAlignment()) { 25166 // We cannot do the resolution if there is no parent so use the default 25167 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25168 // Resolution will need to happen again later 25169 return false; 25170 } 25171 25172 // Parent has not yet resolved, so we still return the default 25173 try { 25174 if (!mParent.isTextAlignmentResolved()) { 25175 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25176 // Resolution will need to happen again later 25177 return false; 25178 } 25179 } catch (AbstractMethodError e) { 25180 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 25181 " does not fully implement ViewParent", e); 25182 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 25183 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25184 return true; 25185 } 25186 25187 int parentResolvedTextAlignment; 25188 try { 25189 parentResolvedTextAlignment = mParent.getTextAlignment(); 25190 } catch (AbstractMethodError e) { 25191 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 25192 " does not fully implement ViewParent", e); 25193 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 25194 } 25195 switch (parentResolvedTextAlignment) { 25196 case TEXT_ALIGNMENT_GRAVITY: 25197 case TEXT_ALIGNMENT_TEXT_START: 25198 case TEXT_ALIGNMENT_TEXT_END: 25199 case TEXT_ALIGNMENT_CENTER: 25200 case TEXT_ALIGNMENT_VIEW_START: 25201 case TEXT_ALIGNMENT_VIEW_END: 25202 // Resolved text alignment is the same as the parent resolved 25203 // text alignment 25204 mPrivateFlags2 |= 25205 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 25206 break; 25207 default: 25208 // Use default resolved text alignment 25209 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25210 } 25211 break; 25212 case TEXT_ALIGNMENT_GRAVITY: 25213 case TEXT_ALIGNMENT_TEXT_START: 25214 case TEXT_ALIGNMENT_TEXT_END: 25215 case TEXT_ALIGNMENT_CENTER: 25216 case TEXT_ALIGNMENT_VIEW_START: 25217 case TEXT_ALIGNMENT_VIEW_END: 25218 // Resolved text alignment is the same as text alignment 25219 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 25220 break; 25221 default: 25222 // Use default resolved text alignment 25223 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25224 } 25225 } else { 25226 // Use default resolved text alignment 25227 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25228 } 25229 25230 // Set the resolved 25231 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 25232 return true; 25233 } 25234 25235 /** 25236 * Check if text alignment resolution can be done. 25237 * 25238 * @return true if text alignment resolution can be done otherwise return false. 25239 */ canResolveTextAlignment()25240 public boolean canResolveTextAlignment() { 25241 switch (getRawTextAlignment()) { 25242 case TEXT_DIRECTION_INHERIT: 25243 if (mParent != null) { 25244 try { 25245 return mParent.canResolveTextAlignment(); 25246 } catch (AbstractMethodError e) { 25247 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 25248 " does not fully implement ViewParent", e); 25249 } 25250 } 25251 return false; 25252 25253 default: 25254 return true; 25255 } 25256 } 25257 25258 /** 25259 * Reset resolved text alignment. Text alignment will be resolved during a call to 25260 * {@link #onMeasure(int, int)}. 25261 * 25262 * @hide 25263 */ resetResolvedTextAlignment()25264 public void resetResolvedTextAlignment() { 25265 // Reset any previous text alignment resolution 25266 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 25267 // Set to default 25268 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 25269 } 25270 25271 /** 25272 * @return true if text alignment is inherited. 25273 * 25274 * @hide 25275 */ isTextAlignmentInherited()25276 public boolean isTextAlignmentInherited() { 25277 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 25278 } 25279 25280 /** 25281 * @return true if text alignment is resolved. 25282 */ isTextAlignmentResolved()25283 public boolean isTextAlignmentResolved() { 25284 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 25285 } 25286 25287 /** 25288 * Generate a value suitable for use in {@link #setId(int)}. 25289 * This value will not collide with ID values generated at build time by aapt for R.id. 25290 * 25291 * @return a generated ID value 25292 */ generateViewId()25293 public static int generateViewId() { 25294 for (;;) { 25295 final int result = sNextGeneratedId.get(); 25296 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 25297 int newValue = result + 1; 25298 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 25299 if (sNextGeneratedId.compareAndSet(result, newValue)) { 25300 return result; 25301 } 25302 } 25303 } 25304 isViewIdGenerated(int id)25305 private static boolean isViewIdGenerated(int id) { 25306 return (id & 0xFF000000) == 0 && (id & 0x00FFFFFF) != 0; 25307 } 25308 25309 /** 25310 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. 25311 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and 25312 * a normal View or a ViewGroup with 25313 * {@link android.view.ViewGroup#isTransitionGroup()} true. 25314 * @hide 25315 */ captureTransitioningViews(List<View> transitioningViews)25316 public void captureTransitioningViews(List<View> transitioningViews) { 25317 if (getVisibility() == View.VISIBLE) { 25318 transitioningViews.add(this); 25319 } 25320 } 25321 25322 /** 25323 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements. 25324 * @param namedElements Will contain all Views in the hierarchy having a transitionName. 25325 * @hide 25326 */ findNamedViews(Map<String, View> namedElements)25327 public void findNamedViews(Map<String, View> namedElements) { 25328 if (getVisibility() == VISIBLE || mGhostView != null) { 25329 String transitionName = getTransitionName(); 25330 if (transitionName != null) { 25331 namedElements.put(transitionName, this); 25332 } 25333 } 25334 } 25335 25336 /** 25337 * Returns the pointer icon for the motion event, or null if it doesn't specify the icon. 25338 * The default implementation does not care the location or event types, but some subclasses 25339 * may use it (such as WebViews). 25340 * @param event The MotionEvent from a mouse 25341 * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}. 25342 * This will be between 0 and {@link MotionEvent#getPointerCount()}. 25343 * @see PointerIcon 25344 */ onResolvePointerIcon(MotionEvent event, int pointerIndex)25345 public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { 25346 final float x = event.getX(pointerIndex); 25347 final float y = event.getY(pointerIndex); 25348 if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) { 25349 return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW); 25350 } 25351 return mPointerIcon; 25352 } 25353 25354 /** 25355 * Set the pointer icon for the current view. 25356 * Passing {@code null} will restore the pointer icon to its default value. 25357 * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers. 25358 */ setPointerIcon(PointerIcon pointerIcon)25359 public void setPointerIcon(PointerIcon pointerIcon) { 25360 mPointerIcon = pointerIcon; 25361 if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) { 25362 return; 25363 } 25364 try { 25365 mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow); 25366 } catch (RemoteException e) { 25367 } 25368 } 25369 25370 /** 25371 * Gets the pointer icon for the current view. 25372 */ getPointerIcon()25373 public PointerIcon getPointerIcon() { 25374 return mPointerIcon; 25375 } 25376 25377 /** 25378 * Checks pointer capture status. 25379 * 25380 * @return true if the view has pointer capture. 25381 * @see #requestPointerCapture() 25382 * @see #hasPointerCapture() 25383 */ hasPointerCapture()25384 public boolean hasPointerCapture() { 25385 final ViewRootImpl viewRootImpl = getViewRootImpl(); 25386 if (viewRootImpl == null) { 25387 return false; 25388 } 25389 return viewRootImpl.hasPointerCapture(); 25390 } 25391 25392 /** 25393 * Requests pointer capture mode. 25394 * <p> 25395 * When the window has pointer capture, the mouse pointer icon will disappear and will not 25396 * change its position. Further mouse will be dispatched with the source 25397 * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available 25398 * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events 25399 * (touchscreens, or stylus) will not be affected. 25400 * <p> 25401 * If the window already has pointer capture, this call does nothing. 25402 * <p> 25403 * The capture may be released through {@link #releasePointerCapture()}, or will be lost 25404 * automatically when the window loses focus. 25405 * 25406 * @see #releasePointerCapture() 25407 * @see #hasPointerCapture() 25408 */ requestPointerCapture()25409 public void requestPointerCapture() { 25410 final ViewRootImpl viewRootImpl = getViewRootImpl(); 25411 if (viewRootImpl != null) { 25412 viewRootImpl.requestPointerCapture(true); 25413 } 25414 } 25415 25416 25417 /** 25418 * Releases the pointer capture. 25419 * <p> 25420 * If the window does not have pointer capture, this call will do nothing. 25421 * @see #requestPointerCapture() 25422 * @see #hasPointerCapture() 25423 */ releasePointerCapture()25424 public void releasePointerCapture() { 25425 final ViewRootImpl viewRootImpl = getViewRootImpl(); 25426 if (viewRootImpl != null) { 25427 viewRootImpl.requestPointerCapture(false); 25428 } 25429 } 25430 25431 /** 25432 * Called when the window has just acquired or lost pointer capture. 25433 * 25434 * @param hasCapture True if the view now has pointerCapture, false otherwise. 25435 */ 25436 @CallSuper onPointerCaptureChange(boolean hasCapture)25437 public void onPointerCaptureChange(boolean hasCapture) { 25438 } 25439 25440 /** 25441 * @see #onPointerCaptureChange 25442 */ dispatchPointerCaptureChanged(boolean hasCapture)25443 public void dispatchPointerCaptureChanged(boolean hasCapture) { 25444 onPointerCaptureChange(hasCapture); 25445 } 25446 25447 /** 25448 * Implement this method to handle captured pointer events 25449 * 25450 * @param event The captured pointer event. 25451 * @return True if the event was handled, false otherwise. 25452 * @see #requestPointerCapture() 25453 */ onCapturedPointerEvent(MotionEvent event)25454 public boolean onCapturedPointerEvent(MotionEvent event) { 25455 return false; 25456 } 25457 25458 /** 25459 * Interface definition for a callback to be invoked when a captured pointer event 25460 * is being dispatched this view. The callback will be invoked before the event is 25461 * given to the view. 25462 */ 25463 public interface OnCapturedPointerListener { 25464 /** 25465 * Called when a captured pointer event is dispatched to a view. 25466 * @param view The view this event has been dispatched to. 25467 * @param event The captured event. 25468 * @return True if the listener has consumed the event, false otherwise. 25469 */ onCapturedPointer(View view, MotionEvent event)25470 boolean onCapturedPointer(View view, MotionEvent event); 25471 } 25472 25473 /** 25474 * Set a listener to receive callbacks when the pointer capture state of a view changes. 25475 * @param l The {@link OnCapturedPointerListener} to receive callbacks. 25476 */ setOnCapturedPointerListener(OnCapturedPointerListener l)25477 public void setOnCapturedPointerListener(OnCapturedPointerListener l) { 25478 getListenerInfo().mOnCapturedPointerListener = l; 25479 } 25480 25481 // Properties 25482 // 25483 /** 25484 * A Property wrapper around the <code>alpha</code> functionality handled by the 25485 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 25486 */ 25487 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 25488 @Override 25489 public void setValue(View object, float value) { 25490 object.setAlpha(value); 25491 } 25492 25493 @Override 25494 public Float get(View object) { 25495 return object.getAlpha(); 25496 } 25497 }; 25498 25499 /** 25500 * A Property wrapper around the <code>translationX</code> functionality handled by the 25501 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 25502 */ 25503 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 25504 @Override 25505 public void setValue(View object, float value) { 25506 object.setTranslationX(value); 25507 } 25508 25509 @Override 25510 public Float get(View object) { 25511 return object.getTranslationX(); 25512 } 25513 }; 25514 25515 /** 25516 * A Property wrapper around the <code>translationY</code> functionality handled by the 25517 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 25518 */ 25519 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 25520 @Override 25521 public void setValue(View object, float value) { 25522 object.setTranslationY(value); 25523 } 25524 25525 @Override 25526 public Float get(View object) { 25527 return object.getTranslationY(); 25528 } 25529 }; 25530 25531 /** 25532 * A Property wrapper around the <code>translationZ</code> functionality handled by the 25533 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods. 25534 */ 25535 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") { 25536 @Override 25537 public void setValue(View object, float value) { 25538 object.setTranslationZ(value); 25539 } 25540 25541 @Override 25542 public Float get(View object) { 25543 return object.getTranslationZ(); 25544 } 25545 }; 25546 25547 /** 25548 * A Property wrapper around the <code>x</code> functionality handled by the 25549 * {@link View#setX(float)} and {@link View#getX()} methods. 25550 */ 25551 public static final Property<View, Float> X = new FloatProperty<View>("x") { 25552 @Override 25553 public void setValue(View object, float value) { 25554 object.setX(value); 25555 } 25556 25557 @Override 25558 public Float get(View object) { 25559 return object.getX(); 25560 } 25561 }; 25562 25563 /** 25564 * A Property wrapper around the <code>y</code> functionality handled by the 25565 * {@link View#setY(float)} and {@link View#getY()} methods. 25566 */ 25567 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 25568 @Override 25569 public void setValue(View object, float value) { 25570 object.setY(value); 25571 } 25572 25573 @Override 25574 public Float get(View object) { 25575 return object.getY(); 25576 } 25577 }; 25578 25579 /** 25580 * A Property wrapper around the <code>z</code> functionality handled by the 25581 * {@link View#setZ(float)} and {@link View#getZ()} methods. 25582 */ 25583 public static final Property<View, Float> Z = new FloatProperty<View>("z") { 25584 @Override 25585 public void setValue(View object, float value) { 25586 object.setZ(value); 25587 } 25588 25589 @Override 25590 public Float get(View object) { 25591 return object.getZ(); 25592 } 25593 }; 25594 25595 /** 25596 * A Property wrapper around the <code>rotation</code> functionality handled by the 25597 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 25598 */ 25599 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 25600 @Override 25601 public void setValue(View object, float value) { 25602 object.setRotation(value); 25603 } 25604 25605 @Override 25606 public Float get(View object) { 25607 return object.getRotation(); 25608 } 25609 }; 25610 25611 /** 25612 * A Property wrapper around the <code>rotationX</code> functionality handled by the 25613 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 25614 */ 25615 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 25616 @Override 25617 public void setValue(View object, float value) { 25618 object.setRotationX(value); 25619 } 25620 25621 @Override 25622 public Float get(View object) { 25623 return object.getRotationX(); 25624 } 25625 }; 25626 25627 /** 25628 * A Property wrapper around the <code>rotationY</code> functionality handled by the 25629 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 25630 */ 25631 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 25632 @Override 25633 public void setValue(View object, float value) { 25634 object.setRotationY(value); 25635 } 25636 25637 @Override 25638 public Float get(View object) { 25639 return object.getRotationY(); 25640 } 25641 }; 25642 25643 /** 25644 * A Property wrapper around the <code>scaleX</code> functionality handled by the 25645 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 25646 */ 25647 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 25648 @Override 25649 public void setValue(View object, float value) { 25650 object.setScaleX(value); 25651 } 25652 25653 @Override 25654 public Float get(View object) { 25655 return object.getScaleX(); 25656 } 25657 }; 25658 25659 /** 25660 * A Property wrapper around the <code>scaleY</code> functionality handled by the 25661 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 25662 */ 25663 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 25664 @Override 25665 public void setValue(View object, float value) { 25666 object.setScaleY(value); 25667 } 25668 25669 @Override 25670 public Float get(View object) { 25671 return object.getScaleY(); 25672 } 25673 }; 25674 25675 /** 25676 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 25677 * Each MeasureSpec represents a requirement for either the width or the height. 25678 * A MeasureSpec is comprised of a size and a mode. There are three possible 25679 * modes: 25680 * <dl> 25681 * <dt>UNSPECIFIED</dt> 25682 * <dd> 25683 * The parent has not imposed any constraint on the child. It can be whatever size 25684 * it wants. 25685 * </dd> 25686 * 25687 * <dt>EXACTLY</dt> 25688 * <dd> 25689 * The parent has determined an exact size for the child. The child is going to be 25690 * given those bounds regardless of how big it wants to be. 25691 * </dd> 25692 * 25693 * <dt>AT_MOST</dt> 25694 * <dd> 25695 * The child can be as large as it wants up to the specified size. 25696 * </dd> 25697 * </dl> 25698 * 25699 * MeasureSpecs are implemented as ints to reduce object allocation. This class 25700 * is provided to pack and unpack the <size, mode> tuple into the int. 25701 */ 25702 public static class MeasureSpec { 25703 private static final int MODE_SHIFT = 30; 25704 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 25705 25706 /** @hide */ 25707 @IntDef({UNSPECIFIED, EXACTLY, AT_MOST}) 25708 @Retention(RetentionPolicy.SOURCE) 25709 public @interface MeasureSpecMode {} 25710 25711 /** 25712 * Measure specification mode: The parent has not imposed any constraint 25713 * on the child. It can be whatever size it wants. 25714 */ 25715 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 25716 25717 /** 25718 * Measure specification mode: The parent has determined an exact size 25719 * for the child. The child is going to be given those bounds regardless 25720 * of how big it wants to be. 25721 */ 25722 public static final int EXACTLY = 1 << MODE_SHIFT; 25723 25724 /** 25725 * Measure specification mode: The child can be as large as it wants up 25726 * to the specified size. 25727 */ 25728 public static final int AT_MOST = 2 << MODE_SHIFT; 25729 25730 /** 25731 * Creates a measure specification based on the supplied size and mode. 25732 * 25733 * The mode must always be one of the following: 25734 * <ul> 25735 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 25736 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 25737 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 25738 * </ul> 25739 * 25740 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 25741 * implementation was such that the order of arguments did not matter 25742 * and overflow in either value could impact the resulting MeasureSpec. 25743 * {@link android.widget.RelativeLayout} was affected by this bug. 25744 * Apps targeting API levels greater than 17 will get the fixed, more strict 25745 * behavior.</p> 25746 * 25747 * @param size the size of the measure specification 25748 * @param mode the mode of the measure specification 25749 * @return the measure specification based on size and mode 25750 */ makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)25751 public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, 25752 @MeasureSpecMode int mode) { 25753 if (sUseBrokenMakeMeasureSpec) { 25754 return size + mode; 25755 } else { 25756 return (size & ~MODE_MASK) | (mode & MODE_MASK); 25757 } 25758 } 25759 25760 /** 25761 * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED 25762 * will automatically get a size of 0. Older apps expect this. 25763 * 25764 * @hide internal use only for compatibility with system widgets and older apps 25765 */ makeSafeMeasureSpec(int size, int mode)25766 public static int makeSafeMeasureSpec(int size, int mode) { 25767 if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) { 25768 return 0; 25769 } 25770 return makeMeasureSpec(size, mode); 25771 } 25772 25773 /** 25774 * Extracts the mode from the supplied measure specification. 25775 * 25776 * @param measureSpec the measure specification to extract the mode from 25777 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 25778 * {@link android.view.View.MeasureSpec#AT_MOST} or 25779 * {@link android.view.View.MeasureSpec#EXACTLY} 25780 */ 25781 @MeasureSpecMode getMode(int measureSpec)25782 public static int getMode(int measureSpec) { 25783 //noinspection ResourceType 25784 return (measureSpec & MODE_MASK); 25785 } 25786 25787 /** 25788 * Extracts the size from the supplied measure specification. 25789 * 25790 * @param measureSpec the measure specification to extract the size from 25791 * @return the size in pixels defined in the supplied measure specification 25792 */ getSize(int measureSpec)25793 public static int getSize(int measureSpec) { 25794 return (measureSpec & ~MODE_MASK); 25795 } 25796 adjust(int measureSpec, int delta)25797 static int adjust(int measureSpec, int delta) { 25798 final int mode = getMode(measureSpec); 25799 int size = getSize(measureSpec); 25800 if (mode == UNSPECIFIED) { 25801 // No need to adjust size for UNSPECIFIED mode. 25802 return makeMeasureSpec(size, UNSPECIFIED); 25803 } 25804 size += delta; 25805 if (size < 0) { 25806 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + 25807 ") spec: " + toString(measureSpec) + " delta: " + delta); 25808 size = 0; 25809 } 25810 return makeMeasureSpec(size, mode); 25811 } 25812 25813 /** 25814 * Returns a String representation of the specified measure 25815 * specification. 25816 * 25817 * @param measureSpec the measure specification to convert to a String 25818 * @return a String with the following format: "MeasureSpec: MODE SIZE" 25819 */ toString(int measureSpec)25820 public static String toString(int measureSpec) { 25821 int mode = getMode(measureSpec); 25822 int size = getSize(measureSpec); 25823 25824 StringBuilder sb = new StringBuilder("MeasureSpec: "); 25825 25826 if (mode == UNSPECIFIED) 25827 sb.append("UNSPECIFIED "); 25828 else if (mode == EXACTLY) 25829 sb.append("EXACTLY "); 25830 else if (mode == AT_MOST) 25831 sb.append("AT_MOST "); 25832 else 25833 sb.append(mode).append(" "); 25834 25835 sb.append(size); 25836 return sb.toString(); 25837 } 25838 } 25839 25840 private final class CheckForLongPress implements Runnable { 25841 private int mOriginalWindowAttachCount; 25842 private float mX; 25843 private float mY; 25844 private boolean mOriginalPressedState; 25845 25846 @Override run()25847 public void run() { 25848 if ((mOriginalPressedState == isPressed()) && (mParent != null) 25849 && mOriginalWindowAttachCount == mWindowAttachCount) { 25850 if (performLongClick(mX, mY)) { 25851 mHasPerformedLongPress = true; 25852 } 25853 } 25854 } 25855 setAnchor(float x, float y)25856 public void setAnchor(float x, float y) { 25857 mX = x; 25858 mY = y; 25859 } 25860 rememberWindowAttachCount()25861 public void rememberWindowAttachCount() { 25862 mOriginalWindowAttachCount = mWindowAttachCount; 25863 } 25864 rememberPressedState()25865 public void rememberPressedState() { 25866 mOriginalPressedState = isPressed(); 25867 } 25868 } 25869 25870 private final class CheckForTap implements Runnable { 25871 public float x; 25872 public float y; 25873 25874 @Override run()25875 public void run() { 25876 mPrivateFlags &= ~PFLAG_PREPRESSED; 25877 setPressed(true, x, y); 25878 checkForLongClick(ViewConfiguration.getTapTimeout(), x, y); 25879 } 25880 } 25881 25882 private final class PerformClick implements Runnable { 25883 @Override run()25884 public void run() { 25885 performClickInternal(); 25886 } 25887 } 25888 25889 /** 25890 * This method returns a ViewPropertyAnimator object, which can be used to animate 25891 * specific properties on this View. 25892 * 25893 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 25894 */ animate()25895 public ViewPropertyAnimator animate() { 25896 if (mAnimator == null) { 25897 mAnimator = new ViewPropertyAnimator(this); 25898 } 25899 return mAnimator; 25900 } 25901 25902 /** 25903 * Sets the name of the View to be used to identify Views in Transitions. 25904 * Names should be unique in the View hierarchy. 25905 * 25906 * @param transitionName The name of the View to uniquely identify it for Transitions. 25907 */ setTransitionName(String transitionName)25908 public final void setTransitionName(String transitionName) { 25909 mTransitionName = transitionName; 25910 } 25911 25912 /** 25913 * Returns the name of the View to be used to identify Views in Transitions. 25914 * Names should be unique in the View hierarchy. 25915 * 25916 * <p>This returns null if the View has not been given a name.</p> 25917 * 25918 * @return The name used of the View to be used to identify Views in Transitions or null 25919 * if no name has been given. 25920 */ 25921 @ViewDebug.ExportedProperty getTransitionName()25922 public String getTransitionName() { 25923 return mTransitionName; 25924 } 25925 25926 /** 25927 * @hide 25928 */ requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)25929 public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) { 25930 // Do nothing. 25931 } 25932 25933 /** 25934 * Interface definition for a callback to be invoked when a hardware key event is 25935 * dispatched to this view. The callback will be invoked before the key event is 25936 * given to the view. This is only useful for hardware keyboards; a software input 25937 * method has no obligation to trigger this listener. 25938 */ 25939 public interface OnKeyListener { 25940 /** 25941 * Called when a hardware key is dispatched to a view. This allows listeners to 25942 * get a chance to respond before the target view. 25943 * <p>Key presses in software keyboards will generally NOT trigger this method, 25944 * although some may elect to do so in some situations. Do not assume a 25945 * software input method has to be key-based; even if it is, it may use key presses 25946 * in a different way than you expect, so there is no way to reliably catch soft 25947 * input key presses. 25948 * 25949 * @param v The view the key has been dispatched to. 25950 * @param keyCode The code for the physical key that was pressed 25951 * @param event The KeyEvent object containing full information about 25952 * the event. 25953 * @return True if the listener has consumed the event, false otherwise. 25954 */ onKey(View v, int keyCode, KeyEvent event)25955 boolean onKey(View v, int keyCode, KeyEvent event); 25956 } 25957 25958 /** 25959 * Interface definition for a callback to be invoked when a hardware key event hasn't 25960 * been handled by the view hierarchy. 25961 */ 25962 public interface OnUnhandledKeyEventListener { 25963 /** 25964 * Called when a hardware key is dispatched to a view after being unhandled during normal 25965 * {@link KeyEvent} dispatch. 25966 * 25967 * @param v The view the key has been dispatched to. 25968 * @param event The KeyEvent object containing information about the event. 25969 * @return {@code true} if the listener has consumed the event, {@code false} otherwise. 25970 */ onUnhandledKeyEvent(View v, KeyEvent event)25971 boolean onUnhandledKeyEvent(View v, KeyEvent event); 25972 } 25973 25974 /** 25975 * Interface definition for a callback to be invoked when a touch event is 25976 * dispatched to this view. The callback will be invoked before the touch 25977 * event is given to the view. 25978 */ 25979 public interface OnTouchListener { 25980 /** 25981 * Called when a touch event is dispatched to a view. This allows listeners to 25982 * get a chance to respond before the target view. 25983 * 25984 * @param v The view the touch event has been dispatched to. 25985 * @param event The MotionEvent object containing full information about 25986 * the event. 25987 * @return True if the listener has consumed the event, false otherwise. 25988 */ onTouch(View v, MotionEvent event)25989 boolean onTouch(View v, MotionEvent event); 25990 } 25991 25992 /** 25993 * Interface definition for a callback to be invoked when a hover event is 25994 * dispatched to this view. The callback will be invoked before the hover 25995 * event is given to the view. 25996 */ 25997 public interface OnHoverListener { 25998 /** 25999 * Called when a hover event is dispatched to a view. This allows listeners to 26000 * get a chance to respond before the target view. 26001 * 26002 * @param v The view the hover event has been dispatched to. 26003 * @param event The MotionEvent object containing full information about 26004 * the event. 26005 * @return True if the listener has consumed the event, false otherwise. 26006 */ onHover(View v, MotionEvent event)26007 boolean onHover(View v, MotionEvent event); 26008 } 26009 26010 /** 26011 * Interface definition for a callback to be invoked when a generic motion event is 26012 * dispatched to this view. The callback will be invoked before the generic motion 26013 * event is given to the view. 26014 */ 26015 public interface OnGenericMotionListener { 26016 /** 26017 * Called when a generic motion event is dispatched to a view. This allows listeners to 26018 * get a chance to respond before the target view. 26019 * 26020 * @param v The view the generic motion event has been dispatched to. 26021 * @param event The MotionEvent object containing full information about 26022 * the event. 26023 * @return True if the listener has consumed the event, false otherwise. 26024 */ onGenericMotion(View v, MotionEvent event)26025 boolean onGenericMotion(View v, MotionEvent event); 26026 } 26027 26028 /** 26029 * Interface definition for a callback to be invoked when a view has been clicked and held. 26030 */ 26031 public interface OnLongClickListener { 26032 /** 26033 * Called when a view has been clicked and held. 26034 * 26035 * @param v The view that was clicked and held. 26036 * 26037 * @return true if the callback consumed the long click, false otherwise. 26038 */ onLongClick(View v)26039 boolean onLongClick(View v); 26040 } 26041 26042 /** 26043 * Interface definition for a callback to be invoked when a drag is being dispatched 26044 * to this view. The callback will be invoked before the hosting view's own 26045 * onDrag(event) method. If the listener wants to fall back to the hosting view's 26046 * onDrag(event) behavior, it should return 'false' from this callback. 26047 * 26048 * <div class="special reference"> 26049 * <h3>Developer Guides</h3> 26050 * <p>For a guide to implementing drag and drop features, read the 26051 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 26052 * </div> 26053 */ 26054 public interface OnDragListener { 26055 /** 26056 * Called when a drag event is dispatched to a view. This allows listeners 26057 * to get a chance to override base View behavior. 26058 * 26059 * @param v The View that received the drag event. 26060 * @param event The {@link android.view.DragEvent} object for the drag event. 26061 * @return {@code true} if the drag event was handled successfully, or {@code false} 26062 * if the drag event was not handled. Note that {@code false} will trigger the View 26063 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 26064 */ onDrag(View v, DragEvent event)26065 boolean onDrag(View v, DragEvent event); 26066 } 26067 26068 /** 26069 * Interface definition for a callback to be invoked when the focus state of 26070 * a view changed. 26071 */ 26072 public interface OnFocusChangeListener { 26073 /** 26074 * Called when the focus state of a view has changed. 26075 * 26076 * @param v The view whose state has changed. 26077 * @param hasFocus The new focus state of v. 26078 */ onFocusChange(View v, boolean hasFocus)26079 void onFocusChange(View v, boolean hasFocus); 26080 } 26081 26082 /** 26083 * Interface definition for a callback to be invoked when a view is clicked. 26084 */ 26085 public interface OnClickListener { 26086 /** 26087 * Called when a view has been clicked. 26088 * 26089 * @param v The view that was clicked. 26090 */ onClick(View v)26091 void onClick(View v); 26092 } 26093 26094 /** 26095 * Interface definition for a callback to be invoked when a view is context clicked. 26096 */ 26097 public interface OnContextClickListener { 26098 /** 26099 * Called when a view is context clicked. 26100 * 26101 * @param v The view that has been context clicked. 26102 * @return true if the callback consumed the context click, false otherwise. 26103 */ onContextClick(View v)26104 boolean onContextClick(View v); 26105 } 26106 26107 /** 26108 * Interface definition for a callback to be invoked when the context menu 26109 * for this view is being built. 26110 */ 26111 public interface OnCreateContextMenuListener { 26112 /** 26113 * Called when the context menu for this view is being built. It is not 26114 * safe to hold onto the menu after this method returns. 26115 * 26116 * @param menu The context menu that is being built 26117 * @param v The view for which the context menu is being built 26118 * @param menuInfo Extra information about the item for which the 26119 * context menu should be shown. This information will vary 26120 * depending on the class of v. 26121 */ onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)26122 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 26123 } 26124 26125 /** 26126 * Interface definition for a callback to be invoked when the status bar changes 26127 * visibility. This reports <strong>global</strong> changes to the system UI 26128 * state, not what the application is requesting. 26129 * 26130 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 26131 */ 26132 public interface OnSystemUiVisibilityChangeListener { 26133 /** 26134 * Called when the status bar changes visibility because of a call to 26135 * {@link View#setSystemUiVisibility(int)}. 26136 * 26137 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 26138 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 26139 * This tells you the <strong>global</strong> state of these UI visibility 26140 * flags, not what your app is currently applying. 26141 */ onSystemUiVisibilityChange(int visibility)26142 public void onSystemUiVisibilityChange(int visibility); 26143 } 26144 26145 /** 26146 * Interface definition for a callback to be invoked when this view is attached 26147 * or detached from its window. 26148 */ 26149 public interface OnAttachStateChangeListener { 26150 /** 26151 * Called when the view is attached to a window. 26152 * @param v The view that was attached 26153 */ onViewAttachedToWindow(View v)26154 public void onViewAttachedToWindow(View v); 26155 /** 26156 * Called when the view is detached from a window. 26157 * @param v The view that was detached 26158 */ onViewDetachedFromWindow(View v)26159 public void onViewDetachedFromWindow(View v); 26160 } 26161 26162 /** 26163 * Listener for applying window insets on a view in a custom way. 26164 * 26165 * <p>Apps may choose to implement this interface if they want to apply custom policy 26166 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener 26167 * is set, its 26168 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 26169 * method will be called instead of the View's own 26170 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener 26171 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply 26172 * the View's normal behavior as part of its own.</p> 26173 */ 26174 public interface OnApplyWindowInsetsListener { 26175 /** 26176 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set} 26177 * on a View, this listener method will be called instead of the view's own 26178 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 26179 * 26180 * @param v The view applying window insets 26181 * @param insets The insets to apply 26182 * @return The insets supplied, minus any insets that were consumed 26183 */ onApplyWindowInsets(View v, WindowInsets insets)26184 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets); 26185 } 26186 26187 private final class UnsetPressedState implements Runnable { 26188 @Override run()26189 public void run() { 26190 setPressed(false); 26191 } 26192 } 26193 26194 /** 26195 * When a view becomes invisible checks if autofill considers the view invisible too. This 26196 * happens after the regular removal operation to make sure the operation is finished by the 26197 * time this is called. 26198 */ 26199 private static class VisibilityChangeForAutofillHandler extends Handler { 26200 private final AutofillManager mAfm; 26201 private final View mView; 26202 VisibilityChangeForAutofillHandler(@onNull AutofillManager afm, @NonNull View view)26203 private VisibilityChangeForAutofillHandler(@NonNull AutofillManager afm, 26204 @NonNull View view) { 26205 mAfm = afm; 26206 mView = view; 26207 } 26208 26209 @Override handleMessage(Message msg)26210 public void handleMessage(Message msg) { 26211 mAfm.notifyViewVisibilityChanged(mView, mView.isShown()); 26212 } 26213 } 26214 26215 /** 26216 * Base class for derived classes that want to save and restore their own 26217 * state in {@link android.view.View#onSaveInstanceState()}. 26218 */ 26219 public static class BaseSavedState extends AbsSavedState { 26220 static final int START_ACTIVITY_REQUESTED_WHO_SAVED = 0b1; 26221 static final int IS_AUTOFILLED = 0b10; 26222 static final int AUTOFILL_ID = 0b100; 26223 26224 // Flags that describe what data in this state is valid 26225 int mSavedData; 26226 String mStartActivityRequestWhoSaved; 26227 boolean mIsAutofilled; 26228 int mAutofillViewId; 26229 26230 /** 26231 * Constructor used when reading from a parcel. Reads the state of the superclass. 26232 * 26233 * @param source parcel to read from 26234 */ BaseSavedState(Parcel source)26235 public BaseSavedState(Parcel source) { 26236 this(source, null); 26237 } 26238 26239 /** 26240 * Constructor used when reading from a parcel using a given class loader. 26241 * Reads the state of the superclass. 26242 * 26243 * @param source parcel to read from 26244 * @param loader ClassLoader to use for reading 26245 */ BaseSavedState(Parcel source, ClassLoader loader)26246 public BaseSavedState(Parcel source, ClassLoader loader) { 26247 super(source, loader); 26248 mSavedData = source.readInt(); 26249 mStartActivityRequestWhoSaved = source.readString(); 26250 mIsAutofilled = source.readBoolean(); 26251 mAutofillViewId = source.readInt(); 26252 } 26253 26254 /** 26255 * Constructor called by derived classes when creating their SavedState objects 26256 * 26257 * @param superState The state of the superclass of this view 26258 */ BaseSavedState(Parcelable superState)26259 public BaseSavedState(Parcelable superState) { 26260 super(superState); 26261 } 26262 26263 @Override writeToParcel(Parcel out, int flags)26264 public void writeToParcel(Parcel out, int flags) { 26265 super.writeToParcel(out, flags); 26266 26267 out.writeInt(mSavedData); 26268 out.writeString(mStartActivityRequestWhoSaved); 26269 out.writeBoolean(mIsAutofilled); 26270 out.writeInt(mAutofillViewId); 26271 } 26272 26273 public static final Parcelable.Creator<BaseSavedState> CREATOR 26274 = new Parcelable.ClassLoaderCreator<BaseSavedState>() { 26275 @Override 26276 public BaseSavedState createFromParcel(Parcel in) { 26277 return new BaseSavedState(in); 26278 } 26279 26280 @Override 26281 public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) { 26282 return new BaseSavedState(in, loader); 26283 } 26284 26285 @Override 26286 public BaseSavedState[] newArray(int size) { 26287 return new BaseSavedState[size]; 26288 } 26289 }; 26290 } 26291 26292 /** 26293 * A set of information given to a view when it is attached to its parent 26294 * window. 26295 */ 26296 final static class AttachInfo { 26297 interface Callbacks { playSoundEffect(int effectId)26298 void playSoundEffect(int effectId); performHapticFeedback(int effectId, boolean always)26299 boolean performHapticFeedback(int effectId, boolean always); 26300 } 26301 26302 /** 26303 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 26304 * to a Handler. This class contains the target (View) to invalidate and 26305 * the coordinates of the dirty rectangle. 26306 * 26307 * For performance purposes, this class also implements a pool of up to 26308 * POOL_LIMIT objects that get reused. This reduces memory allocations 26309 * whenever possible. 26310 */ 26311 static class InvalidateInfo { 26312 private static final int POOL_LIMIT = 10; 26313 26314 private static final SynchronizedPool<InvalidateInfo> sPool = 26315 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 26316 26317 View target; 26318 26319 int left; 26320 int top; 26321 int right; 26322 int bottom; 26323 obtain()26324 public static InvalidateInfo obtain() { 26325 InvalidateInfo instance = sPool.acquire(); 26326 return (instance != null) ? instance : new InvalidateInfo(); 26327 } 26328 recycle()26329 public void recycle() { 26330 target = null; 26331 sPool.release(this); 26332 } 26333 } 26334 26335 final IWindowSession mSession; 26336 26337 final IWindow mWindow; 26338 26339 final IBinder mWindowToken; 26340 26341 Display mDisplay; 26342 26343 final Callbacks mRootCallbacks; 26344 26345 IWindowId mIWindowId; 26346 WindowId mWindowId; 26347 26348 /** 26349 * The top view of the hierarchy. 26350 */ 26351 View mRootView; 26352 26353 IBinder mPanelParentWindowToken; 26354 26355 boolean mHardwareAccelerated; 26356 boolean mHardwareAccelerationRequested; 26357 ThreadedRenderer mThreadedRenderer; 26358 List<RenderNode> mPendingAnimatingRenderNodes; 26359 26360 /** 26361 * The state of the display to which the window is attached, as reported 26362 * by {@link Display#getState()}. Note that the display state constants 26363 * declared by {@link Display} do not exactly line up with the screen state 26364 * constants declared by {@link View} (there are more display states than 26365 * screen states). 26366 */ 26367 int mDisplayState = Display.STATE_UNKNOWN; 26368 26369 /** 26370 * Scale factor used by the compatibility mode 26371 */ 26372 float mApplicationScale; 26373 26374 /** 26375 * Indicates whether the application is in compatibility mode 26376 */ 26377 boolean mScalingRequired; 26378 26379 /** 26380 * Left position of this view's window 26381 */ 26382 int mWindowLeft; 26383 26384 /** 26385 * Top position of this view's window 26386 */ 26387 int mWindowTop; 26388 26389 /** 26390 * Indicates whether views need to use 32-bit drawing caches 26391 */ 26392 boolean mUse32BitDrawingCache; 26393 26394 /** 26395 * For windows that are full-screen but using insets to layout inside 26396 * of the screen areas, these are the current insets to appear inside 26397 * the overscan area of the display. 26398 */ 26399 final Rect mOverscanInsets = new Rect(); 26400 26401 /** 26402 * For windows that are full-screen but using insets to layout inside 26403 * of the screen decorations, these are the current insets for the 26404 * content of the window. 26405 */ 26406 final Rect mContentInsets = new Rect(); 26407 26408 /** 26409 * For windows that are full-screen but using insets to layout inside 26410 * of the screen decorations, these are the current insets for the 26411 * actual visible parts of the window. 26412 */ 26413 final Rect mVisibleInsets = new Rect(); 26414 26415 /** 26416 * For windows that are full-screen but using insets to layout inside 26417 * of the screen decorations, these are the current insets for the 26418 * stable system windows. 26419 */ 26420 final Rect mStableInsets = new Rect(); 26421 26422 final DisplayCutout.ParcelableWrapper mDisplayCutout = 26423 new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT); 26424 26425 /** 26426 * For windows that include areas that are not covered by real surface these are the outsets 26427 * for real surface. 26428 */ 26429 final Rect mOutsets = new Rect(); 26430 26431 /** 26432 * In multi-window we force show the navigation bar. Because we don't want that the surface 26433 * size changes in this mode, we instead have a flag whether the navigation bar size should 26434 * always be consumed, so the app is treated like there is no virtual navigation bar at all. 26435 */ 26436 boolean mAlwaysConsumeNavBar; 26437 26438 /** 26439 * The internal insets given by this window. This value is 26440 * supplied by the client (through 26441 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 26442 * be given to the window manager when changed to be used in laying 26443 * out windows behind it. 26444 */ 26445 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 26446 = new ViewTreeObserver.InternalInsetsInfo(); 26447 26448 /** 26449 * Set to true when mGivenInternalInsets is non-empty. 26450 */ 26451 boolean mHasNonEmptyGivenInternalInsets; 26452 26453 /** 26454 * All views in the window's hierarchy that serve as scroll containers, 26455 * used to determine if the window can be resized or must be panned 26456 * to adjust for a soft input area. 26457 */ 26458 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 26459 26460 final KeyEvent.DispatcherState mKeyDispatchState 26461 = new KeyEvent.DispatcherState(); 26462 26463 /** 26464 * Indicates whether the view's window currently has the focus. 26465 */ 26466 boolean mHasWindowFocus; 26467 26468 /** 26469 * The current visibility of the window. 26470 */ 26471 int mWindowVisibility; 26472 26473 /** 26474 * Indicates the time at which drawing started to occur. 26475 */ 26476 long mDrawingTime; 26477 26478 /** 26479 * Indicates whether or not ignoring the DIRTY_MASK flags. 26480 */ 26481 boolean mIgnoreDirtyState; 26482 26483 /** 26484 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 26485 * to avoid clearing that flag prematurely. 26486 */ 26487 boolean mSetIgnoreDirtyState = false; 26488 26489 /** 26490 * Indicates whether the view's window is currently in touch mode. 26491 */ 26492 boolean mInTouchMode; 26493 26494 /** 26495 * Indicates whether the view has requested unbuffered input dispatching for the current 26496 * event stream. 26497 */ 26498 boolean mUnbufferedDispatchRequested; 26499 26500 /** 26501 * Indicates that ViewAncestor should trigger a global layout change 26502 * the next time it performs a traversal 26503 */ 26504 boolean mRecomputeGlobalAttributes; 26505 26506 /** 26507 * Always report new attributes at next traversal. 26508 */ 26509 boolean mForceReportNewAttributes; 26510 26511 /** 26512 * Set during a traveral if any views want to keep the screen on. 26513 */ 26514 boolean mKeepScreenOn; 26515 26516 /** 26517 * Set during a traveral if the light center needs to be updated. 26518 */ 26519 boolean mNeedsUpdateLightCenter; 26520 26521 /** 26522 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 26523 */ 26524 int mSystemUiVisibility; 26525 26526 /** 26527 * Hack to force certain system UI visibility flags to be cleared. 26528 */ 26529 int mDisabledSystemUiVisibility; 26530 26531 /** 26532 * Last global system UI visibility reported by the window manager. 26533 */ 26534 int mGlobalSystemUiVisibility = -1; 26535 26536 /** 26537 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 26538 * attached. 26539 */ 26540 boolean mHasSystemUiListeners; 26541 26542 /** 26543 * Set if the window has requested to extend into the overscan region 26544 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 26545 */ 26546 boolean mOverscanRequested; 26547 26548 /** 26549 * Set if the visibility of any views has changed. 26550 */ 26551 boolean mViewVisibilityChanged; 26552 26553 /** 26554 * Set to true if a view has been scrolled. 26555 */ 26556 boolean mViewScrollChanged; 26557 26558 /** 26559 * Set to true if a pointer event is currently being handled. 26560 */ 26561 boolean mHandlingPointerEvent; 26562 26563 /** 26564 * Global to the view hierarchy used as a temporary for dealing with 26565 * x/y points in the transparent region computations. 26566 */ 26567 final int[] mTransparentLocation = new int[2]; 26568 26569 /** 26570 * Global to the view hierarchy used as a temporary for dealing with 26571 * x/y points in the ViewGroup.invalidateChild implementation. 26572 */ 26573 final int[] mInvalidateChildLocation = new int[2]; 26574 26575 /** 26576 * Global to the view hierarchy used as a temporary for dealing with 26577 * computing absolute on-screen location. 26578 */ 26579 final int[] mTmpLocation = new int[2]; 26580 26581 /** 26582 * Global to the view hierarchy used as a temporary for dealing with 26583 * x/y location when view is transformed. 26584 */ 26585 final float[] mTmpTransformLocation = new float[2]; 26586 26587 /** 26588 * The view tree observer used to dispatch global events like 26589 * layout, pre-draw, touch mode change, etc. 26590 */ 26591 final ViewTreeObserver mTreeObserver; 26592 26593 /** 26594 * A Canvas used by the view hierarchy to perform bitmap caching. 26595 */ 26596 Canvas mCanvas; 26597 26598 /** 26599 * The view root impl. 26600 */ 26601 final ViewRootImpl mViewRootImpl; 26602 26603 /** 26604 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 26605 * handler can be used to pump events in the UI events queue. 26606 */ 26607 final Handler mHandler; 26608 26609 /** 26610 * Temporary for use in computing invalidate rectangles while 26611 * calling up the hierarchy. 26612 */ 26613 final Rect mTmpInvalRect = new Rect(); 26614 26615 /** 26616 * Temporary for use in computing hit areas with transformed views 26617 */ 26618 final RectF mTmpTransformRect = new RectF(); 26619 26620 /** 26621 * Temporary for use in computing hit areas with transformed views 26622 */ 26623 final RectF mTmpTransformRect1 = new RectF(); 26624 26625 /** 26626 * Temporary list of rectanges. 26627 */ 26628 final List<RectF> mTmpRectList = new ArrayList<>(); 26629 26630 /** 26631 * Temporary for use in transforming invalidation rect 26632 */ 26633 final Matrix mTmpMatrix = new Matrix(); 26634 26635 /** 26636 * Temporary for use in transforming invalidation rect 26637 */ 26638 final Transformation mTmpTransformation = new Transformation(); 26639 26640 /** 26641 * Temporary for use in querying outlines from OutlineProviders 26642 */ 26643 final Outline mTmpOutline = new Outline(); 26644 26645 /** 26646 * Temporary list for use in collecting focusable descendents of a view. 26647 */ 26648 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 26649 26650 /** 26651 * The id of the window for accessibility purposes. 26652 */ 26653 int mAccessibilityWindowId = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 26654 26655 /** 26656 * Flags related to accessibility processing. 26657 * 26658 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 26659 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 26660 */ 26661 int mAccessibilityFetchFlags; 26662 26663 /** 26664 * The drawable for highlighting accessibility focus. 26665 */ 26666 Drawable mAccessibilityFocusDrawable; 26667 26668 /** 26669 * The drawable for highlighting autofilled views. 26670 * 26671 * @see #isAutofilled() 26672 */ 26673 Drawable mAutofilledDrawable; 26674 26675 /** 26676 * Show where the margins, bounds and layout bounds are for each view. 26677 */ 26678 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 26679 26680 /** 26681 * Point used to compute visible regions. 26682 */ 26683 final Point mPoint = new Point(); 26684 26685 /** 26686 * Used to track which View originated a requestLayout() call, used when 26687 * requestLayout() is called during layout. 26688 */ 26689 View mViewRequestingLayout; 26690 26691 /** 26692 * Used to track views that need (at least) a partial relayout at their current size 26693 * during the next traversal. 26694 */ 26695 List<View> mPartialLayoutViews = new ArrayList<>(); 26696 26697 /** 26698 * Swapped with mPartialLayoutViews during layout to avoid concurrent 26699 * modification. Lazily assigned during ViewRootImpl layout. 26700 */ 26701 List<View> mEmptyPartialLayoutViews; 26702 26703 /** 26704 * Used to track the identity of the current drag operation. 26705 */ 26706 IBinder mDragToken; 26707 26708 /** 26709 * The drag shadow surface for the current drag operation. 26710 */ 26711 public Surface mDragSurface; 26712 26713 26714 /** 26715 * The view that currently has a tooltip displayed. 26716 */ 26717 View mTooltipHost; 26718 26719 /** 26720 * Creates a new set of attachment information with the specified 26721 * events handler and thread. 26722 * 26723 * @param handler the events handler the view must use 26724 */ AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, Context context)26725 AttachInfo(IWindowSession session, IWindow window, Display display, 26726 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer, 26727 Context context) { 26728 mSession = session; 26729 mWindow = window; 26730 mWindowToken = window.asBinder(); 26731 mDisplay = display; 26732 mViewRootImpl = viewRootImpl; 26733 mHandler = handler; 26734 mRootCallbacks = effectPlayer; 26735 mTreeObserver = new ViewTreeObserver(context); 26736 } 26737 } 26738 26739 /** 26740 * <p>ScrollabilityCache holds various fields used by a View when scrolling 26741 * is supported. This avoids keeping too many unused fields in most 26742 * instances of View.</p> 26743 */ 26744 private static class ScrollabilityCache implements Runnable { 26745 26746 /** 26747 * Scrollbars are not visible 26748 */ 26749 public static final int OFF = 0; 26750 26751 /** 26752 * Scrollbars are visible 26753 */ 26754 public static final int ON = 1; 26755 26756 /** 26757 * Scrollbars are fading away 26758 */ 26759 public static final int FADING = 2; 26760 26761 public boolean fadeScrollBars; 26762 26763 public int fadingEdgeLength; 26764 public int scrollBarDefaultDelayBeforeFade; 26765 public int scrollBarFadeDuration; 26766 26767 public int scrollBarSize; 26768 public int scrollBarMinTouchTarget; 26769 public ScrollBarDrawable scrollBar; 26770 public float[] interpolatorValues; 26771 public View host; 26772 26773 public final Paint paint; 26774 public final Matrix matrix; 26775 public Shader shader; 26776 26777 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 26778 26779 private static final float[] OPAQUE = { 255 }; 26780 private static final float[] TRANSPARENT = { 0.0f }; 26781 26782 /** 26783 * When fading should start. This time moves into the future every time 26784 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 26785 */ 26786 public long fadeStartTime; 26787 26788 26789 /** 26790 * The current state of the scrollbars: ON, OFF, or FADING 26791 */ 26792 public int state = OFF; 26793 26794 private int mLastColor; 26795 26796 public final Rect mScrollBarBounds = new Rect(); 26797 public final Rect mScrollBarTouchBounds = new Rect(); 26798 26799 public static final int NOT_DRAGGING = 0; 26800 public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1; 26801 public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2; 26802 public int mScrollBarDraggingState = NOT_DRAGGING; 26803 26804 public float mScrollBarDraggingPos = 0; 26805 ScrollabilityCache(ViewConfiguration configuration, View host)26806 public ScrollabilityCache(ViewConfiguration configuration, View host) { 26807 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 26808 scrollBarSize = configuration.getScaledScrollBarSize(); 26809 scrollBarMinTouchTarget = configuration.getScaledMinScrollbarTouchTarget(); 26810 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 26811 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 26812 26813 paint = new Paint(); 26814 matrix = new Matrix(); 26815 // use use a height of 1, and then wack the matrix each time we 26816 // actually use it. 26817 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 26818 paint.setShader(shader); 26819 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 26820 26821 this.host = host; 26822 } 26823 setFadeColor(int color)26824 public void setFadeColor(int color) { 26825 if (color != mLastColor) { 26826 mLastColor = color; 26827 26828 if (color != 0) { 26829 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 26830 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 26831 paint.setShader(shader); 26832 // Restore the default transfer mode (src_over) 26833 paint.setXfermode(null); 26834 } else { 26835 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 26836 paint.setShader(shader); 26837 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 26838 } 26839 } 26840 } 26841 run()26842 public void run() { 26843 long now = AnimationUtils.currentAnimationTimeMillis(); 26844 if (now >= fadeStartTime) { 26845 26846 // the animation fades the scrollbars out by changing 26847 // the opacity (alpha) from fully opaque to fully 26848 // transparent 26849 int nextFrame = (int) now; 26850 int framesCount = 0; 26851 26852 Interpolator interpolator = scrollBarInterpolator; 26853 26854 // Start opaque 26855 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 26856 26857 // End transparent 26858 nextFrame += scrollBarFadeDuration; 26859 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 26860 26861 state = FADING; 26862 26863 // Kick off the fade animation 26864 host.invalidate(true); 26865 } 26866 } 26867 } 26868 26869 /** 26870 * Resuable callback for sending 26871 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 26872 */ 26873 private class SendViewScrolledAccessibilityEvent implements Runnable { 26874 public volatile boolean mIsPending; 26875 public int mDeltaX; 26876 public int mDeltaY; 26877 post(int dx, int dy)26878 public void post(int dx, int dy) { 26879 mDeltaX += dx; 26880 mDeltaY += dy; 26881 if (!mIsPending) { 26882 mIsPending = true; 26883 postDelayed(this, ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 26884 } 26885 } 26886 26887 @Override run()26888 public void run() { 26889 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 26890 AccessibilityEvent event = AccessibilityEvent.obtain( 26891 AccessibilityEvent.TYPE_VIEW_SCROLLED); 26892 event.setScrollDeltaX(mDeltaX); 26893 event.setScrollDeltaY(mDeltaY); 26894 sendAccessibilityEventUnchecked(event); 26895 } 26896 reset(); 26897 } 26898 reset()26899 private void reset() { 26900 mIsPending = false; 26901 mDeltaX = 0; 26902 mDeltaY = 0; 26903 } 26904 } 26905 26906 /** 26907 * Remove the pending callback for sending a 26908 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 26909 */ cancel(@ullable SendViewScrolledAccessibilityEvent callback)26910 private void cancel(@Nullable SendViewScrolledAccessibilityEvent callback) { 26911 if (callback == null || !callback.mIsPending) return; 26912 removeCallbacks(callback); 26913 callback.reset(); 26914 } 26915 26916 /** 26917 * <p> 26918 * This class represents a delegate that can be registered in a {@link View} 26919 * to enhance accessibility support via composition rather via inheritance. 26920 * It is specifically targeted to widget developers that extend basic View 26921 * classes i.e. classes in package android.view, that would like their 26922 * applications to be backwards compatible. 26923 * </p> 26924 * <div class="special reference"> 26925 * <h3>Developer Guides</h3> 26926 * <p>For more information about making applications accessible, read the 26927 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 26928 * developer guide.</p> 26929 * </div> 26930 * <p> 26931 * A scenario in which a developer would like to use an accessibility delegate 26932 * is overriding a method introduced in a later API version than the minimal API 26933 * version supported by the application. For example, the method 26934 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 26935 * in API version 4 when the accessibility APIs were first introduced. If a 26936 * developer would like their application to run on API version 4 devices (assuming 26937 * all other APIs used by the application are version 4 or lower) and take advantage 26938 * of this method, instead of overriding the method which would break the application's 26939 * backwards compatibility, they can override the corresponding method in this 26940 * delegate and register the delegate in the target View if the API version of 26941 * the system is high enough, i.e. the API version is the same as or higher than the API 26942 * version that introduced 26943 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 26944 * </p> 26945 * <p> 26946 * Here is an example implementation: 26947 * </p> 26948 * <code><pre><p> 26949 * if (Build.VERSION.SDK_INT >= 14) { 26950 * // If the API version is equal of higher than the version in 26951 * // which onInitializeAccessibilityNodeInfo was introduced we 26952 * // register a delegate with a customized implementation. 26953 * View view = findViewById(R.id.view_id); 26954 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 26955 * public void onInitializeAccessibilityNodeInfo(View host, 26956 * AccessibilityNodeInfo info) { 26957 * // Let the default implementation populate the info. 26958 * super.onInitializeAccessibilityNodeInfo(host, info); 26959 * // Set some other information. 26960 * info.setEnabled(host.isEnabled()); 26961 * } 26962 * }); 26963 * } 26964 * </code></pre></p> 26965 * <p> 26966 * This delegate contains methods that correspond to the accessibility methods 26967 * in View. If a delegate has been specified the implementation in View hands 26968 * off handling to the corresponding method in this delegate. The default 26969 * implementation the delegate methods behaves exactly as the corresponding 26970 * method in View for the case of no accessibility delegate been set. Hence, 26971 * to customize the behavior of a View method, clients can override only the 26972 * corresponding delegate method without altering the behavior of the rest 26973 * accessibility related methods of the host view. 26974 * </p> 26975 * <p> 26976 * <strong>Note:</strong> On platform versions prior to 26977 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 26978 * views in the {@code android.widget.*} package are called <i>before</i> 26979 * host methods. This prevents certain properties such as class name from 26980 * being modified by overriding 26981 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 26982 * as any changes will be overwritten by the host class. 26983 * <p> 26984 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 26985 * methods are called <i>after</i> host methods, which all properties to be 26986 * modified without being overwritten by the host class. 26987 */ 26988 public static class AccessibilityDelegate { 26989 26990 /** 26991 * Sends an accessibility event of the given type. If accessibility is not 26992 * enabled this method has no effect. 26993 * <p> 26994 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 26995 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 26996 * been set. 26997 * </p> 26998 * 26999 * @param host The View hosting the delegate. 27000 * @param eventType The type of the event to send. 27001 * 27002 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 27003 */ sendAccessibilityEvent(View host, int eventType)27004 public void sendAccessibilityEvent(View host, int eventType) { 27005 host.sendAccessibilityEventInternal(eventType); 27006 } 27007 27008 /** 27009 * Performs the specified accessibility action on the view. For 27010 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 27011 * <p> 27012 * The default implementation behaves as 27013 * {@link View#performAccessibilityAction(int, Bundle) 27014 * View#performAccessibilityAction(int, Bundle)} for the case of 27015 * no accessibility delegate been set. 27016 * </p> 27017 * 27018 * @param action The action to perform. 27019 * @return Whether the action was performed. 27020 * 27021 * @see View#performAccessibilityAction(int, Bundle) 27022 * View#performAccessibilityAction(int, Bundle) 27023 */ performAccessibilityAction(View host, int action, Bundle args)27024 public boolean performAccessibilityAction(View host, int action, Bundle args) { 27025 return host.performAccessibilityActionInternal(action, args); 27026 } 27027 27028 /** 27029 * Sends an accessibility event. This method behaves exactly as 27030 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 27031 * empty {@link AccessibilityEvent} and does not perform a check whether 27032 * accessibility is enabled. 27033 * <p> 27034 * The default implementation behaves as 27035 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 27036 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 27037 * the case of no accessibility delegate been set. 27038 * </p> 27039 * 27040 * @param host The View hosting the delegate. 27041 * @param event The event to send. 27042 * 27043 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 27044 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 27045 */ sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)27046 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 27047 host.sendAccessibilityEventUncheckedInternal(event); 27048 } 27049 27050 /** 27051 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 27052 * to its children for adding their text content to the event. 27053 * <p> 27054 * The default implementation behaves as 27055 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 27056 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 27057 * the case of no accessibility delegate been set. 27058 * </p> 27059 * 27060 * @param host The View hosting the delegate. 27061 * @param event The event. 27062 * @return True if the event population was completed. 27063 * 27064 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 27065 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 27066 */ dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)27067 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 27068 return host.dispatchPopulateAccessibilityEventInternal(event); 27069 } 27070 27071 /** 27072 * Gives a chance to the host View to populate the accessibility event with its 27073 * text content. 27074 * <p> 27075 * The default implementation behaves as 27076 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 27077 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 27078 * the case of no accessibility delegate been set. 27079 * </p> 27080 * 27081 * @param host The View hosting the delegate. 27082 * @param event The accessibility event which to populate. 27083 * 27084 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 27085 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 27086 */ onPopulateAccessibilityEvent(View host, AccessibilityEvent event)27087 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 27088 host.onPopulateAccessibilityEventInternal(event); 27089 } 27090 27091 /** 27092 * Initializes an {@link AccessibilityEvent} with information about the 27093 * the host View which is the event source. 27094 * <p> 27095 * The default implementation behaves as 27096 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 27097 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 27098 * the case of no accessibility delegate been set. 27099 * </p> 27100 * 27101 * @param host The View hosting the delegate. 27102 * @param event The event to initialize. 27103 * 27104 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 27105 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 27106 */ onInitializeAccessibilityEvent(View host, AccessibilityEvent event)27107 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 27108 host.onInitializeAccessibilityEventInternal(event); 27109 } 27110 27111 /** 27112 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 27113 * <p> 27114 * The default implementation behaves as 27115 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 27116 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 27117 * the case of no accessibility delegate been set. 27118 * </p> 27119 * 27120 * @param host The View hosting the delegate. 27121 * @param info The instance to initialize. 27122 * 27123 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 27124 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 27125 */ onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)27126 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 27127 host.onInitializeAccessibilityNodeInfoInternal(info); 27128 } 27129 27130 /** 27131 * Adds extra data to an {@link AccessibilityNodeInfo} based on an explicit request for the 27132 * additional data. 27133 * <p> 27134 * This method only needs to be implemented if the View offers to provide additional data. 27135 * </p> 27136 * <p> 27137 * The default implementation behaves as 27138 * {@link View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle) 27139 * for the case where no accessibility delegate is set. 27140 * </p> 27141 * 27142 * @param host The View hosting the delegate. Never {@code null}. 27143 * @param info The info to which to add the extra data. Never {@code null}. 27144 * @param extraDataKey A key specifying the type of extra data to add to the info. The 27145 * extra data should be added to the {@link Bundle} returned by 27146 * the info's {@link AccessibilityNodeInfo#getExtras} method. Never 27147 * {@code null}. 27148 * @param arguments A {@link Bundle} holding any arguments relevant for this request. 27149 * May be {@code null} if the if the service provided no arguments. 27150 * 27151 * @see AccessibilityNodeInfo#setExtraAvailableData 27152 */ addExtraDataToAccessibilityNodeInfo(@onNull View host, @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, @Nullable Bundle arguments)27153 public void addExtraDataToAccessibilityNodeInfo(@NonNull View host, 27154 @NonNull AccessibilityNodeInfo info, @NonNull String extraDataKey, 27155 @Nullable Bundle arguments) { 27156 host.addExtraDataToAccessibilityNodeInfo(info, extraDataKey, arguments); 27157 } 27158 27159 /** 27160 * Called when a child of the host View has requested sending an 27161 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 27162 * to augment the event. 27163 * <p> 27164 * The default implementation behaves as 27165 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 27166 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 27167 * the case of no accessibility delegate been set. 27168 * </p> 27169 * 27170 * @param host The View hosting the delegate. 27171 * @param child The child which requests sending the event. 27172 * @param event The event to be sent. 27173 * @return True if the event should be sent 27174 * 27175 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 27176 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 27177 */ onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)27178 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 27179 AccessibilityEvent event) { 27180 return host.onRequestSendAccessibilityEventInternal(child, event); 27181 } 27182 27183 /** 27184 * Gets the provider for managing a virtual view hierarchy rooted at this View 27185 * and reported to {@link android.accessibilityservice.AccessibilityService}s 27186 * that explore the window content. 27187 * <p> 27188 * The default implementation behaves as 27189 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 27190 * the case of no accessibility delegate been set. 27191 * </p> 27192 * 27193 * @return The provider. 27194 * 27195 * @see AccessibilityNodeProvider 27196 */ getAccessibilityNodeProvider(View host)27197 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 27198 return null; 27199 } 27200 27201 /** 27202 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 27203 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 27204 * This method is responsible for obtaining an accessibility node info from a 27205 * pool of reusable instances and calling 27206 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 27207 * view to initialize the former. 27208 * <p> 27209 * <strong>Note:</strong> The client is responsible for recycling the obtained 27210 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 27211 * creation. 27212 * </p> 27213 * <p> 27214 * The default implementation behaves as 27215 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 27216 * the case of no accessibility delegate been set. 27217 * </p> 27218 * @return A populated {@link AccessibilityNodeInfo}. 27219 * 27220 * @see AccessibilityNodeInfo 27221 * 27222 * @hide 27223 */ createAccessibilityNodeInfo(View host)27224 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 27225 return host.createAccessibilityNodeInfoInternal(); 27226 } 27227 } 27228 27229 private static class MatchIdPredicate implements Predicate<View> { 27230 public int mId; 27231 27232 @Override test(View view)27233 public boolean test(View view) { 27234 return (view.mID == mId); 27235 } 27236 } 27237 27238 private static class MatchLabelForPredicate implements Predicate<View> { 27239 private int mLabeledId; 27240 27241 @Override test(View view)27242 public boolean test(View view) { 27243 return (view.mLabelForId == mLabeledId); 27244 } 27245 } 27246 27247 /** 27248 * Dump all private flags in readable format, useful for documentation and 27249 * sanity checking. 27250 */ dumpFlags()27251 private static void dumpFlags() { 27252 final HashMap<String, String> found = Maps.newHashMap(); 27253 try { 27254 for (Field field : View.class.getDeclaredFields()) { 27255 final int modifiers = field.getModifiers(); 27256 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 27257 if (field.getType().equals(int.class)) { 27258 final int value = field.getInt(null); 27259 dumpFlag(found, field.getName(), value); 27260 } else if (field.getType().equals(int[].class)) { 27261 final int[] values = (int[]) field.get(null); 27262 for (int i = 0; i < values.length; i++) { 27263 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 27264 } 27265 } 27266 } 27267 } 27268 } catch (IllegalAccessException e) { 27269 throw new RuntimeException(e); 27270 } 27271 27272 final ArrayList<String> keys = Lists.newArrayList(); 27273 keys.addAll(found.keySet()); 27274 Collections.sort(keys); 27275 for (String key : keys) { 27276 Log.d(VIEW_LOG_TAG, found.get(key)); 27277 } 27278 } 27279 dumpFlag(HashMap<String, String> found, String name, int value)27280 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 27281 // Sort flags by prefix, then by bits, always keeping unique keys 27282 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 27283 final int prefix = name.indexOf('_'); 27284 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 27285 final String output = bits + " " + name; 27286 found.put(key, output); 27287 } 27288 27289 /** {@hide} */ encode(@onNull ViewHierarchyEncoder stream)27290 public void encode(@NonNull ViewHierarchyEncoder stream) { 27291 stream.beginObject(this); 27292 encodeProperties(stream); 27293 stream.endObject(); 27294 } 27295 27296 /** {@hide} */ 27297 @CallSuper encodeProperties(@onNull ViewHierarchyEncoder stream)27298 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 27299 Object resolveId = ViewDebug.resolveId(getContext(), mID); 27300 if (resolveId instanceof String) { 27301 stream.addProperty("id", (String) resolveId); 27302 } else { 27303 stream.addProperty("id", mID); 27304 } 27305 27306 stream.addProperty("misc:transformation.alpha", 27307 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); 27308 stream.addProperty("misc:transitionName", getTransitionName()); 27309 27310 // layout 27311 stream.addProperty("layout:left", mLeft); 27312 stream.addProperty("layout:right", mRight); 27313 stream.addProperty("layout:top", mTop); 27314 stream.addProperty("layout:bottom", mBottom); 27315 stream.addProperty("layout:width", getWidth()); 27316 stream.addProperty("layout:height", getHeight()); 27317 stream.addProperty("layout:layoutDirection", getLayoutDirection()); 27318 stream.addProperty("layout:layoutRtl", isLayoutRtl()); 27319 stream.addProperty("layout:hasTransientState", hasTransientState()); 27320 stream.addProperty("layout:baseline", getBaseline()); 27321 27322 // layout params 27323 ViewGroup.LayoutParams layoutParams = getLayoutParams(); 27324 if (layoutParams != null) { 27325 stream.addPropertyKey("layoutParams"); 27326 layoutParams.encode(stream); 27327 } 27328 27329 // scrolling 27330 stream.addProperty("scrolling:scrollX", mScrollX); 27331 stream.addProperty("scrolling:scrollY", mScrollY); 27332 27333 // padding 27334 stream.addProperty("padding:paddingLeft", mPaddingLeft); 27335 stream.addProperty("padding:paddingRight", mPaddingRight); 27336 stream.addProperty("padding:paddingTop", mPaddingTop); 27337 stream.addProperty("padding:paddingBottom", mPaddingBottom); 27338 stream.addProperty("padding:userPaddingRight", mUserPaddingRight); 27339 stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); 27340 stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); 27341 stream.addProperty("padding:userPaddingStart", mUserPaddingStart); 27342 stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); 27343 27344 // measurement 27345 stream.addProperty("measurement:minHeight", mMinHeight); 27346 stream.addProperty("measurement:minWidth", mMinWidth); 27347 stream.addProperty("measurement:measuredWidth", mMeasuredWidth); 27348 stream.addProperty("measurement:measuredHeight", mMeasuredHeight); 27349 27350 // drawing 27351 stream.addProperty("drawing:elevation", getElevation()); 27352 stream.addProperty("drawing:translationX", getTranslationX()); 27353 stream.addProperty("drawing:translationY", getTranslationY()); 27354 stream.addProperty("drawing:translationZ", getTranslationZ()); 27355 stream.addProperty("drawing:rotation", getRotation()); 27356 stream.addProperty("drawing:rotationX", getRotationX()); 27357 stream.addProperty("drawing:rotationY", getRotationY()); 27358 stream.addProperty("drawing:scaleX", getScaleX()); 27359 stream.addProperty("drawing:scaleY", getScaleY()); 27360 stream.addProperty("drawing:pivotX", getPivotX()); 27361 stream.addProperty("drawing:pivotY", getPivotY()); 27362 stream.addProperty("drawing:clipBounds", 27363 mClipBounds == null ? null : mClipBounds.toString()); 27364 stream.addProperty("drawing:opaque", isOpaque()); 27365 stream.addProperty("drawing:alpha", getAlpha()); 27366 stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); 27367 stream.addProperty("drawing:shadow", hasShadow()); 27368 stream.addProperty("drawing:solidColor", getSolidColor()); 27369 stream.addProperty("drawing:layerType", mLayerType); 27370 stream.addProperty("drawing:willNotDraw", willNotDraw()); 27371 stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); 27372 stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); 27373 stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); 27374 stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); 27375 stream.addProperty("drawing:outlineAmbientShadowColor", getOutlineAmbientShadowColor()); 27376 stream.addProperty("drawing:outlineSpotShadowColor", getOutlineSpotShadowColor()); 27377 27378 // focus 27379 stream.addProperty("focus:hasFocus", hasFocus()); 27380 stream.addProperty("focus:isFocused", isFocused()); 27381 stream.addProperty("focus:focusable", getFocusable()); 27382 stream.addProperty("focus:isFocusable", isFocusable()); 27383 stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); 27384 27385 stream.addProperty("misc:clickable", isClickable()); 27386 stream.addProperty("misc:pressed", isPressed()); 27387 stream.addProperty("misc:selected", isSelected()); 27388 stream.addProperty("misc:touchMode", isInTouchMode()); 27389 stream.addProperty("misc:hovered", isHovered()); 27390 stream.addProperty("misc:activated", isActivated()); 27391 27392 stream.addProperty("misc:visibility", getVisibility()); 27393 stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); 27394 stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); 27395 27396 stream.addProperty("misc:enabled", isEnabled()); 27397 stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); 27398 stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); 27399 27400 // theme attributes 27401 Resources.Theme theme = getContext().getTheme(); 27402 if (theme != null) { 27403 stream.addPropertyKey("theme"); 27404 theme.encode(stream); 27405 } 27406 27407 // view attribute information 27408 int n = mAttributes != null ? mAttributes.length : 0; 27409 stream.addProperty("meta:__attrCount__", n/2); 27410 for (int i = 0; i < n; i += 2) { 27411 stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); 27412 } 27413 27414 stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); 27415 27416 // text 27417 stream.addProperty("text:textDirection", getTextDirection()); 27418 stream.addProperty("text:textAlignment", getTextAlignment()); 27419 27420 // accessibility 27421 CharSequence contentDescription = getContentDescription(); 27422 stream.addProperty("accessibility:contentDescription", 27423 contentDescription == null ? "" : contentDescription.toString()); 27424 stream.addProperty("accessibility:labelFor", getLabelFor()); 27425 stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); 27426 } 27427 27428 /** 27429 * Determine if this view is rendered on a round wearable device and is the main view 27430 * on the screen. 27431 */ shouldDrawRoundScrollbar()27432 boolean shouldDrawRoundScrollbar() { 27433 if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) { 27434 return false; 27435 } 27436 27437 final View rootView = getRootView(); 27438 final WindowInsets insets = getRootWindowInsets(); 27439 27440 int height = getHeight(); 27441 int width = getWidth(); 27442 int displayHeight = rootView.getHeight(); 27443 int displayWidth = rootView.getWidth(); 27444 27445 if (height != displayHeight || width != displayWidth) { 27446 return false; 27447 } 27448 27449 getLocationInWindow(mAttachInfo.mTmpLocation); 27450 return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft() 27451 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop(); 27452 } 27453 27454 /** 27455 * Sets the tooltip text which will be displayed in a small popup next to the view. 27456 * <p> 27457 * The tooltip will be displayed: 27458 * <ul> 27459 * <li>On long click, unless it is handled otherwise (by OnLongClickListener or a context 27460 * menu). </li> 27461 * <li>On hover, after a brief delay since the pointer has stopped moving </li> 27462 * </ul> 27463 * <p> 27464 * <strong>Note:</strong> Do not override this method, as it will have no 27465 * effect on the text displayed in the tooltip. 27466 * 27467 * @param tooltipText the tooltip text, or null if no tooltip is required 27468 * @see #getTooltipText() 27469 * @attr ref android.R.styleable#View_tooltipText 27470 */ setTooltipText(@ullable CharSequence tooltipText)27471 public void setTooltipText(@Nullable CharSequence tooltipText) { 27472 if (TextUtils.isEmpty(tooltipText)) { 27473 setFlags(0, TOOLTIP); 27474 hideTooltip(); 27475 mTooltipInfo = null; 27476 } else { 27477 setFlags(TOOLTIP, TOOLTIP); 27478 if (mTooltipInfo == null) { 27479 mTooltipInfo = new TooltipInfo(); 27480 mTooltipInfo.mShowTooltipRunnable = this::showHoverTooltip; 27481 mTooltipInfo.mHideTooltipRunnable = this::hideTooltip; 27482 mTooltipInfo.mHoverSlop = ViewConfiguration.get(mContext).getScaledHoverSlop(); 27483 mTooltipInfo.clearAnchorPos(); 27484 } 27485 mTooltipInfo.mTooltipText = tooltipText; 27486 } 27487 } 27488 27489 /** 27490 * @hide Binary compatibility stub. To be removed when we finalize O APIs. 27491 */ setTooltip(@ullable CharSequence tooltipText)27492 public void setTooltip(@Nullable CharSequence tooltipText) { 27493 setTooltipText(tooltipText); 27494 } 27495 27496 /** 27497 * Returns the view's tooltip text. 27498 * 27499 * <strong>Note:</strong> Do not override this method, as it will have no 27500 * effect on the text displayed in the tooltip. You must call 27501 * {@link #setTooltipText(CharSequence)} to modify the tooltip text. 27502 * 27503 * @return the tooltip text 27504 * @see #setTooltipText(CharSequence) 27505 * @attr ref android.R.styleable#View_tooltipText 27506 */ 27507 @Nullable getTooltipText()27508 public CharSequence getTooltipText() { 27509 return mTooltipInfo != null ? mTooltipInfo.mTooltipText : null; 27510 } 27511 27512 /** 27513 * @hide Binary compatibility stub. To be removed when we finalize O APIs. 27514 */ 27515 @Nullable getTooltip()27516 public CharSequence getTooltip() { 27517 return getTooltipText(); 27518 } 27519 showTooltip(int x, int y, boolean fromLongClick)27520 private boolean showTooltip(int x, int y, boolean fromLongClick) { 27521 if (mAttachInfo == null || mTooltipInfo == null) { 27522 return false; 27523 } 27524 if (fromLongClick && (mViewFlags & ENABLED_MASK) != ENABLED) { 27525 return false; 27526 } 27527 if (TextUtils.isEmpty(mTooltipInfo.mTooltipText)) { 27528 return false; 27529 } 27530 hideTooltip(); 27531 mTooltipInfo.mTooltipFromLongClick = fromLongClick; 27532 mTooltipInfo.mTooltipPopup = new TooltipPopup(getContext()); 27533 final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN; 27534 mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText); 27535 mAttachInfo.mTooltipHost = this; 27536 // The available accessibility actions have changed 27537 notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED); 27538 return true; 27539 } 27540 hideTooltip()27541 void hideTooltip() { 27542 if (mTooltipInfo == null) { 27543 return; 27544 } 27545 removeCallbacks(mTooltipInfo.mShowTooltipRunnable); 27546 if (mTooltipInfo.mTooltipPopup == null) { 27547 return; 27548 } 27549 mTooltipInfo.mTooltipPopup.hide(); 27550 mTooltipInfo.mTooltipPopup = null; 27551 mTooltipInfo.mTooltipFromLongClick = false; 27552 mTooltipInfo.clearAnchorPos(); 27553 if (mAttachInfo != null) { 27554 mAttachInfo.mTooltipHost = null; 27555 } 27556 // The available accessibility actions have changed 27557 notifyViewAccessibilityStateChangedIfNeeded(CONTENT_CHANGE_TYPE_UNDEFINED); 27558 } 27559 showLongClickTooltip(int x, int y)27560 private boolean showLongClickTooltip(int x, int y) { 27561 removeCallbacks(mTooltipInfo.mShowTooltipRunnable); 27562 removeCallbacks(mTooltipInfo.mHideTooltipRunnable); 27563 return showTooltip(x, y, true); 27564 } 27565 showHoverTooltip()27566 private boolean showHoverTooltip() { 27567 return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false); 27568 } 27569 dispatchTooltipHoverEvent(MotionEvent event)27570 boolean dispatchTooltipHoverEvent(MotionEvent event) { 27571 if (mTooltipInfo == null) { 27572 return false; 27573 } 27574 switch(event.getAction()) { 27575 case MotionEvent.ACTION_HOVER_MOVE: 27576 if ((mViewFlags & TOOLTIP) != TOOLTIP) { 27577 break; 27578 } 27579 if (!mTooltipInfo.mTooltipFromLongClick && mTooltipInfo.updateAnchorPos(event)) { 27580 if (mTooltipInfo.mTooltipPopup == null) { 27581 // Schedule showing the tooltip after a timeout. 27582 removeCallbacks(mTooltipInfo.mShowTooltipRunnable); 27583 postDelayed(mTooltipInfo.mShowTooltipRunnable, 27584 ViewConfiguration.getHoverTooltipShowTimeout()); 27585 } 27586 27587 // Hide hover-triggered tooltip after a period of inactivity. 27588 // Match the timeout used by NativeInputManager to hide the mouse pointer 27589 // (depends on SYSTEM_UI_FLAG_LOW_PROFILE being set). 27590 final int timeout; 27591 if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LOW_PROFILE) 27592 == SYSTEM_UI_FLAG_LOW_PROFILE) { 27593 timeout = ViewConfiguration.getHoverTooltipHideShortTimeout(); 27594 } else { 27595 timeout = ViewConfiguration.getHoverTooltipHideTimeout(); 27596 } 27597 removeCallbacks(mTooltipInfo.mHideTooltipRunnable); 27598 postDelayed(mTooltipInfo.mHideTooltipRunnable, timeout); 27599 } 27600 return true; 27601 27602 case MotionEvent.ACTION_HOVER_EXIT: 27603 mTooltipInfo.clearAnchorPos(); 27604 if (!mTooltipInfo.mTooltipFromLongClick) { 27605 hideTooltip(); 27606 } 27607 break; 27608 } 27609 return false; 27610 } 27611 handleTooltipKey(KeyEvent event)27612 void handleTooltipKey(KeyEvent event) { 27613 switch (event.getAction()) { 27614 case KeyEvent.ACTION_DOWN: 27615 if (event.getRepeatCount() == 0) { 27616 hideTooltip(); 27617 } 27618 break; 27619 27620 case KeyEvent.ACTION_UP: 27621 handleTooltipUp(); 27622 break; 27623 } 27624 } 27625 handleTooltipUp()27626 private void handleTooltipUp() { 27627 if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) { 27628 return; 27629 } 27630 removeCallbacks(mTooltipInfo.mHideTooltipRunnable); 27631 postDelayed(mTooltipInfo.mHideTooltipRunnable, 27632 ViewConfiguration.getLongPressTooltipHideTimeout()); 27633 } 27634 getFocusableAttribute(TypedArray attributes)27635 private int getFocusableAttribute(TypedArray attributes) { 27636 TypedValue val = new TypedValue(); 27637 if (attributes.getValue(com.android.internal.R.styleable.View_focusable, val)) { 27638 if (val.type == TypedValue.TYPE_INT_BOOLEAN) { 27639 return (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE); 27640 } else { 27641 return val.data; 27642 } 27643 } else { 27644 return FOCUSABLE_AUTO; 27645 } 27646 } 27647 27648 /** 27649 * @return The content view of the tooltip popup currently being shown, or null if the tooltip 27650 * is not showing. 27651 * @hide 27652 */ 27653 @TestApi getTooltipView()27654 public View getTooltipView() { 27655 if (mTooltipInfo == null || mTooltipInfo.mTooltipPopup == null) { 27656 return null; 27657 } 27658 return mTooltipInfo.mTooltipPopup.getContentView(); 27659 } 27660 27661 /** 27662 * @return {@code true} if the default focus highlight is enabled, {@code false} otherwies. 27663 * @hide 27664 */ 27665 @TestApi isDefaultFocusHighlightEnabled()27666 public static boolean isDefaultFocusHighlightEnabled() { 27667 return sUseDefaultFocusHighlight; 27668 } 27669 27670 /** 27671 * Dispatch a previously unhandled {@link KeyEvent} to this view. Unlike normal key dispatch, 27672 * this dispatches to ALL child views until it is consumed. The dispatch order is z-order 27673 * (visually on-top views first). 27674 * 27675 * @param evt the previously unhandled {@link KeyEvent}. 27676 * @return the {@link View} which consumed the event or {@code null} if not consumed. 27677 */ dispatchUnhandledKeyEvent(KeyEvent evt)27678 View dispatchUnhandledKeyEvent(KeyEvent evt) { 27679 if (onUnhandledKeyEvent(evt)) { 27680 return this; 27681 } 27682 return null; 27683 } 27684 27685 /** 27686 * Allows this view to handle {@link KeyEvent}s which weren't handled by normal dispatch. This 27687 * occurs after the normal view hierarchy dispatch, but before the window callback. By default, 27688 * this will dispatch into all the listeners registered via 27689 * {@link #addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener)} in last-in-first-out 27690 * order (most recently added will receive events first). 27691 * 27692 * @param event An unhandled event. 27693 * @return {@code true} if the event was handled, {@code false} otherwise. 27694 * @see #addOnUnhandledKeyEventListener 27695 */ onUnhandledKeyEvent(@onNull KeyEvent event)27696 boolean onUnhandledKeyEvent(@NonNull KeyEvent event) { 27697 if (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null) { 27698 for (int i = mListenerInfo.mUnhandledKeyListeners.size() - 1; i >= 0; --i) { 27699 if (mListenerInfo.mUnhandledKeyListeners.get(i).onUnhandledKeyEvent(this, event)) { 27700 return true; 27701 } 27702 } 27703 } 27704 return false; 27705 } 27706 hasUnhandledKeyListener()27707 boolean hasUnhandledKeyListener() { 27708 return (mListenerInfo != null && mListenerInfo.mUnhandledKeyListeners != null 27709 && !mListenerInfo.mUnhandledKeyListeners.isEmpty()); 27710 } 27711 27712 /** 27713 * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the 27714 * UI thread. 27715 * 27716 * @param listener a receiver of unhandled {@link KeyEvent}s. 27717 * @see #removeOnUnhandledKeyEventListener 27718 */ addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)27719 public void addOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) { 27720 ArrayList<OnUnhandledKeyEventListener> listeners = getListenerInfo().mUnhandledKeyListeners; 27721 if (listeners == null) { 27722 listeners = new ArrayList<>(); 27723 getListenerInfo().mUnhandledKeyListeners = listeners; 27724 } 27725 listeners.add(listener); 27726 if (listeners.size() == 1 && mParent instanceof ViewGroup) { 27727 ((ViewGroup) mParent).incrementChildUnhandledKeyListeners(); 27728 } 27729 } 27730 27731 /** 27732 * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the 27733 * UI thread. 27734 * 27735 * @param listener a receiver of unhandled {@link KeyEvent}s. 27736 * @see #addOnUnhandledKeyEventListener 27737 */ removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener)27738 public void removeOnUnhandledKeyEventListener(OnUnhandledKeyEventListener listener) { 27739 if (mListenerInfo != null) { 27740 if (mListenerInfo.mUnhandledKeyListeners != null 27741 && !mListenerInfo.mUnhandledKeyListeners.isEmpty()) { 27742 mListenerInfo.mUnhandledKeyListeners.remove(listener); 27743 if (mListenerInfo.mUnhandledKeyListeners.isEmpty()) { 27744 mListenerInfo.mUnhandledKeyListeners = null; 27745 if (mParent instanceof ViewGroup) { 27746 ((ViewGroup) mParent).decrementChildUnhandledKeyListeners(); 27747 } 27748 } 27749 } 27750 } 27751 } 27752 } 27753