1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.animation.AnimatorInflater; 20 import android.animation.StateListAnimator; 21 import android.annotation.CallSuper; 22 import android.annotation.ColorInt; 23 import android.annotation.DrawableRes; 24 import android.annotation.FloatRange; 25 import android.annotation.IdRes; 26 import android.annotation.IntDef; 27 import android.annotation.IntRange; 28 import android.annotation.LayoutRes; 29 import android.annotation.NonNull; 30 import android.annotation.Nullable; 31 import android.annotation.Size; 32 import android.annotation.UiThread; 33 import android.content.ClipData; 34 import android.content.Context; 35 import android.content.ContextWrapper; 36 import android.content.Intent; 37 import android.content.res.ColorStateList; 38 import android.content.res.Configuration; 39 import android.content.res.Resources; 40 import android.content.res.TypedArray; 41 import android.graphics.Bitmap; 42 import android.graphics.Canvas; 43 import android.graphics.Color; 44 import android.graphics.Insets; 45 import android.graphics.Interpolator; 46 import android.graphics.LinearGradient; 47 import android.graphics.Matrix; 48 import android.graphics.Outline; 49 import android.graphics.Paint; 50 import android.graphics.PixelFormat; 51 import android.graphics.Point; 52 import android.graphics.PorterDuff; 53 import android.graphics.PorterDuffXfermode; 54 import android.graphics.Rect; 55 import android.graphics.RectF; 56 import android.graphics.Region; 57 import android.graphics.Shader; 58 import android.graphics.drawable.ColorDrawable; 59 import android.graphics.drawable.Drawable; 60 import android.hardware.display.DisplayManagerGlobal; 61 import android.os.Build.VERSION_CODES; 62 import android.os.Bundle; 63 import android.os.Handler; 64 import android.os.IBinder; 65 import android.os.Parcel; 66 import android.os.Parcelable; 67 import android.os.RemoteException; 68 import android.os.SystemClock; 69 import android.os.SystemProperties; 70 import android.os.Trace; 71 import android.text.TextUtils; 72 import android.util.AttributeSet; 73 import android.util.FloatProperty; 74 import android.util.LayoutDirection; 75 import android.util.Log; 76 import android.util.LongSparseLongArray; 77 import android.util.Pools.SynchronizedPool; 78 import android.util.Property; 79 import android.util.SparseArray; 80 import android.util.StateSet; 81 import android.util.SuperNotCalledException; 82 import android.util.TypedValue; 83 import android.view.ContextMenu.ContextMenuInfo; 84 import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 85 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 86 import android.view.AccessibilityIterators.TextSegmentIterator; 87 import android.view.AccessibilityIterators.WordTextSegmentIterator; 88 import android.view.accessibility.AccessibilityEvent; 89 import android.view.accessibility.AccessibilityEventSource; 90 import android.view.accessibility.AccessibilityManager; 91 import android.view.accessibility.AccessibilityNodeInfo; 92 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 93 import android.view.accessibility.AccessibilityNodeProvider; 94 import android.view.animation.Animation; 95 import android.view.animation.AnimationUtils; 96 import android.view.animation.Transformation; 97 import android.view.inputmethod.EditorInfo; 98 import android.view.inputmethod.InputConnection; 99 import android.view.inputmethod.InputMethodManager; 100 import android.widget.Checkable; 101 import android.widget.FrameLayout; 102 import android.widget.ScrollBarDrawable; 103 import static android.os.Build.VERSION_CODES.*; 104 import static java.lang.Math.max; 105 106 import com.android.internal.R; 107 import com.android.internal.util.Predicate; 108 import com.android.internal.view.menu.MenuBuilder; 109 import com.android.internal.widget.ScrollBarUtils; 110 import com.google.android.collect.Lists; 111 import com.google.android.collect.Maps; 112 113 import java.lang.NullPointerException; 114 import java.lang.annotation.Retention; 115 import java.lang.annotation.RetentionPolicy; 116 import java.lang.ref.WeakReference; 117 import java.lang.reflect.Field; 118 import java.lang.reflect.InvocationTargetException; 119 import java.lang.reflect.Method; 120 import java.lang.reflect.Modifier; 121 import java.util.ArrayList; 122 import java.util.Arrays; 123 import java.util.Collections; 124 import java.util.HashMap; 125 import java.util.List; 126 import java.util.Locale; 127 import java.util.Map; 128 import java.util.concurrent.CopyOnWriteArrayList; 129 import java.util.concurrent.atomic.AtomicInteger; 130 131 /** 132 * <p> 133 * This class represents the basic building block for user interface components. A View 134 * occupies a rectangular area on the screen and is responsible for drawing and 135 * event handling. View is the base class for <em>widgets</em>, which are 136 * used to create interactive UI components (buttons, text fields, etc.). The 137 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 138 * are invisible containers that hold other Views (or other ViewGroups) and define 139 * their layout properties. 140 * </p> 141 * 142 * <div class="special reference"> 143 * <h3>Developer Guides</h3> 144 * <p>For information about using this class to develop your application's user interface, 145 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 146 * </div> 147 * 148 * <a name="Using"></a> 149 * <h3>Using Views</h3> 150 * <p> 151 * All of the views in a window are arranged in a single tree. You can add views 152 * either from code or by specifying a tree of views in one or more XML layout 153 * files. There are many specialized subclasses of views that act as controls or 154 * are capable of displaying text, images, or other content. 155 * </p> 156 * <p> 157 * Once you have created a tree of views, there are typically a few types of 158 * common operations you may wish to perform: 159 * <ul> 160 * <li><strong>Set properties:</strong> for example setting the text of a 161 * {@link android.widget.TextView}. The available properties and the methods 162 * that set them will vary among the different subclasses of views. Note that 163 * properties that are known at build time can be set in the XML layout 164 * files.</li> 165 * <li><strong>Set focus:</strong> The framework will handle moving focus in 166 * response to user input. To force focus to a specific view, call 167 * {@link #requestFocus}.</li> 168 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 169 * that will be notified when something interesting happens to the view. For 170 * example, all views will let you set a listener to be notified when the view 171 * gains or loses focus. You can register such a listener using 172 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 173 * Other view subclasses offer more specialized listeners. For example, a Button 174 * exposes a listener to notify clients when the button is clicked.</li> 175 * <li><strong>Set visibility:</strong> You can hide or show views using 176 * {@link #setVisibility(int)}.</li> 177 * </ul> 178 * </p> 179 * <p><em> 180 * Note: The Android framework is responsible for measuring, laying out and 181 * drawing views. You should not call methods that perform these actions on 182 * views yourself unless you are actually implementing a 183 * {@link android.view.ViewGroup}. 184 * </em></p> 185 * 186 * <a name="Lifecycle"></a> 187 * <h3>Implementing a Custom View</h3> 188 * 189 * <p> 190 * To implement a custom view, you will usually begin by providing overrides for 191 * some of the standard methods that the framework calls on all views. You do 192 * not need to override all of these methods. In fact, you can start by just 193 * overriding {@link #onDraw(android.graphics.Canvas)}. 194 * <table border="2" width="85%" align="center" cellpadding="5"> 195 * <thead> 196 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 197 * </thead> 198 * 199 * <tbody> 200 * <tr> 201 * <td rowspan="2">Creation</td> 202 * <td>Constructors</td> 203 * <td>There is a form of the constructor that are called when the view 204 * is created from code and a form that is called when the view is 205 * inflated from a layout file. The second form should parse and apply 206 * any attributes defined in the layout file. 207 * </td> 208 * </tr> 209 * <tr> 210 * <td><code>{@link #onFinishInflate()}</code></td> 211 * <td>Called after a view and all of its children has been inflated 212 * from XML.</td> 213 * </tr> 214 * 215 * <tr> 216 * <td rowspan="3">Layout</td> 217 * <td><code>{@link #onMeasure(int, int)}</code></td> 218 * <td>Called to determine the size requirements for this view and all 219 * of its children. 220 * </td> 221 * </tr> 222 * <tr> 223 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 224 * <td>Called when this view should assign a size and position to all 225 * of its children. 226 * </td> 227 * </tr> 228 * <tr> 229 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 230 * <td>Called when the size of this view has changed. 231 * </td> 232 * </tr> 233 * 234 * <tr> 235 * <td>Drawing</td> 236 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 237 * <td>Called when the view should render its content. 238 * </td> 239 * </tr> 240 * 241 * <tr> 242 * <td rowspan="4">Event processing</td> 243 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 244 * <td>Called when a new hardware key event occurs. 245 * </td> 246 * </tr> 247 * <tr> 248 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 249 * <td>Called when a hardware key up event occurs. 250 * </td> 251 * </tr> 252 * <tr> 253 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 254 * <td>Called when a trackball motion event occurs. 255 * </td> 256 * </tr> 257 * <tr> 258 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 259 * <td>Called when a touch screen motion event occurs. 260 * </td> 261 * </tr> 262 * 263 * <tr> 264 * <td rowspan="2">Focus</td> 265 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 266 * <td>Called when the view gains or loses focus. 267 * </td> 268 * </tr> 269 * 270 * <tr> 271 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 272 * <td>Called when the window containing the view gains or loses focus. 273 * </td> 274 * </tr> 275 * 276 * <tr> 277 * <td rowspan="3">Attaching</td> 278 * <td><code>{@link #onAttachedToWindow()}</code></td> 279 * <td>Called when the view is attached to a window. 280 * </td> 281 * </tr> 282 * 283 * <tr> 284 * <td><code>{@link #onDetachedFromWindow}</code></td> 285 * <td>Called when the view is detached from its window. 286 * </td> 287 * </tr> 288 * 289 * <tr> 290 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 291 * <td>Called when the visibility of the window containing the view 292 * has changed. 293 * </td> 294 * </tr> 295 * </tbody> 296 * 297 * </table> 298 * </p> 299 * 300 * <a name="IDs"></a> 301 * <h3>IDs</h3> 302 * Views may have an integer id associated with them. These ids are typically 303 * assigned in the layout XML files, and are used to find specific views within 304 * the view tree. A common pattern is to: 305 * <ul> 306 * <li>Define a Button in the layout file and assign it a unique ID. 307 * <pre> 308 * <Button 309 * android:id="@+id/my_button" 310 * android:layout_width="wrap_content" 311 * android:layout_height="wrap_content" 312 * android:text="@string/my_button_text"/> 313 * </pre></li> 314 * <li>From the onCreate method of an Activity, find the Button 315 * <pre class="prettyprint"> 316 * Button myButton = (Button) findViewById(R.id.my_button); 317 * </pre></li> 318 * </ul> 319 * <p> 320 * View IDs need not be unique throughout the tree, but it is good practice to 321 * ensure that they are at least unique within the part of the tree you are 322 * searching. 323 * </p> 324 * 325 * <a name="Position"></a> 326 * <h3>Position</h3> 327 * <p> 328 * The geometry of a view is that of a rectangle. A view has a location, 329 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 330 * two dimensions, expressed as a width and a height. The unit for location 331 * and dimensions is the pixel. 332 * </p> 333 * 334 * <p> 335 * It is possible to retrieve the location of a view by invoking the methods 336 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 337 * coordinate of the rectangle representing the view. The latter returns the 338 * top, or Y, coordinate of the rectangle representing the view. These methods 339 * both return the location of the view relative to its parent. For instance, 340 * when getLeft() returns 20, that means the view is located 20 pixels to the 341 * right of the left edge of its direct parent. 342 * </p> 343 * 344 * <p> 345 * In addition, several convenience methods are offered to avoid unnecessary 346 * computations, namely {@link #getRight()} and {@link #getBottom()}. 347 * These methods return the coordinates of the right and bottom edges of the 348 * rectangle representing the view. For instance, calling {@link #getRight()} 349 * is similar to the following computation: <code>getLeft() + getWidth()</code> 350 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 351 * </p> 352 * 353 * <a name="SizePaddingMargins"></a> 354 * <h3>Size, padding and margins</h3> 355 * <p> 356 * The size of a view is expressed with a width and a height. A view actually 357 * possess two pairs of width and height values. 358 * </p> 359 * 360 * <p> 361 * The first pair is known as <em>measured width</em> and 362 * <em>measured height</em>. These dimensions define how big a view wants to be 363 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 364 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 365 * and {@link #getMeasuredHeight()}. 366 * </p> 367 * 368 * <p> 369 * The second pair is simply known as <em>width</em> and <em>height</em>, or 370 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 371 * dimensions define the actual size of the view on screen, at drawing time and 372 * after layout. These values may, but do not have to, be different from the 373 * measured width and height. The width and height can be obtained by calling 374 * {@link #getWidth()} and {@link #getHeight()}. 375 * </p> 376 * 377 * <p> 378 * To measure its dimensions, a view takes into account its padding. The padding 379 * is expressed in pixels for the left, top, right and bottom parts of the view. 380 * Padding can be used to offset the content of the view by a specific amount of 381 * pixels. For instance, a left padding of 2 will push the view's content by 382 * 2 pixels to the right of the left edge. Padding can be set using the 383 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 384 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 385 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 386 * {@link #getPaddingEnd()}. 387 * </p> 388 * 389 * <p> 390 * Even though a view can define a padding, it does not provide any support for 391 * margins. However, view groups provide such a support. Refer to 392 * {@link android.view.ViewGroup} and 393 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 394 * </p> 395 * 396 * <a name="Layout"></a> 397 * <h3>Layout</h3> 398 * <p> 399 * Layout is a two pass process: a measure pass and a layout pass. The measuring 400 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 401 * of the view tree. Each view pushes dimension specifications down the tree 402 * during the recursion. At the end of the measure pass, every view has stored 403 * its measurements. The second pass happens in 404 * {@link #layout(int,int,int,int)} and is also top-down. During 405 * this pass each parent is responsible for positioning all of its children 406 * using the sizes computed in the measure pass. 407 * </p> 408 * 409 * <p> 410 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 411 * {@link #getMeasuredHeight()} values must be set, along with those for all of 412 * that view's descendants. A view's measured width and measured height values 413 * must respect the constraints imposed by the view's parents. This guarantees 414 * that at the end of the measure pass, all parents accept all of their 415 * children's measurements. A parent view may call measure() more than once on 416 * its children. For example, the parent may measure each child once with 417 * unspecified dimensions to find out how big they want to be, then call 418 * measure() on them again with actual numbers if the sum of all the children's 419 * unconstrained sizes is too big or too small. 420 * </p> 421 * 422 * <p> 423 * The measure pass uses two classes to communicate dimensions. The 424 * {@link MeasureSpec} class is used by views to tell their parents how they 425 * want to be measured and positioned. The base LayoutParams class just 426 * describes how big the view wants to be for both width and height. For each 427 * dimension, it can specify one of: 428 * <ul> 429 * <li> an exact number 430 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 431 * (minus padding) 432 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 433 * enclose its content (plus padding). 434 * </ul> 435 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 436 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 437 * an X and Y value. 438 * </p> 439 * 440 * <p> 441 * MeasureSpecs are used to push requirements down the tree from parent to 442 * child. A MeasureSpec can be in one of three modes: 443 * <ul> 444 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 445 * of a child view. For example, a LinearLayout may call measure() on its child 446 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 447 * tall the child view wants to be given a width of 240 pixels. 448 * <li>EXACTLY: This is used by the parent to impose an exact size on the 449 * child. The child must use this size, and guarantee that all of its 450 * descendants will fit within this size. 451 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 452 * child. The child must guarantee that it and all of its descendants will fit 453 * within this size. 454 * </ul> 455 * </p> 456 * 457 * <p> 458 * To initiate a layout, call {@link #requestLayout}. This method is typically 459 * called by a view on itself when it believes that is can no longer fit within 460 * its current bounds. 461 * </p> 462 * 463 * <a name="Drawing"></a> 464 * <h3>Drawing</h3> 465 * <p> 466 * Drawing is handled by walking the tree and recording the drawing commands of 467 * any View that needs to update. After this, the drawing commands of the 468 * entire tree are issued to screen, clipped to the newly damaged area. 469 * </p> 470 * 471 * <p> 472 * The tree is largely recorded and drawn in order, with parents drawn before 473 * (i.e., behind) their children, with siblings drawn in the order they appear 474 * in the tree. If you set a background drawable for a View, then the View will 475 * draw it before calling back to its <code>onDraw()</code> method. The child 476 * drawing order can be overridden with 477 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order} 478 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views. 479 * </p> 480 * 481 * <p> 482 * To force a view to draw, call {@link #invalidate()}. 483 * </p> 484 * 485 * <a name="EventHandlingThreading"></a> 486 * <h3>Event Handling and Threading</h3> 487 * <p> 488 * The basic cycle of a view is as follows: 489 * <ol> 490 * <li>An event comes in and is dispatched to the appropriate view. The view 491 * handles the event and notifies any listeners.</li> 492 * <li>If in the course of processing the event, the view's bounds may need 493 * to be changed, the view will call {@link #requestLayout()}.</li> 494 * <li>Similarly, if in the course of processing the event the view's appearance 495 * may need to be changed, the view will call {@link #invalidate()}.</li> 496 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 497 * the framework will take care of measuring, laying out, and drawing the tree 498 * as appropriate.</li> 499 * </ol> 500 * </p> 501 * 502 * <p><em>Note: The entire view tree is single threaded. You must always be on 503 * the UI thread when calling any method on any view.</em> 504 * If you are doing work on other threads and want to update the state of a view 505 * from that thread, you should use a {@link Handler}. 506 * </p> 507 * 508 * <a name="FocusHandling"></a> 509 * <h3>Focus Handling</h3> 510 * <p> 511 * The framework will handle routine focus movement in response to user input. 512 * This includes changing the focus as views are removed or hidden, or as new 513 * views become available. Views indicate their willingness to take focus 514 * through the {@link #isFocusable} method. To change whether a view can take 515 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 516 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 517 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 518 * </p> 519 * <p> 520 * Focus movement is based on an algorithm which finds the nearest neighbor in a 521 * given direction. In rare cases, the default algorithm may not match the 522 * intended behavior of the developer. In these situations, you can provide 523 * explicit overrides by using these XML attributes in the layout file: 524 * <pre> 525 * nextFocusDown 526 * nextFocusLeft 527 * nextFocusRight 528 * nextFocusUp 529 * </pre> 530 * </p> 531 * 532 * 533 * <p> 534 * To get a particular view to take focus, call {@link #requestFocus()}. 535 * </p> 536 * 537 * <a name="TouchMode"></a> 538 * <h3>Touch Mode</h3> 539 * <p> 540 * When a user is navigating a user interface via directional keys such as a D-pad, it is 541 * necessary to give focus to actionable items such as buttons so the user can see 542 * what will take input. If the device has touch capabilities, however, and the user 543 * begins interacting with the interface by touching it, it is no longer necessary to 544 * always highlight, or give focus to, a particular view. This motivates a mode 545 * for interaction named 'touch mode'. 546 * </p> 547 * <p> 548 * For a touch capable device, once the user touches the screen, the device 549 * will enter touch mode. From this point onward, only views for which 550 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 551 * Other views that are touchable, like buttons, will not take focus when touched; they will 552 * only fire the on click listeners. 553 * </p> 554 * <p> 555 * Any time a user hits a directional key, such as a D-pad direction, the view device will 556 * exit touch mode, and find a view to take focus, so that the user may resume interacting 557 * with the user interface without touching the screen again. 558 * </p> 559 * <p> 560 * The touch mode state is maintained across {@link android.app.Activity}s. Call 561 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 562 * </p> 563 * 564 * <a name="Scrolling"></a> 565 * <h3>Scrolling</h3> 566 * <p> 567 * The framework provides basic support for views that wish to internally 568 * scroll their content. This includes keeping track of the X and Y scroll 569 * offset as well as mechanisms for drawing scrollbars. See 570 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 571 * {@link #awakenScrollBars()} for more details. 572 * </p> 573 * 574 * <a name="Tags"></a> 575 * <h3>Tags</h3> 576 * <p> 577 * Unlike IDs, tags are not used to identify views. Tags are essentially an 578 * extra piece of information that can be associated with a view. They are most 579 * often used as a convenience to store data related to views in the views 580 * themselves rather than by putting them in a separate structure. 581 * </p> 582 * <p> 583 * Tags may be specified with character sequence values in layout XML as either 584 * a single tag using the {@link android.R.styleable#View_tag android:tag} 585 * attribute or multiple tags using the {@code <tag>} child element: 586 * <pre> 587 * <View ... 588 * android:tag="@string/mytag_value" /> 589 * <View ...> 590 * <tag android:id="@+id/mytag" 591 * android:value="@string/mytag_value" /> 592 * </View> 593 * </pre> 594 * </p> 595 * <p> 596 * Tags may also be specified with arbitrary objects from code using 597 * {@link #setTag(Object)} or {@link #setTag(int, Object)}. 598 * </p> 599 * 600 * <a name="Themes"></a> 601 * <h3>Themes</h3> 602 * <p> 603 * By default, Views are created using the theme of the Context object supplied 604 * to their constructor; however, a different theme may be specified by using 605 * the {@link android.R.styleable#View_theme android:theme} attribute in layout 606 * XML or by passing a {@link ContextThemeWrapper} to the constructor from 607 * code. 608 * </p> 609 * <p> 610 * When the {@link android.R.styleable#View_theme android:theme} attribute is 611 * used in XML, the specified theme is applied on top of the inflation 612 * context's theme (see {@link LayoutInflater}) and used for the view itself as 613 * well as any child elements. 614 * </p> 615 * <p> 616 * In the following example, both views will be created using the Material dark 617 * color scheme; however, because an overlay theme is used which only defines a 618 * subset of attributes, the value of 619 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on 620 * the inflation context's theme (e.g. the Activity theme) will be preserved. 621 * <pre> 622 * <LinearLayout 623 * ... 624 * android:theme="@android:theme/ThemeOverlay.Material.Dark"> 625 * <View ...> 626 * </LinearLayout> 627 * </pre> 628 * </p> 629 * 630 * <a name="Properties"></a> 631 * <h3>Properties</h3> 632 * <p> 633 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 634 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 635 * available both in the {@link Property} form as well as in similarly-named setter/getter 636 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 637 * be used to set persistent state associated with these rendering-related properties on the view. 638 * The properties and methods can also be used in conjunction with 639 * {@link android.animation.Animator Animator}-based animations, described more in the 640 * <a href="#Animation">Animation</a> section. 641 * </p> 642 * 643 * <a name="Animation"></a> 644 * <h3>Animation</h3> 645 * <p> 646 * Starting with Android 3.0, the preferred way of animating views is to use the 647 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 648 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 649 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 650 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 651 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 652 * makes animating these View properties particularly easy and efficient. 653 * </p> 654 * <p> 655 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 656 * You can attach an {@link Animation} object to a view using 657 * {@link #setAnimation(Animation)} or 658 * {@link #startAnimation(Animation)}. The animation can alter the scale, 659 * rotation, translation and alpha of a view over time. If the animation is 660 * attached to a view that has children, the animation will affect the entire 661 * subtree rooted by that node. When an animation is started, the framework will 662 * take care of redrawing the appropriate views until the animation completes. 663 * </p> 664 * 665 * <a name="Security"></a> 666 * <h3>Security</h3> 667 * <p> 668 * Sometimes it is essential that an application be able to verify that an action 669 * is being performed with the full knowledge and consent of the user, such as 670 * granting a permission request, making a purchase or clicking on an advertisement. 671 * Unfortunately, a malicious application could try to spoof the user into 672 * performing these actions, unaware, by concealing the intended purpose of the view. 673 * As a remedy, the framework offers a touch filtering mechanism that can be used to 674 * improve the security of views that provide access to sensitive functionality. 675 * </p><p> 676 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 677 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 678 * will discard touches that are received whenever the view's window is obscured by 679 * another visible window. As a result, the view will not receive touches whenever a 680 * toast, dialog or other window appears above the view's window. 681 * </p><p> 682 * For more fine-grained control over security, consider overriding the 683 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 684 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 685 * </p> 686 * 687 * @attr ref android.R.styleable#View_alpha 688 * @attr ref android.R.styleable#View_background 689 * @attr ref android.R.styleable#View_clickable 690 * @attr ref android.R.styleable#View_contentDescription 691 * @attr ref android.R.styleable#View_drawingCacheQuality 692 * @attr ref android.R.styleable#View_duplicateParentState 693 * @attr ref android.R.styleable#View_id 694 * @attr ref android.R.styleable#View_requiresFadingEdge 695 * @attr ref android.R.styleable#View_fadeScrollbars 696 * @attr ref android.R.styleable#View_fadingEdgeLength 697 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 698 * @attr ref android.R.styleable#View_fitsSystemWindows 699 * @attr ref android.R.styleable#View_isScrollContainer 700 * @attr ref android.R.styleable#View_focusable 701 * @attr ref android.R.styleable#View_focusableInTouchMode 702 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 703 * @attr ref android.R.styleable#View_keepScreenOn 704 * @attr ref android.R.styleable#View_layerType 705 * @attr ref android.R.styleable#View_layoutDirection 706 * @attr ref android.R.styleable#View_longClickable 707 * @attr ref android.R.styleable#View_minHeight 708 * @attr ref android.R.styleable#View_minWidth 709 * @attr ref android.R.styleable#View_nextFocusDown 710 * @attr ref android.R.styleable#View_nextFocusLeft 711 * @attr ref android.R.styleable#View_nextFocusRight 712 * @attr ref android.R.styleable#View_nextFocusUp 713 * @attr ref android.R.styleable#View_onClick 714 * @attr ref android.R.styleable#View_padding 715 * @attr ref android.R.styleable#View_paddingBottom 716 * @attr ref android.R.styleable#View_paddingLeft 717 * @attr ref android.R.styleable#View_paddingRight 718 * @attr ref android.R.styleable#View_paddingTop 719 * @attr ref android.R.styleable#View_paddingStart 720 * @attr ref android.R.styleable#View_paddingEnd 721 * @attr ref android.R.styleable#View_saveEnabled 722 * @attr ref android.R.styleable#View_rotation 723 * @attr ref android.R.styleable#View_rotationX 724 * @attr ref android.R.styleable#View_rotationY 725 * @attr ref android.R.styleable#View_scaleX 726 * @attr ref android.R.styleable#View_scaleY 727 * @attr ref android.R.styleable#View_scrollX 728 * @attr ref android.R.styleable#View_scrollY 729 * @attr ref android.R.styleable#View_scrollbarSize 730 * @attr ref android.R.styleable#View_scrollbarStyle 731 * @attr ref android.R.styleable#View_scrollbars 732 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 733 * @attr ref android.R.styleable#View_scrollbarFadeDuration 734 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 735 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 736 * @attr ref android.R.styleable#View_scrollbarThumbVertical 737 * @attr ref android.R.styleable#View_scrollbarTrackVertical 738 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 739 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 740 * @attr ref android.R.styleable#View_stateListAnimator 741 * @attr ref android.R.styleable#View_transitionName 742 * @attr ref android.R.styleable#View_soundEffectsEnabled 743 * @attr ref android.R.styleable#View_tag 744 * @attr ref android.R.styleable#View_textAlignment 745 * @attr ref android.R.styleable#View_textDirection 746 * @attr ref android.R.styleable#View_transformPivotX 747 * @attr ref android.R.styleable#View_transformPivotY 748 * @attr ref android.R.styleable#View_translationX 749 * @attr ref android.R.styleable#View_translationY 750 * @attr ref android.R.styleable#View_translationZ 751 * @attr ref android.R.styleable#View_visibility 752 * @attr ref android.R.styleable#View_theme 753 * 754 * @see android.view.ViewGroup 755 */ 756 @UiThread 757 public class View implements Drawable.Callback, KeyEvent.Callback, 758 AccessibilityEventSource { 759 private static final boolean DBG = false; 760 761 /** 762 * The logging tag used by this class with android.util.Log. 763 */ 764 protected static final String VIEW_LOG_TAG = "View"; 765 766 /** 767 * When set to true, apps will draw debugging information about their layouts. 768 * 769 * @hide 770 */ 771 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 772 773 /** 774 * When set to true, this view will save its attribute data. 775 * 776 * @hide 777 */ 778 public static boolean mDebugViewAttributes = false; 779 780 /** 781 * Used to mark a View that has no ID. 782 */ 783 public static final int NO_ID = -1; 784 785 /** 786 * Signals that compatibility booleans have been initialized according to 787 * target SDK versions. 788 */ 789 private static boolean sCompatibilityDone = false; 790 791 /** 792 * Use the old (broken) way of building MeasureSpecs. 793 */ 794 private static boolean sUseBrokenMakeMeasureSpec = false; 795 796 /** 797 * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED 798 */ 799 static boolean sUseZeroUnspecifiedMeasureSpec = false; 800 801 /** 802 * Ignore any optimizations using the measure cache. 803 */ 804 private static boolean sIgnoreMeasureCache = false; 805 806 /** 807 * Ignore an optimization that skips unnecessary EXACTLY layout passes. 808 */ 809 private static boolean sAlwaysRemeasureExactly = false; 810 811 /** 812 * Relax constraints around whether setLayoutParams() must be called after 813 * modifying the layout params. 814 */ 815 private static boolean sLayoutParamsAlwaysChanged = false; 816 817 /** 818 * Allow setForeground/setBackground to be called (and ignored) on a textureview, 819 * without throwing 820 */ 821 static boolean sTextureViewIgnoresDrawableSetters = false; 822 823 /** 824 * Prior to N, some ViewGroups would not convert LayoutParams properly even though both extend 825 * MarginLayoutParams. For instance, converting LinearLayout.LayoutParams to 826 * RelativeLayout.LayoutParams would lose margin information. This is fixed on N but target API 827 * check is implemented for backwards compatibility. 828 * 829 * {@hide} 830 */ 831 protected static boolean sPreserveMarginParamsInLayoutParamConversion; 832 833 /** 834 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 835 * calling setFlags. 836 */ 837 private static final int NOT_FOCUSABLE = 0x00000000; 838 839 /** 840 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 841 * setFlags. 842 */ 843 private static final int FOCUSABLE = 0x00000001; 844 845 /** 846 * Mask for use with setFlags indicating bits used for focus. 847 */ 848 private static final int FOCUSABLE_MASK = 0x00000001; 849 850 /** 851 * This view will adjust its padding to fit sytem windows (e.g. status bar) 852 */ 853 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 854 855 /** @hide */ 856 @IntDef({VISIBLE, INVISIBLE, GONE}) 857 @Retention(RetentionPolicy.SOURCE) 858 public @interface Visibility {} 859 860 /** 861 * This view is visible. 862 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 863 * android:visibility}. 864 */ 865 public static final int VISIBLE = 0x00000000; 866 867 /** 868 * This view is invisible, but it still takes up space for layout purposes. 869 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 870 * android:visibility}. 871 */ 872 public static final int INVISIBLE = 0x00000004; 873 874 /** 875 * This view is invisible, and it doesn't take any space for layout 876 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 877 * android:visibility}. 878 */ 879 public static final int GONE = 0x00000008; 880 881 /** 882 * Mask for use with setFlags indicating bits used for visibility. 883 * {@hide} 884 */ 885 static final int VISIBILITY_MASK = 0x0000000C; 886 887 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 888 889 /** 890 * This view is enabled. Interpretation varies by subclass. 891 * Use with ENABLED_MASK when calling setFlags. 892 * {@hide} 893 */ 894 static final int ENABLED = 0x00000000; 895 896 /** 897 * This view is disabled. Interpretation varies by subclass. 898 * Use with ENABLED_MASK when calling setFlags. 899 * {@hide} 900 */ 901 static final int DISABLED = 0x00000020; 902 903 /** 904 * Mask for use with setFlags indicating bits used for indicating whether 905 * this view is enabled 906 * {@hide} 907 */ 908 static final int ENABLED_MASK = 0x00000020; 909 910 /** 911 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 912 * called and further optimizations will be performed. It is okay to have 913 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 914 * {@hide} 915 */ 916 static final int WILL_NOT_DRAW = 0x00000080; 917 918 /** 919 * Mask for use with setFlags indicating bits used for indicating whether 920 * this view is will draw 921 * {@hide} 922 */ 923 static final int DRAW_MASK = 0x00000080; 924 925 /** 926 * <p>This view doesn't show scrollbars.</p> 927 * {@hide} 928 */ 929 static final int SCROLLBARS_NONE = 0x00000000; 930 931 /** 932 * <p>This view shows horizontal scrollbars.</p> 933 * {@hide} 934 */ 935 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 936 937 /** 938 * <p>This view shows vertical scrollbars.</p> 939 * {@hide} 940 */ 941 static final int SCROLLBARS_VERTICAL = 0x00000200; 942 943 /** 944 * <p>Mask for use with setFlags indicating bits used for indicating which 945 * scrollbars are enabled.</p> 946 * {@hide} 947 */ 948 static final int SCROLLBARS_MASK = 0x00000300; 949 950 /** 951 * Indicates that the view should filter touches when its window is obscured. 952 * Refer to the class comments for more information about this security feature. 953 * {@hide} 954 */ 955 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 956 957 /** 958 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 959 * that they are optional and should be skipped if the window has 960 * requested system UI flags that ignore those insets for layout. 961 */ 962 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 963 964 /** 965 * <p>This view doesn't show fading edges.</p> 966 * {@hide} 967 */ 968 static final int FADING_EDGE_NONE = 0x00000000; 969 970 /** 971 * <p>This view shows horizontal fading edges.</p> 972 * {@hide} 973 */ 974 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 975 976 /** 977 * <p>This view shows vertical fading edges.</p> 978 * {@hide} 979 */ 980 static final int FADING_EDGE_VERTICAL = 0x00002000; 981 982 /** 983 * <p>Mask for use with setFlags indicating bits used for indicating which 984 * fading edges are enabled.</p> 985 * {@hide} 986 */ 987 static final int FADING_EDGE_MASK = 0x00003000; 988 989 /** 990 * <p>Indicates this view can be clicked. When clickable, a View reacts 991 * to clicks by notifying the OnClickListener.<p> 992 * {@hide} 993 */ 994 static final int CLICKABLE = 0x00004000; 995 996 /** 997 * <p>Indicates this view is caching its drawing into a bitmap.</p> 998 * {@hide} 999 */ 1000 static final int DRAWING_CACHE_ENABLED = 0x00008000; 1001 1002 /** 1003 * <p>Indicates that no icicle should be saved for this view.<p> 1004 * {@hide} 1005 */ 1006 static final int SAVE_DISABLED = 0x000010000; 1007 1008 /** 1009 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 1010 * property.</p> 1011 * {@hide} 1012 */ 1013 static final int SAVE_DISABLED_MASK = 0x000010000; 1014 1015 /** 1016 * <p>Indicates that no drawing cache should ever be created for this view.<p> 1017 * {@hide} 1018 */ 1019 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 1020 1021 /** 1022 * <p>Indicates this view can take / keep focus when int touch mode.</p> 1023 * {@hide} 1024 */ 1025 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 1026 1027 /** @hide */ 1028 @Retention(RetentionPolicy.SOURCE) 1029 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO}) 1030 public @interface DrawingCacheQuality {} 1031 1032 /** 1033 * <p>Enables low quality mode for the drawing cache.</p> 1034 */ 1035 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 1036 1037 /** 1038 * <p>Enables high quality mode for the drawing cache.</p> 1039 */ 1040 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 1041 1042 /** 1043 * <p>Enables automatic quality mode for the drawing cache.</p> 1044 */ 1045 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 1046 1047 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 1048 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 1049 }; 1050 1051 /** 1052 * <p>Mask for use with setFlags indicating bits used for the cache 1053 * quality property.</p> 1054 * {@hide} 1055 */ 1056 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 1057 1058 /** 1059 * <p> 1060 * Indicates this view can be long clicked. When long clickable, a View 1061 * reacts to long clicks by notifying the OnLongClickListener or showing a 1062 * context menu. 1063 * </p> 1064 * {@hide} 1065 */ 1066 static final int LONG_CLICKABLE = 0x00200000; 1067 1068 /** 1069 * <p>Indicates that this view gets its drawable states from its direct parent 1070 * and ignores its original internal states.</p> 1071 * 1072 * @hide 1073 */ 1074 static final int DUPLICATE_PARENT_STATE = 0x00400000; 1075 1076 /** 1077 * <p> 1078 * Indicates this view can be context clicked. When context clickable, a View reacts to a 1079 * context click (e.g. a primary stylus button press or right mouse click) by notifying the 1080 * OnContextClickListener. 1081 * </p> 1082 * {@hide} 1083 */ 1084 static final int CONTEXT_CLICKABLE = 0x00800000; 1085 1086 1087 /** @hide */ 1088 @IntDef({ 1089 SCROLLBARS_INSIDE_OVERLAY, 1090 SCROLLBARS_INSIDE_INSET, 1091 SCROLLBARS_OUTSIDE_OVERLAY, 1092 SCROLLBARS_OUTSIDE_INSET 1093 }) 1094 @Retention(RetentionPolicy.SOURCE) 1095 public @interface ScrollBarStyle {} 1096 1097 /** 1098 * The scrollbar style to display the scrollbars inside the content area, 1099 * without increasing the padding. The scrollbars will be overlaid with 1100 * translucency on the view's content. 1101 */ 1102 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 1103 1104 /** 1105 * The scrollbar style to display the scrollbars inside the padded area, 1106 * increasing the padding of the view. The scrollbars will not overlap the 1107 * content area of the view. 1108 */ 1109 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 1110 1111 /** 1112 * The scrollbar style to display the scrollbars at the edge of the view, 1113 * without increasing the padding. The scrollbars will be overlaid with 1114 * translucency. 1115 */ 1116 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 1117 1118 /** 1119 * The scrollbar style to display the scrollbars at the edge of the view, 1120 * increasing the padding of the view. The scrollbars will only overlap the 1121 * background, if any. 1122 */ 1123 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 1124 1125 /** 1126 * Mask to check if the scrollbar style is overlay or inset. 1127 * {@hide} 1128 */ 1129 static final int SCROLLBARS_INSET_MASK = 0x01000000; 1130 1131 /** 1132 * Mask to check if the scrollbar style is inside or outside. 1133 * {@hide} 1134 */ 1135 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 1136 1137 /** 1138 * Mask for scrollbar style. 1139 * {@hide} 1140 */ 1141 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 1142 1143 /** 1144 * View flag indicating that the screen should remain on while the 1145 * window containing this view is visible to the user. This effectively 1146 * takes care of automatically setting the WindowManager's 1147 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 1148 */ 1149 public static final int KEEP_SCREEN_ON = 0x04000000; 1150 1151 /** 1152 * View flag indicating whether this view should have sound effects enabled 1153 * for events such as clicking and touching. 1154 */ 1155 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1156 1157 /** 1158 * View flag indicating whether this view should have haptic feedback 1159 * enabled for events such as long presses. 1160 */ 1161 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1162 1163 /** 1164 * <p>Indicates that the view hierarchy should stop saving state when 1165 * it reaches this view. If state saving is initiated immediately at 1166 * the view, it will be allowed. 1167 * {@hide} 1168 */ 1169 static final int PARENT_SAVE_DISABLED = 0x20000000; 1170 1171 /** 1172 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1173 * {@hide} 1174 */ 1175 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1176 1177 /** @hide */ 1178 @IntDef(flag = true, 1179 value = { 1180 FOCUSABLES_ALL, 1181 FOCUSABLES_TOUCH_MODE 1182 }) 1183 @Retention(RetentionPolicy.SOURCE) 1184 public @interface FocusableMode {} 1185 1186 /** 1187 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1188 * should add all focusable Views regardless if they are focusable in touch mode. 1189 */ 1190 public static final int FOCUSABLES_ALL = 0x00000000; 1191 1192 /** 1193 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1194 * should add only Views focusable in touch mode. 1195 */ 1196 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1197 1198 /** @hide */ 1199 @IntDef({ 1200 FOCUS_BACKWARD, 1201 FOCUS_FORWARD, 1202 FOCUS_LEFT, 1203 FOCUS_UP, 1204 FOCUS_RIGHT, 1205 FOCUS_DOWN 1206 }) 1207 @Retention(RetentionPolicy.SOURCE) 1208 public @interface FocusDirection {} 1209 1210 /** @hide */ 1211 @IntDef({ 1212 FOCUS_LEFT, 1213 FOCUS_UP, 1214 FOCUS_RIGHT, 1215 FOCUS_DOWN 1216 }) 1217 @Retention(RetentionPolicy.SOURCE) 1218 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward 1219 1220 /** 1221 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1222 * item. 1223 */ 1224 public static final int FOCUS_BACKWARD = 0x00000001; 1225 1226 /** 1227 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1228 * item. 1229 */ 1230 public static final int FOCUS_FORWARD = 0x00000002; 1231 1232 /** 1233 * Use with {@link #focusSearch(int)}. Move focus to the left. 1234 */ 1235 public static final int FOCUS_LEFT = 0x00000011; 1236 1237 /** 1238 * Use with {@link #focusSearch(int)}. Move focus up. 1239 */ 1240 public static final int FOCUS_UP = 0x00000021; 1241 1242 /** 1243 * Use with {@link #focusSearch(int)}. Move focus to the right. 1244 */ 1245 public static final int FOCUS_RIGHT = 0x00000042; 1246 1247 /** 1248 * Use with {@link #focusSearch(int)}. Move focus down. 1249 */ 1250 public static final int FOCUS_DOWN = 0x00000082; 1251 1252 /** 1253 * Bits of {@link #getMeasuredWidthAndState()} and 1254 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1255 */ 1256 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1257 1258 /** 1259 * Bits of {@link #getMeasuredWidthAndState()} and 1260 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1261 */ 1262 public static final int MEASURED_STATE_MASK = 0xff000000; 1263 1264 /** 1265 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1266 * for functions that combine both width and height into a single int, 1267 * such as {@link #getMeasuredState()} and the childState argument of 1268 * {@link #resolveSizeAndState(int, int, int)}. 1269 */ 1270 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1271 1272 /** 1273 * Bit of {@link #getMeasuredWidthAndState()} and 1274 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1275 * is smaller that the space the view would like to have. 1276 */ 1277 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1278 1279 /** 1280 * Base View state sets 1281 */ 1282 // Singles 1283 /** 1284 * Indicates the view has no states set. States are used with 1285 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1286 * view depending on its state. 1287 * 1288 * @see android.graphics.drawable.Drawable 1289 * @see #getDrawableState() 1290 */ 1291 protected static final int[] EMPTY_STATE_SET; 1292 /** 1293 * Indicates the view is enabled. States are used with 1294 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1295 * view depending on its state. 1296 * 1297 * @see android.graphics.drawable.Drawable 1298 * @see #getDrawableState() 1299 */ 1300 protected static final int[] ENABLED_STATE_SET; 1301 /** 1302 * Indicates the view is focused. States are used with 1303 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1304 * view depending on its state. 1305 * 1306 * @see android.graphics.drawable.Drawable 1307 * @see #getDrawableState() 1308 */ 1309 protected static final int[] FOCUSED_STATE_SET; 1310 /** 1311 * Indicates the view is selected. States are used with 1312 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1313 * view depending on its state. 1314 * 1315 * @see android.graphics.drawable.Drawable 1316 * @see #getDrawableState() 1317 */ 1318 protected static final int[] SELECTED_STATE_SET; 1319 /** 1320 * Indicates the view is pressed. States are used with 1321 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1322 * view depending on its state. 1323 * 1324 * @see android.graphics.drawable.Drawable 1325 * @see #getDrawableState() 1326 */ 1327 protected static final int[] PRESSED_STATE_SET; 1328 /** 1329 * Indicates the view's window has focus. States are used with 1330 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1331 * view depending on its state. 1332 * 1333 * @see android.graphics.drawable.Drawable 1334 * @see #getDrawableState() 1335 */ 1336 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1337 // Doubles 1338 /** 1339 * Indicates the view is enabled and has the focus. 1340 * 1341 * @see #ENABLED_STATE_SET 1342 * @see #FOCUSED_STATE_SET 1343 */ 1344 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1345 /** 1346 * Indicates the view is enabled and selected. 1347 * 1348 * @see #ENABLED_STATE_SET 1349 * @see #SELECTED_STATE_SET 1350 */ 1351 protected static final int[] ENABLED_SELECTED_STATE_SET; 1352 /** 1353 * Indicates the view is enabled and that its window has focus. 1354 * 1355 * @see #ENABLED_STATE_SET 1356 * @see #WINDOW_FOCUSED_STATE_SET 1357 */ 1358 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1359 /** 1360 * Indicates the view is focused and selected. 1361 * 1362 * @see #FOCUSED_STATE_SET 1363 * @see #SELECTED_STATE_SET 1364 */ 1365 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1366 /** 1367 * Indicates the view has the focus and that its window has the focus. 1368 * 1369 * @see #FOCUSED_STATE_SET 1370 * @see #WINDOW_FOCUSED_STATE_SET 1371 */ 1372 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1373 /** 1374 * Indicates the view is selected and that its window has the focus. 1375 * 1376 * @see #SELECTED_STATE_SET 1377 * @see #WINDOW_FOCUSED_STATE_SET 1378 */ 1379 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1380 // Triples 1381 /** 1382 * Indicates the view is enabled, focused and selected. 1383 * 1384 * @see #ENABLED_STATE_SET 1385 * @see #FOCUSED_STATE_SET 1386 * @see #SELECTED_STATE_SET 1387 */ 1388 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1389 /** 1390 * Indicates the view is enabled, focused and its window has the focus. 1391 * 1392 * @see #ENABLED_STATE_SET 1393 * @see #FOCUSED_STATE_SET 1394 * @see #WINDOW_FOCUSED_STATE_SET 1395 */ 1396 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1397 /** 1398 * Indicates the view is enabled, selected and its window has the focus. 1399 * 1400 * @see #ENABLED_STATE_SET 1401 * @see #SELECTED_STATE_SET 1402 * @see #WINDOW_FOCUSED_STATE_SET 1403 */ 1404 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1405 /** 1406 * Indicates the view is focused, selected and its window has the focus. 1407 * 1408 * @see #FOCUSED_STATE_SET 1409 * @see #SELECTED_STATE_SET 1410 * @see #WINDOW_FOCUSED_STATE_SET 1411 */ 1412 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1413 /** 1414 * Indicates the view is enabled, focused, selected and its window 1415 * has the focus. 1416 * 1417 * @see #ENABLED_STATE_SET 1418 * @see #FOCUSED_STATE_SET 1419 * @see #SELECTED_STATE_SET 1420 * @see #WINDOW_FOCUSED_STATE_SET 1421 */ 1422 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1423 /** 1424 * Indicates the view is pressed and its window has the focus. 1425 * 1426 * @see #PRESSED_STATE_SET 1427 * @see #WINDOW_FOCUSED_STATE_SET 1428 */ 1429 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1430 /** 1431 * Indicates the view is pressed and selected. 1432 * 1433 * @see #PRESSED_STATE_SET 1434 * @see #SELECTED_STATE_SET 1435 */ 1436 protected static final int[] PRESSED_SELECTED_STATE_SET; 1437 /** 1438 * Indicates the view is pressed, selected and its window has the focus. 1439 * 1440 * @see #PRESSED_STATE_SET 1441 * @see #SELECTED_STATE_SET 1442 * @see #WINDOW_FOCUSED_STATE_SET 1443 */ 1444 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1445 /** 1446 * Indicates the view is pressed and focused. 1447 * 1448 * @see #PRESSED_STATE_SET 1449 * @see #FOCUSED_STATE_SET 1450 */ 1451 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1452 /** 1453 * Indicates the view is pressed, focused and its window has the focus. 1454 * 1455 * @see #PRESSED_STATE_SET 1456 * @see #FOCUSED_STATE_SET 1457 * @see #WINDOW_FOCUSED_STATE_SET 1458 */ 1459 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1460 /** 1461 * Indicates the view is pressed, focused and selected. 1462 * 1463 * @see #PRESSED_STATE_SET 1464 * @see #SELECTED_STATE_SET 1465 * @see #FOCUSED_STATE_SET 1466 */ 1467 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1468 /** 1469 * Indicates the view is pressed, focused, selected and its window has the focus. 1470 * 1471 * @see #PRESSED_STATE_SET 1472 * @see #FOCUSED_STATE_SET 1473 * @see #SELECTED_STATE_SET 1474 * @see #WINDOW_FOCUSED_STATE_SET 1475 */ 1476 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1477 /** 1478 * Indicates the view is pressed and enabled. 1479 * 1480 * @see #PRESSED_STATE_SET 1481 * @see #ENABLED_STATE_SET 1482 */ 1483 protected static final int[] PRESSED_ENABLED_STATE_SET; 1484 /** 1485 * Indicates the view is pressed, enabled and its window has the focus. 1486 * 1487 * @see #PRESSED_STATE_SET 1488 * @see #ENABLED_STATE_SET 1489 * @see #WINDOW_FOCUSED_STATE_SET 1490 */ 1491 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1492 /** 1493 * Indicates the view is pressed, enabled and selected. 1494 * 1495 * @see #PRESSED_STATE_SET 1496 * @see #ENABLED_STATE_SET 1497 * @see #SELECTED_STATE_SET 1498 */ 1499 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1500 /** 1501 * Indicates the view is pressed, enabled, selected and its window has the 1502 * focus. 1503 * 1504 * @see #PRESSED_STATE_SET 1505 * @see #ENABLED_STATE_SET 1506 * @see #SELECTED_STATE_SET 1507 * @see #WINDOW_FOCUSED_STATE_SET 1508 */ 1509 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1510 /** 1511 * Indicates the view is pressed, enabled and focused. 1512 * 1513 * @see #PRESSED_STATE_SET 1514 * @see #ENABLED_STATE_SET 1515 * @see #FOCUSED_STATE_SET 1516 */ 1517 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1518 /** 1519 * Indicates the view is pressed, enabled, focused and its window has the 1520 * focus. 1521 * 1522 * @see #PRESSED_STATE_SET 1523 * @see #ENABLED_STATE_SET 1524 * @see #FOCUSED_STATE_SET 1525 * @see #WINDOW_FOCUSED_STATE_SET 1526 */ 1527 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1528 /** 1529 * Indicates the view is pressed, enabled, focused and selected. 1530 * 1531 * @see #PRESSED_STATE_SET 1532 * @see #ENABLED_STATE_SET 1533 * @see #SELECTED_STATE_SET 1534 * @see #FOCUSED_STATE_SET 1535 */ 1536 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1537 /** 1538 * Indicates the view is pressed, enabled, focused, selected and its window 1539 * has the focus. 1540 * 1541 * @see #PRESSED_STATE_SET 1542 * @see #ENABLED_STATE_SET 1543 * @see #SELECTED_STATE_SET 1544 * @see #FOCUSED_STATE_SET 1545 * @see #WINDOW_FOCUSED_STATE_SET 1546 */ 1547 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1548 1549 static { 1550 EMPTY_STATE_SET = StateSet.get(0); 1551 1552 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED); 1553 1554 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED); 1555 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1556 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED); 1557 1558 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED); 1559 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1560 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED); 1561 FOCUSED_SELECTED_STATE_SET = StateSet.get( 1562 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED); 1563 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1564 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1565 | StateSet.VIEW_STATE_FOCUSED); 1566 1567 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED); 1568 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1569 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1570 ENABLED_SELECTED_STATE_SET = StateSet.get( 1571 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED); 1572 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1573 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1574 | StateSet.VIEW_STATE_ENABLED); 1575 ENABLED_FOCUSED_STATE_SET = StateSet.get( 1576 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1577 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1578 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1579 | StateSet.VIEW_STATE_ENABLED); 1580 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1581 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1582 | StateSet.VIEW_STATE_ENABLED); 1583 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1584 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1585 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED); 1586 1587 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED); 1588 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1589 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1590 PRESSED_SELECTED_STATE_SET = StateSet.get( 1591 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED); 1592 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1593 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1594 | StateSet.VIEW_STATE_PRESSED); 1595 PRESSED_FOCUSED_STATE_SET = StateSet.get( 1596 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1597 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1598 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1599 | StateSet.VIEW_STATE_PRESSED); 1600 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1601 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1602 | StateSet.VIEW_STATE_PRESSED); 1603 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1604 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1605 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1606 PRESSED_ENABLED_STATE_SET = StateSet.get( 1607 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1608 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1609 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED 1610 | StateSet.VIEW_STATE_PRESSED); 1611 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get( 1612 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED 1613 | StateSet.VIEW_STATE_PRESSED); 1614 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1615 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1616 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1617 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get( 1618 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED 1619 | StateSet.VIEW_STATE_PRESSED); 1620 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1621 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1622 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1623 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1624 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1625 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1626 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1627 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1628 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED 1629 | StateSet.VIEW_STATE_PRESSED); 1630 } 1631 1632 /** 1633 * Accessibility event types that are dispatched for text population. 1634 */ 1635 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1636 AccessibilityEvent.TYPE_VIEW_CLICKED 1637 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1638 | AccessibilityEvent.TYPE_VIEW_SELECTED 1639 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1640 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1641 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1642 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 1643 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 1644 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 1645 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 1646 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 1647 1648 /** 1649 * Temporary Rect currently for use in setBackground(). This will probably 1650 * be extended in the future to hold our own class with more than just 1651 * a Rect. :) 1652 */ 1653 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1654 1655 /** 1656 * Map used to store views' tags. 1657 */ 1658 private SparseArray<Object> mKeyedTags; 1659 1660 /** 1661 * The next available accessibility id. 1662 */ 1663 private static int sNextAccessibilityViewId; 1664 1665 /** 1666 * The animation currently associated with this view. 1667 * @hide 1668 */ 1669 protected Animation mCurrentAnimation = null; 1670 1671 /** 1672 * Width as measured during measure pass. 1673 * {@hide} 1674 */ 1675 @ViewDebug.ExportedProperty(category = "measurement") 1676 int mMeasuredWidth; 1677 1678 /** 1679 * Height as measured during measure pass. 1680 * {@hide} 1681 */ 1682 @ViewDebug.ExportedProperty(category = "measurement") 1683 int mMeasuredHeight; 1684 1685 /** 1686 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1687 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1688 * its display list. This flag, used only when hw accelerated, allows us to clear the 1689 * flag while retaining this information until it's needed (at getDisplayList() time and 1690 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1691 * 1692 * {@hide} 1693 */ 1694 boolean mRecreateDisplayList = false; 1695 1696 /** 1697 * The view's identifier. 1698 * {@hide} 1699 * 1700 * @see #setId(int) 1701 * @see #getId() 1702 */ 1703 @IdRes 1704 @ViewDebug.ExportedProperty(resolveId = true) 1705 int mID = NO_ID; 1706 1707 /** 1708 * The stable ID of this view for accessibility purposes. 1709 */ 1710 int mAccessibilityViewId = NO_ID; 1711 1712 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 1713 1714 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent; 1715 1716 /** 1717 * The view's tag. 1718 * {@hide} 1719 * 1720 * @see #setTag(Object) 1721 * @see #getTag() 1722 */ 1723 protected Object mTag = null; 1724 1725 // for mPrivateFlags: 1726 /** {@hide} */ 1727 static final int PFLAG_WANTS_FOCUS = 0x00000001; 1728 /** {@hide} */ 1729 static final int PFLAG_FOCUSED = 0x00000002; 1730 /** {@hide} */ 1731 static final int PFLAG_SELECTED = 0x00000004; 1732 /** {@hide} */ 1733 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 1734 /** {@hide} */ 1735 static final int PFLAG_HAS_BOUNDS = 0x00000010; 1736 /** {@hide} */ 1737 static final int PFLAG_DRAWN = 0x00000020; 1738 /** 1739 * When this flag is set, this view is running an animation on behalf of its 1740 * children and should therefore not cancel invalidate requests, even if they 1741 * lie outside of this view's bounds. 1742 * 1743 * {@hide} 1744 */ 1745 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 1746 /** {@hide} */ 1747 static final int PFLAG_SKIP_DRAW = 0x00000080; 1748 /** {@hide} */ 1749 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1750 /** {@hide} */ 1751 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 1752 /** {@hide} */ 1753 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 1754 /** {@hide} */ 1755 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 1756 /** {@hide} */ 1757 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 1758 1759 private static final int PFLAG_PRESSED = 0x00004000; 1760 1761 /** {@hide} */ 1762 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 1763 /** 1764 * Flag used to indicate that this view should be drawn once more (and only once 1765 * more) after its animation has completed. 1766 * {@hide} 1767 */ 1768 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 1769 1770 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 1771 1772 /** 1773 * Indicates that the View returned true when onSetAlpha() was called and that 1774 * the alpha must be restored. 1775 * {@hide} 1776 */ 1777 static final int PFLAG_ALPHA_SET = 0x00040000; 1778 1779 /** 1780 * Set by {@link #setScrollContainer(boolean)}. 1781 */ 1782 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 1783 1784 /** 1785 * Set by {@link #setScrollContainer(boolean)}. 1786 */ 1787 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 1788 1789 /** 1790 * View flag indicating whether this view was invalidated (fully or partially.) 1791 * 1792 * @hide 1793 */ 1794 static final int PFLAG_DIRTY = 0x00200000; 1795 1796 /** 1797 * View flag indicating whether this view was invalidated by an opaque 1798 * invalidate request. 1799 * 1800 * @hide 1801 */ 1802 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 1803 1804 /** 1805 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 1806 * 1807 * @hide 1808 */ 1809 static final int PFLAG_DIRTY_MASK = 0x00600000; 1810 1811 /** 1812 * Indicates whether the background is opaque. 1813 * 1814 * @hide 1815 */ 1816 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 1817 1818 /** 1819 * Indicates whether the scrollbars are opaque. 1820 * 1821 * @hide 1822 */ 1823 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 1824 1825 /** 1826 * Indicates whether the view is opaque. 1827 * 1828 * @hide 1829 */ 1830 static final int PFLAG_OPAQUE_MASK = 0x01800000; 1831 1832 /** 1833 * Indicates a prepressed state; 1834 * the short time between ACTION_DOWN and recognizing 1835 * a 'real' press. Prepressed is used to recognize quick taps 1836 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1837 * 1838 * @hide 1839 */ 1840 private static final int PFLAG_PREPRESSED = 0x02000000; 1841 1842 /** 1843 * Indicates whether the view is temporarily detached. 1844 * 1845 * @hide 1846 */ 1847 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 1848 1849 /** 1850 * Indicates that we should awaken scroll bars once attached 1851 * 1852 * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged 1853 * during window attachment and it is no longer needed. Feel free to repurpose it. 1854 * 1855 * @hide 1856 */ 1857 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1858 1859 /** 1860 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1861 * @hide 1862 */ 1863 private static final int PFLAG_HOVERED = 0x10000000; 1864 1865 /** 1866 * no longer needed, should be reused 1867 */ 1868 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000; 1869 1870 /** {@hide} */ 1871 static final int PFLAG_ACTIVATED = 0x40000000; 1872 1873 /** 1874 * Indicates that this view was specifically invalidated, not just dirtied because some 1875 * child view was invalidated. The flag is used to determine when we need to recreate 1876 * a view's display list (as opposed to just returning a reference to its existing 1877 * display list). 1878 * 1879 * @hide 1880 */ 1881 static final int PFLAG_INVALIDATED = 0x80000000; 1882 1883 /** 1884 * Masks for mPrivateFlags2, as generated by dumpFlags(): 1885 * 1886 * |-------|-------|-------|-------| 1887 * 1 PFLAG2_DRAG_CAN_ACCEPT 1888 * 1 PFLAG2_DRAG_HOVERED 1889 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 1890 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 1891 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 1892 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 1893 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 1894 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 1895 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 1896 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 1897 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 1898 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6] 1899 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7] 1900 * 111 PFLAG2_TEXT_DIRECTION_MASK 1901 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 1902 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 1903 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 1904 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 1905 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 1906 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 1907 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 1908 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 1909 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 1910 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 1911 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 1912 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 1913 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 1914 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 1915 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 1916 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 1917 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 1918 * 1 PFLAG2_VIEW_QUICK_REJECTED 1919 * 1 PFLAG2_PADDING_RESOLVED 1920 * 1 PFLAG2_DRAWABLE_RESOLVED 1921 * 1 PFLAG2_HAS_TRANSIENT_STATE 1922 * |-------|-------|-------|-------| 1923 */ 1924 1925 /** 1926 * Indicates that this view has reported that it can accept the current drag's content. 1927 * Cleared when the drag operation concludes. 1928 * @hide 1929 */ 1930 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 1931 1932 /** 1933 * Indicates that this view is currently directly under the drag location in a 1934 * drag-and-drop operation involving content that it can accept. Cleared when 1935 * the drag exits the view, or when the drag operation concludes. 1936 * @hide 1937 */ 1938 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 1939 1940 /** @hide */ 1941 @IntDef({ 1942 LAYOUT_DIRECTION_LTR, 1943 LAYOUT_DIRECTION_RTL, 1944 LAYOUT_DIRECTION_INHERIT, 1945 LAYOUT_DIRECTION_LOCALE 1946 }) 1947 @Retention(RetentionPolicy.SOURCE) 1948 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection 1949 public @interface LayoutDir {} 1950 1951 /** @hide */ 1952 @IntDef({ 1953 LAYOUT_DIRECTION_LTR, 1954 LAYOUT_DIRECTION_RTL 1955 }) 1956 @Retention(RetentionPolicy.SOURCE) 1957 public @interface ResolvedLayoutDir {} 1958 1959 /** 1960 * A flag to indicate that the layout direction of this view has not been defined yet. 1961 * @hide 1962 */ 1963 public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED; 1964 1965 /** 1966 * Horizontal layout direction of this view is from Left to Right. 1967 * Use with {@link #setLayoutDirection}. 1968 */ 1969 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 1970 1971 /** 1972 * Horizontal layout direction of this view is from Right to Left. 1973 * Use with {@link #setLayoutDirection}. 1974 */ 1975 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 1976 1977 /** 1978 * Horizontal layout direction of this view is inherited from its parent. 1979 * Use with {@link #setLayoutDirection}. 1980 */ 1981 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 1982 1983 /** 1984 * Horizontal layout direction of this view is from deduced from the default language 1985 * script for the locale. Use with {@link #setLayoutDirection}. 1986 */ 1987 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 1988 1989 /** 1990 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1991 * @hide 1992 */ 1993 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 1994 1995 /** 1996 * Mask for use with private flags indicating bits used for horizontal layout direction. 1997 * @hide 1998 */ 1999 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2000 2001 /** 2002 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 2003 * right-to-left direction. 2004 * @hide 2005 */ 2006 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2007 2008 /** 2009 * Indicates whether the view horizontal layout direction has been resolved. 2010 * @hide 2011 */ 2012 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2013 2014 /** 2015 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 2016 * @hide 2017 */ 2018 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 2019 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2020 2021 /* 2022 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 2023 * flag value. 2024 * @hide 2025 */ 2026 private static final int[] LAYOUT_DIRECTION_FLAGS = { 2027 LAYOUT_DIRECTION_LTR, 2028 LAYOUT_DIRECTION_RTL, 2029 LAYOUT_DIRECTION_INHERIT, 2030 LAYOUT_DIRECTION_LOCALE 2031 }; 2032 2033 /** 2034 * Default horizontal layout direction. 2035 */ 2036 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 2037 2038 /** 2039 * Default horizontal layout direction. 2040 * @hide 2041 */ 2042 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 2043 2044 /** 2045 * Text direction is inherited through {@link ViewGroup} 2046 */ 2047 public static final int TEXT_DIRECTION_INHERIT = 0; 2048 2049 /** 2050 * Text direction is using "first strong algorithm". The first strong directional character 2051 * determines the paragraph direction. If there is no strong directional character, the 2052 * paragraph direction is the view's resolved layout direction. 2053 */ 2054 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 2055 2056 /** 2057 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 2058 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 2059 * If there are neither, the paragraph direction is the view's resolved layout direction. 2060 */ 2061 public static final int TEXT_DIRECTION_ANY_RTL = 2; 2062 2063 /** 2064 * Text direction is forced to LTR. 2065 */ 2066 public static final int TEXT_DIRECTION_LTR = 3; 2067 2068 /** 2069 * Text direction is forced to RTL. 2070 */ 2071 public static final int TEXT_DIRECTION_RTL = 4; 2072 2073 /** 2074 * Text direction is coming from the system Locale. 2075 */ 2076 public static final int TEXT_DIRECTION_LOCALE = 5; 2077 2078 /** 2079 * Text direction is using "first strong algorithm". The first strong directional character 2080 * determines the paragraph direction. If there is no strong directional character, the 2081 * paragraph direction is LTR. 2082 */ 2083 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6; 2084 2085 /** 2086 * Text direction is using "first strong algorithm". The first strong directional character 2087 * determines the paragraph direction. If there is no strong directional character, the 2088 * paragraph direction is RTL. 2089 */ 2090 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7; 2091 2092 /** 2093 * Default text direction is inherited 2094 */ 2095 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 2096 2097 /** 2098 * Default resolved text direction 2099 * @hide 2100 */ 2101 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 2102 2103 /** 2104 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 2105 * @hide 2106 */ 2107 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 2108 2109 /** 2110 * Mask for use with private flags indicating bits used for text direction. 2111 * @hide 2112 */ 2113 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 2114 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2115 2116 /** 2117 * Array of text direction flags for mapping attribute "textDirection" to correct 2118 * flag value. 2119 * @hide 2120 */ 2121 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 2122 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2123 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2124 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2125 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2126 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2127 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2128 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2129 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 2130 }; 2131 2132 /** 2133 * Indicates whether the view text direction has been resolved. 2134 * @hide 2135 */ 2136 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 2137 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2138 2139 /** 2140 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2141 * @hide 2142 */ 2143 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 2144 2145 /** 2146 * Mask for use with private flags indicating bits used for resolved text direction. 2147 * @hide 2148 */ 2149 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 2150 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2151 2152 /** 2153 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 2154 * @hide 2155 */ 2156 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 2157 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2158 2159 /** @hide */ 2160 @IntDef({ 2161 TEXT_ALIGNMENT_INHERIT, 2162 TEXT_ALIGNMENT_GRAVITY, 2163 TEXT_ALIGNMENT_CENTER, 2164 TEXT_ALIGNMENT_TEXT_START, 2165 TEXT_ALIGNMENT_TEXT_END, 2166 TEXT_ALIGNMENT_VIEW_START, 2167 TEXT_ALIGNMENT_VIEW_END 2168 }) 2169 @Retention(RetentionPolicy.SOURCE) 2170 public @interface TextAlignment {} 2171 2172 /** 2173 * Default text alignment. The text alignment of this View is inherited from its parent. 2174 * Use with {@link #setTextAlignment(int)} 2175 */ 2176 public static final int TEXT_ALIGNMENT_INHERIT = 0; 2177 2178 /** 2179 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 2180 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 2181 * 2182 * Use with {@link #setTextAlignment(int)} 2183 */ 2184 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 2185 2186 /** 2187 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2188 * 2189 * Use with {@link #setTextAlignment(int)} 2190 */ 2191 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2192 2193 /** 2194 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2195 * 2196 * Use with {@link #setTextAlignment(int)} 2197 */ 2198 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2199 2200 /** 2201 * Center the paragraph, e.g. ALIGN_CENTER. 2202 * 2203 * Use with {@link #setTextAlignment(int)} 2204 */ 2205 public static final int TEXT_ALIGNMENT_CENTER = 4; 2206 2207 /** 2208 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved 2209 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2210 * 2211 * Use with {@link #setTextAlignment(int)} 2212 */ 2213 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2214 2215 /** 2216 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved 2217 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2218 * 2219 * Use with {@link #setTextAlignment(int)} 2220 */ 2221 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2222 2223 /** 2224 * Default text alignment is inherited 2225 */ 2226 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2227 2228 /** 2229 * Default resolved text alignment 2230 * @hide 2231 */ 2232 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2233 2234 /** 2235 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2236 * @hide 2237 */ 2238 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2239 2240 /** 2241 * Mask for use with private flags indicating bits used for text alignment. 2242 * @hide 2243 */ 2244 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2245 2246 /** 2247 * Array of text direction flags for mapping attribute "textAlignment" to correct 2248 * flag value. 2249 * @hide 2250 */ 2251 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2252 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2253 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2254 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2255 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2256 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2257 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2258 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2259 }; 2260 2261 /** 2262 * Indicates whether the view text alignment has been resolved. 2263 * @hide 2264 */ 2265 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2266 2267 /** 2268 * Bit shift to get the resolved text alignment. 2269 * @hide 2270 */ 2271 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2272 2273 /** 2274 * Mask for use with private flags indicating bits used for text alignment. 2275 * @hide 2276 */ 2277 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2278 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2279 2280 /** 2281 * Indicates whether if the view text alignment has been resolved to gravity 2282 */ 2283 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2284 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2285 2286 // Accessiblity constants for mPrivateFlags2 2287 2288 /** 2289 * Shift for the bits in {@link #mPrivateFlags2} related to the 2290 * "importantForAccessibility" attribute. 2291 */ 2292 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2293 2294 /** 2295 * Automatically determine whether a view is important for accessibility. 2296 */ 2297 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2298 2299 /** 2300 * The view is important for accessibility. 2301 */ 2302 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2303 2304 /** 2305 * The view is not important for accessibility. 2306 */ 2307 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2308 2309 /** 2310 * The view is not important for accessibility, nor are any of its 2311 * descendant views. 2312 */ 2313 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2314 2315 /** 2316 * The default whether the view is important for accessibility. 2317 */ 2318 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2319 2320 /** 2321 * Mask for obtainig the bits which specify how to determine 2322 * whether a view is important for accessibility. 2323 */ 2324 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2325 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2326 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2327 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2328 2329 /** 2330 * Shift for the bits in {@link #mPrivateFlags2} related to the 2331 * "accessibilityLiveRegion" attribute. 2332 */ 2333 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2334 2335 /** 2336 * Live region mode specifying that accessibility services should not 2337 * automatically announce changes to this view. This is the default live 2338 * region mode for most views. 2339 * <p> 2340 * Use with {@link #setAccessibilityLiveRegion(int)}. 2341 */ 2342 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2343 2344 /** 2345 * Live region mode specifying that accessibility services should announce 2346 * changes to this view. 2347 * <p> 2348 * Use with {@link #setAccessibilityLiveRegion(int)}. 2349 */ 2350 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2351 2352 /** 2353 * Live region mode specifying that accessibility services should interrupt 2354 * ongoing speech to immediately announce changes to this view. 2355 * <p> 2356 * Use with {@link #setAccessibilityLiveRegion(int)}. 2357 */ 2358 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2359 2360 /** 2361 * The default whether the view is important for accessibility. 2362 */ 2363 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2364 2365 /** 2366 * Mask for obtaining the bits which specify a view's accessibility live 2367 * region mode. 2368 */ 2369 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2370 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2371 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2372 2373 /** 2374 * Flag indicating whether a view has accessibility focus. 2375 */ 2376 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2377 2378 /** 2379 * Flag whether the accessibility state of the subtree rooted at this view changed. 2380 */ 2381 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2382 2383 /** 2384 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2385 * is used to check whether later changes to the view's transform should invalidate the 2386 * view to force the quickReject test to run again. 2387 */ 2388 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2389 2390 /** 2391 * Flag indicating that start/end padding has been resolved into left/right padding 2392 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2393 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2394 * during measurement. In some special cases this is required such as when an adapter-based 2395 * view measures prospective children without attaching them to a window. 2396 */ 2397 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2398 2399 /** 2400 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2401 */ 2402 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2403 2404 /** 2405 * Indicates that the view is tracking some sort of transient state 2406 * that the app should not need to be aware of, but that the framework 2407 * should take special care to preserve. 2408 */ 2409 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2410 2411 /** 2412 * Group of bits indicating that RTL properties resolution is done. 2413 */ 2414 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2415 PFLAG2_TEXT_DIRECTION_RESOLVED | 2416 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2417 PFLAG2_PADDING_RESOLVED | 2418 PFLAG2_DRAWABLE_RESOLVED; 2419 2420 // There are a couple of flags left in mPrivateFlags2 2421 2422 /* End of masks for mPrivateFlags2 */ 2423 2424 /** 2425 * Masks for mPrivateFlags3, as generated by dumpFlags(): 2426 * 2427 * |-------|-------|-------|-------| 2428 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM 2429 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA 2430 * 1 PFLAG3_IS_LAID_OUT 2431 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT 2432 * 1 PFLAG3_CALLED_SUPER 2433 * 1 PFLAG3_APPLYING_INSETS 2434 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS 2435 * 1 PFLAG3_NESTED_SCROLLING_ENABLED 2436 * 1 PFLAG3_SCROLL_INDICATOR_TOP 2437 * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM 2438 * 1 PFLAG3_SCROLL_INDICATOR_LEFT 2439 * 1 PFLAG3_SCROLL_INDICATOR_RIGHT 2440 * 1 PFLAG3_SCROLL_INDICATOR_START 2441 * 1 PFLAG3_SCROLL_INDICATOR_END 2442 * 1 PFLAG3_ASSIST_BLOCKED 2443 * 1 PFLAG3_POINTER_ICON_NULL 2444 * 1 PFLAG3_POINTER_ICON_VALUE_START 2445 * 11111111 PFLAG3_POINTER_ICON_MASK 2446 * 1 PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE 2447 * 1 PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED 2448 * 1 PFLAG3_TEMPORARY_DETACH 2449 * 1 PFLAG3_NO_REVEAL_ON_FOCUS 2450 * |-------|-------|-------|-------| 2451 */ 2452 2453 /** 2454 * Flag indicating that view has a transform animation set on it. This is used to track whether 2455 * an animation is cleared between successive frames, in order to tell the associated 2456 * DisplayList to clear its animation matrix. 2457 */ 2458 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2459 2460 /** 2461 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2462 * animation is cleared between successive frames, in order to tell the associated 2463 * DisplayList to restore its alpha value. 2464 */ 2465 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2466 2467 /** 2468 * Flag indicating that the view has been through at least one layout since it 2469 * was last attached to a window. 2470 */ 2471 static final int PFLAG3_IS_LAID_OUT = 0x4; 2472 2473 /** 2474 * Flag indicating that a call to measure() was skipped and should be done 2475 * instead when layout() is invoked. 2476 */ 2477 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2478 2479 /** 2480 * Flag indicating that an overridden method correctly called down to 2481 * the superclass implementation as required by the API spec. 2482 */ 2483 static final int PFLAG3_CALLED_SUPER = 0x10; 2484 2485 /** 2486 * Flag indicating that we're in the process of applying window insets. 2487 */ 2488 static final int PFLAG3_APPLYING_INSETS = 0x20; 2489 2490 /** 2491 * Flag indicating that we're in the process of fitting system windows using the old method. 2492 */ 2493 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40; 2494 2495 /** 2496 * Flag indicating that nested scrolling is enabled for this view. 2497 * The view will optionally cooperate with views up its parent chain to allow for 2498 * integrated nested scrolling along the same axis. 2499 */ 2500 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; 2501 2502 /** 2503 * Flag indicating that the bottom scroll indicator should be displayed 2504 * when this view can scroll up. 2505 */ 2506 static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; 2507 2508 /** 2509 * Flag indicating that the bottom scroll indicator should be displayed 2510 * when this view can scroll down. 2511 */ 2512 static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; 2513 2514 /** 2515 * Flag indicating that the left scroll indicator should be displayed 2516 * when this view can scroll left. 2517 */ 2518 static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; 2519 2520 /** 2521 * Flag indicating that the right scroll indicator should be displayed 2522 * when this view can scroll right. 2523 */ 2524 static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; 2525 2526 /** 2527 * Flag indicating that the start scroll indicator should be displayed 2528 * when this view can scroll in the start direction. 2529 */ 2530 static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; 2531 2532 /** 2533 * Flag indicating that the end scroll indicator should be displayed 2534 * when this view can scroll in the end direction. 2535 */ 2536 static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; 2537 2538 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 2539 2540 static final int SCROLL_INDICATORS_NONE = 0x0000; 2541 2542 /** 2543 * Mask for use with setFlags indicating bits used for indicating which 2544 * scroll indicators are enabled. 2545 */ 2546 static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP 2547 | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT 2548 | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START 2549 | PFLAG3_SCROLL_INDICATOR_END; 2550 2551 /** 2552 * Left-shift required to translate between public scroll indicator flags 2553 * and internal PFLAGS3 flags. When used as a right-shift, translates 2554 * PFLAGS3 flags to public flags. 2555 */ 2556 static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; 2557 2558 /** @hide */ 2559 @Retention(RetentionPolicy.SOURCE) 2560 @IntDef(flag = true, 2561 value = { 2562 SCROLL_INDICATOR_TOP, 2563 SCROLL_INDICATOR_BOTTOM, 2564 SCROLL_INDICATOR_LEFT, 2565 SCROLL_INDICATOR_RIGHT, 2566 SCROLL_INDICATOR_START, 2567 SCROLL_INDICATOR_END, 2568 }) 2569 public @interface ScrollIndicators {} 2570 2571 /** 2572 * Scroll indicator direction for the top edge of the view. 2573 * 2574 * @see #setScrollIndicators(int) 2575 * @see #setScrollIndicators(int, int) 2576 * @see #getScrollIndicators() 2577 */ 2578 public static final int SCROLL_INDICATOR_TOP = 2579 PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2580 2581 /** 2582 * Scroll indicator direction for the bottom edge of the view. 2583 * 2584 * @see #setScrollIndicators(int) 2585 * @see #setScrollIndicators(int, int) 2586 * @see #getScrollIndicators() 2587 */ 2588 public static final int SCROLL_INDICATOR_BOTTOM = 2589 PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2590 2591 /** 2592 * Scroll indicator direction for the left edge of the view. 2593 * 2594 * @see #setScrollIndicators(int) 2595 * @see #setScrollIndicators(int, int) 2596 * @see #getScrollIndicators() 2597 */ 2598 public static final int SCROLL_INDICATOR_LEFT = 2599 PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2600 2601 /** 2602 * Scroll indicator direction for the right edge of the view. 2603 * 2604 * @see #setScrollIndicators(int) 2605 * @see #setScrollIndicators(int, int) 2606 * @see #getScrollIndicators() 2607 */ 2608 public static final int SCROLL_INDICATOR_RIGHT = 2609 PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2610 2611 /** 2612 * Scroll indicator direction for the starting edge of the view. 2613 * <p> 2614 * Resolved according to the view's layout direction, see 2615 * {@link #getLayoutDirection()} for more information. 2616 * 2617 * @see #setScrollIndicators(int) 2618 * @see #setScrollIndicators(int, int) 2619 * @see #getScrollIndicators() 2620 */ 2621 public static final int SCROLL_INDICATOR_START = 2622 PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2623 2624 /** 2625 * Scroll indicator direction for the ending edge of the view. 2626 * <p> 2627 * Resolved according to the view's layout direction, see 2628 * {@link #getLayoutDirection()} for more information. 2629 * 2630 * @see #setScrollIndicators(int) 2631 * @see #setScrollIndicators(int, int) 2632 * @see #getScrollIndicators() 2633 */ 2634 public static final int SCROLL_INDICATOR_END = 2635 PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2636 2637 /** 2638 * <p>Indicates that we are allowing {@link ViewStructure} to traverse 2639 * into this view.<p> 2640 */ 2641 static final int PFLAG3_ASSIST_BLOCKED = 0x4000; 2642 2643 /** 2644 * The mask for use with private flags indicating bits used for pointer icon shapes. 2645 */ 2646 static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000; 2647 2648 /** 2649 * Left-shift used for pointer icon shape values in private flags. 2650 */ 2651 static final int PFLAG3_POINTER_ICON_LSHIFT = 15; 2652 2653 /** 2654 * Value indicating no specific pointer icons. 2655 */ 2656 private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT; 2657 2658 /** 2659 * Value indicating {@link PointerIcon.TYPE_NULL}. 2660 */ 2661 private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT; 2662 2663 /** 2664 * The base value for other pointer icon shapes. 2665 */ 2666 private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT; 2667 2668 /** 2669 * Whether this view has rendered elements that overlap (see {@link 2670 * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and 2671 * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when 2672 * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is 2673 * determined by whatever {@link #hasOverlappingRendering()} returns. 2674 */ 2675 private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000; 2676 2677 /** 2678 * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value 2679 * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid. 2680 */ 2681 private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000; 2682 2683 /** 2684 * Flag indicating that the view is temporarily detached from the parent view. 2685 * 2686 * @see #onStartTemporaryDetach() 2687 * @see #onFinishTemporaryDetach() 2688 */ 2689 static final int PFLAG3_TEMPORARY_DETACH = 0x2000000; 2690 2691 /** 2692 * Flag indicating that the view does not wish to be revealed within its parent 2693 * hierarchy when it gains focus. Expressed in the negative since the historical 2694 * default behavior is to reveal on focus; this flag suppresses that behavior. 2695 * 2696 * @see #setRevealOnFocusHint(boolean) 2697 * @see #getRevealOnFocusHint() 2698 */ 2699 private static final int PFLAG3_NO_REVEAL_ON_FOCUS = 0x4000000; 2700 2701 /* End of masks for mPrivateFlags3 */ 2702 2703 /** 2704 * Always allow a user to over-scroll this view, provided it is a 2705 * view that can scroll. 2706 * 2707 * @see #getOverScrollMode() 2708 * @see #setOverScrollMode(int) 2709 */ 2710 public static final int OVER_SCROLL_ALWAYS = 0; 2711 2712 /** 2713 * Allow a user to over-scroll this view only if the content is large 2714 * enough to meaningfully scroll, provided it is a view that can scroll. 2715 * 2716 * @see #getOverScrollMode() 2717 * @see #setOverScrollMode(int) 2718 */ 2719 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 2720 2721 /** 2722 * Never allow a user to over-scroll this view. 2723 * 2724 * @see #getOverScrollMode() 2725 * @see #setOverScrollMode(int) 2726 */ 2727 public static final int OVER_SCROLL_NEVER = 2; 2728 2729 /** 2730 * Special constant for {@link #setSystemUiVisibility(int)}: View has 2731 * requested the system UI (status bar) to be visible (the default). 2732 * 2733 * @see #setSystemUiVisibility(int) 2734 */ 2735 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 2736 2737 /** 2738 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 2739 * system UI to enter an unobtrusive "low profile" mode. 2740 * 2741 * <p>This is for use in games, book readers, video players, or any other 2742 * "immersive" application where the usual system chrome is deemed too distracting. 2743 * 2744 * <p>In low profile mode, the status bar and/or navigation icons may dim. 2745 * 2746 * @see #setSystemUiVisibility(int) 2747 */ 2748 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 2749 2750 /** 2751 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 2752 * system navigation be temporarily hidden. 2753 * 2754 * <p>This is an even less obtrusive state than that called for by 2755 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 2756 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 2757 * those to disappear. This is useful (in conjunction with the 2758 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 2759 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 2760 * window flags) for displaying content using every last pixel on the display. 2761 * 2762 * <p>There is a limitation: because navigation controls are so important, the least user 2763 * interaction will cause them to reappear immediately. When this happens, both 2764 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 2765 * so that both elements reappear at the same time. 2766 * 2767 * @see #setSystemUiVisibility(int) 2768 */ 2769 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 2770 2771 /** 2772 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 2773 * into the normal fullscreen mode so that its content can take over the screen 2774 * while still allowing the user to interact with the application. 2775 * 2776 * <p>This has the same visual effect as 2777 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 2778 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 2779 * meaning that non-critical screen decorations (such as the status bar) will be 2780 * hidden while the user is in the View's window, focusing the experience on 2781 * that content. Unlike the window flag, if you are using ActionBar in 2782 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2783 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 2784 * hide the action bar. 2785 * 2786 * <p>This approach to going fullscreen is best used over the window flag when 2787 * it is a transient state -- that is, the application does this at certain 2788 * points in its user interaction where it wants to allow the user to focus 2789 * on content, but not as a continuous state. For situations where the application 2790 * would like to simply stay full screen the entire time (such as a game that 2791 * wants to take over the screen), the 2792 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 2793 * is usually a better approach. The state set here will be removed by the system 2794 * in various situations (such as the user moving to another application) like 2795 * the other system UI states. 2796 * 2797 * <p>When using this flag, the application should provide some easy facility 2798 * for the user to go out of it. A common example would be in an e-book 2799 * reader, where tapping on the screen brings back whatever screen and UI 2800 * decorations that had been hidden while the user was immersed in reading 2801 * the book. 2802 * 2803 * @see #setSystemUiVisibility(int) 2804 */ 2805 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 2806 2807 /** 2808 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 2809 * flags, we would like a stable view of the content insets given to 2810 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 2811 * will always represent the worst case that the application can expect 2812 * as a continuous state. In the stock Android UI this is the space for 2813 * the system bar, nav bar, and status bar, but not more transient elements 2814 * such as an input method. 2815 * 2816 * The stable layout your UI sees is based on the system UI modes you can 2817 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 2818 * then you will get a stable layout for changes of the 2819 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 2820 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 2821 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 2822 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 2823 * with a stable layout. (Note that you should avoid using 2824 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 2825 * 2826 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 2827 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 2828 * then a hidden status bar will be considered a "stable" state for purposes 2829 * here. This allows your UI to continually hide the status bar, while still 2830 * using the system UI flags to hide the action bar while still retaining 2831 * a stable layout. Note that changing the window fullscreen flag will never 2832 * provide a stable layout for a clean transition. 2833 * 2834 * <p>If you are using ActionBar in 2835 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2836 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 2837 * insets it adds to those given to the application. 2838 */ 2839 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 2840 2841 /** 2842 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2843 * to be laid out as if it has requested 2844 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 2845 * allows it to avoid artifacts when switching in and out of that mode, at 2846 * the expense that some of its user interface may be covered by screen 2847 * decorations when they are shown. You can perform layout of your inner 2848 * UI elements to account for the navigation system UI through the 2849 * {@link #fitSystemWindows(Rect)} method. 2850 */ 2851 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 2852 2853 /** 2854 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2855 * to be laid out as if it has requested 2856 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 2857 * allows it to avoid artifacts when switching in and out of that mode, at 2858 * the expense that some of its user interface may be covered by screen 2859 * decorations when they are shown. You can perform layout of your inner 2860 * UI elements to account for non-fullscreen system UI through the 2861 * {@link #fitSystemWindows(Rect)} method. 2862 */ 2863 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 2864 2865 /** 2866 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2867 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 2868 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 2869 * user interaction. 2870 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 2871 * has an effect when used in combination with that flag.</p> 2872 */ 2873 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 2874 2875 /** 2876 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2877 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 2878 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 2879 * experience while also hiding the system bars. If this flag is not set, 2880 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 2881 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 2882 * if the user swipes from the top of the screen. 2883 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 2884 * system gestures, such as swiping from the top of the screen. These transient system bars 2885 * will overlay app’s content, may have some degree of transparency, and will automatically 2886 * hide after a short timeout. 2887 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 2888 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 2889 * with one or both of those flags.</p> 2890 */ 2891 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 2892 2893 /** 2894 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that 2895 * is compatible with light status bar backgrounds. 2896 * 2897 * <p>For this to take effect, the window must request 2898 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 2899 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not 2900 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS 2901 * FLAG_TRANSLUCENT_STATUS}. 2902 * 2903 * @see android.R.attr#windowLightStatusBar 2904 */ 2905 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; 2906 2907 /** 2908 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 2909 */ 2910 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 2911 2912 /** 2913 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 2914 */ 2915 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 2916 2917 /** 2918 * @hide 2919 * 2920 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2921 * out of the public fields to keep the undefined bits out of the developer's way. 2922 * 2923 * Flag to make the status bar not expandable. Unless you also 2924 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 2925 */ 2926 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 2927 2928 /** 2929 * @hide 2930 * 2931 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2932 * out of the public fields to keep the undefined bits out of the developer's way. 2933 * 2934 * Flag to hide notification icons and scrolling ticker text. 2935 */ 2936 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 2937 2938 /** 2939 * @hide 2940 * 2941 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2942 * out of the public fields to keep the undefined bits out of the developer's way. 2943 * 2944 * Flag to disable incoming notification alerts. This will not block 2945 * icons, but it will block sound, vibrating and other visual or aural notifications. 2946 */ 2947 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 2948 2949 /** 2950 * @hide 2951 * 2952 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2953 * out of the public fields to keep the undefined bits out of the developer's way. 2954 * 2955 * Flag to hide only the scrolling ticker. Note that 2956 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 2957 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 2958 */ 2959 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 2960 2961 /** 2962 * @hide 2963 * 2964 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2965 * out of the public fields to keep the undefined bits out of the developer's way. 2966 * 2967 * Flag to hide the center system info area. 2968 */ 2969 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 2970 2971 /** 2972 * @hide 2973 * 2974 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2975 * out of the public fields to keep the undefined bits out of the developer's way. 2976 * 2977 * Flag to hide only the home button. Don't use this 2978 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2979 */ 2980 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 2981 2982 /** 2983 * @hide 2984 * 2985 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2986 * out of the public fields to keep the undefined bits out of the developer's way. 2987 * 2988 * Flag to hide only the back button. Don't use this 2989 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2990 */ 2991 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 2992 2993 /** 2994 * @hide 2995 * 2996 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2997 * out of the public fields to keep the undefined bits out of the developer's way. 2998 * 2999 * Flag to hide only the clock. You might use this if your activity has 3000 * its own clock making the status bar's clock redundant. 3001 */ 3002 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 3003 3004 /** 3005 * @hide 3006 * 3007 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3008 * out of the public fields to keep the undefined bits out of the developer's way. 3009 * 3010 * Flag to hide only the recent apps button. Don't use this 3011 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3012 */ 3013 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 3014 3015 /** 3016 * @hide 3017 * 3018 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3019 * out of the public fields to keep the undefined bits out of the developer's way. 3020 * 3021 * Flag to disable the global search gesture. Don't use this 3022 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 3023 */ 3024 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 3025 3026 /** 3027 * @hide 3028 * 3029 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3030 * out of the public fields to keep the undefined bits out of the developer's way. 3031 * 3032 * Flag to specify that the status bar is displayed in transient mode. 3033 */ 3034 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 3035 3036 /** 3037 * @hide 3038 * 3039 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3040 * out of the public fields to keep the undefined bits out of the developer's way. 3041 * 3042 * Flag to specify that the navigation bar is displayed in transient mode. 3043 */ 3044 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 3045 3046 /** 3047 * @hide 3048 * 3049 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3050 * out of the public fields to keep the undefined bits out of the developer's way. 3051 * 3052 * Flag to specify that the hidden status bar would like to be shown. 3053 */ 3054 public static final int STATUS_BAR_UNHIDE = 0x10000000; 3055 3056 /** 3057 * @hide 3058 * 3059 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3060 * out of the public fields to keep the undefined bits out of the developer's way. 3061 * 3062 * Flag to specify that the hidden navigation bar would like to be shown. 3063 */ 3064 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 3065 3066 /** 3067 * @hide 3068 * 3069 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3070 * out of the public fields to keep the undefined bits out of the developer's way. 3071 * 3072 * Flag to specify that the status bar is displayed in translucent mode. 3073 */ 3074 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 3075 3076 /** 3077 * @hide 3078 * 3079 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3080 * out of the public fields to keep the undefined bits out of the developer's way. 3081 * 3082 * Flag to specify that the navigation bar is displayed in translucent mode. 3083 */ 3084 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 3085 3086 /** 3087 * @hide 3088 * 3089 * Whether Recents is visible or not. 3090 */ 3091 public static final int RECENT_APPS_VISIBLE = 0x00004000; 3092 3093 /** 3094 * @hide 3095 * 3096 * Whether the TV's picture-in-picture is visible or not. 3097 */ 3098 public static final int TV_PICTURE_IN_PICTURE_VISIBLE = 0x00010000; 3099 3100 /** 3101 * @hide 3102 * 3103 * Makes navigation bar transparent (but not the status bar). 3104 */ 3105 public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000; 3106 3107 /** 3108 * @hide 3109 * 3110 * Makes status bar transparent (but not the navigation bar). 3111 */ 3112 public static final int STATUS_BAR_TRANSPARENT = 0x0000008; 3113 3114 /** 3115 * @hide 3116 * 3117 * Makes both status bar and navigation bar transparent. 3118 */ 3119 public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT 3120 | STATUS_BAR_TRANSPARENT; 3121 3122 /** 3123 * @hide 3124 */ 3125 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7; 3126 3127 /** 3128 * These are the system UI flags that can be cleared by events outside 3129 * of an application. Currently this is just the ability to tap on the 3130 * screen while hiding the navigation bar to have it return. 3131 * @hide 3132 */ 3133 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 3134 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 3135 | SYSTEM_UI_FLAG_FULLSCREEN; 3136 3137 /** 3138 * Flags that can impact the layout in relation to system UI. 3139 */ 3140 public static final int SYSTEM_UI_LAYOUT_FLAGS = 3141 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 3142 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 3143 3144 /** @hide */ 3145 @IntDef(flag = true, 3146 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION }) 3147 @Retention(RetentionPolicy.SOURCE) 3148 public @interface FindViewFlags {} 3149 3150 /** 3151 * Find views that render the specified text. 3152 * 3153 * @see #findViewsWithText(ArrayList, CharSequence, int) 3154 */ 3155 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 3156 3157 /** 3158 * Find find views that contain the specified content description. 3159 * 3160 * @see #findViewsWithText(ArrayList, CharSequence, int) 3161 */ 3162 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 3163 3164 /** 3165 * Find views that contain {@link AccessibilityNodeProvider}. Such 3166 * a View is a root of virtual view hierarchy and may contain the searched 3167 * text. If this flag is set Views with providers are automatically 3168 * added and it is a responsibility of the client to call the APIs of 3169 * the provider to determine whether the virtual tree rooted at this View 3170 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 3171 * representing the virtual views with this text. 3172 * 3173 * @see #findViewsWithText(ArrayList, CharSequence, int) 3174 * 3175 * @hide 3176 */ 3177 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 3178 3179 /** 3180 * The undefined cursor position. 3181 * 3182 * @hide 3183 */ 3184 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 3185 3186 /** 3187 * Indicates that the screen has changed state and is now off. 3188 * 3189 * @see #onScreenStateChanged(int) 3190 */ 3191 public static final int SCREEN_STATE_OFF = 0x0; 3192 3193 /** 3194 * Indicates that the screen has changed state and is now on. 3195 * 3196 * @see #onScreenStateChanged(int) 3197 */ 3198 public static final int SCREEN_STATE_ON = 0x1; 3199 3200 /** 3201 * Indicates no axis of view scrolling. 3202 */ 3203 public static final int SCROLL_AXIS_NONE = 0; 3204 3205 /** 3206 * Indicates scrolling along the horizontal axis. 3207 */ 3208 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0; 3209 3210 /** 3211 * Indicates scrolling along the vertical axis. 3212 */ 3213 public static final int SCROLL_AXIS_VERTICAL = 1 << 1; 3214 3215 /** 3216 * Controls the over-scroll mode for this view. 3217 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 3218 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 3219 * and {@link #OVER_SCROLL_NEVER}. 3220 */ 3221 private int mOverScrollMode; 3222 3223 /** 3224 * The parent this view is attached to. 3225 * {@hide} 3226 * 3227 * @see #getParent() 3228 */ 3229 protected ViewParent mParent; 3230 3231 /** 3232 * {@hide} 3233 */ 3234 AttachInfo mAttachInfo; 3235 3236 /** 3237 * {@hide} 3238 */ 3239 @ViewDebug.ExportedProperty(flagMapping = { 3240 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 3241 name = "FORCE_LAYOUT"), 3242 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 3243 name = "LAYOUT_REQUIRED"), 3244 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 3245 name = "DRAWING_CACHE_INVALID", outputIf = false), 3246 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 3247 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 3248 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 3249 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 3250 }, formatToHexString = true) 3251 int mPrivateFlags; 3252 int mPrivateFlags2; 3253 int mPrivateFlags3; 3254 3255 /** 3256 * This view's request for the visibility of the status bar. 3257 * @hide 3258 */ 3259 @ViewDebug.ExportedProperty(flagMapping = { 3260 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 3261 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 3262 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 3263 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3264 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3265 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 3266 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 3267 equals = SYSTEM_UI_FLAG_VISIBLE, 3268 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 3269 }, formatToHexString = true) 3270 int mSystemUiVisibility; 3271 3272 /** 3273 * Reference count for transient state. 3274 * @see #setHasTransientState(boolean) 3275 */ 3276 int mTransientStateCount = 0; 3277 3278 /** 3279 * Count of how many windows this view has been attached to. 3280 */ 3281 int mWindowAttachCount; 3282 3283 /** 3284 * The layout parameters associated with this view and used by the parent 3285 * {@link android.view.ViewGroup} to determine how this view should be 3286 * laid out. 3287 * {@hide} 3288 */ 3289 protected ViewGroup.LayoutParams mLayoutParams; 3290 3291 /** 3292 * The view flags hold various views states. 3293 * {@hide} 3294 */ 3295 @ViewDebug.ExportedProperty(formatToHexString = true) 3296 int mViewFlags; 3297 3298 static class TransformationInfo { 3299 /** 3300 * The transform matrix for the View. This transform is calculated internally 3301 * based on the translation, rotation, and scale properties. 3302 * 3303 * Do *not* use this variable directly; instead call getMatrix(), which will 3304 * load the value from the View's RenderNode. 3305 */ 3306 private final Matrix mMatrix = new Matrix(); 3307 3308 /** 3309 * The inverse transform matrix for the View. This transform is calculated 3310 * internally based on the translation, rotation, and scale properties. 3311 * 3312 * Do *not* use this variable directly; instead call getInverseMatrix(), 3313 * which will load the value from the View's RenderNode. 3314 */ 3315 private Matrix mInverseMatrix; 3316 3317 /** 3318 * The opacity of the View. This is a value from 0 to 1, where 0 means 3319 * completely transparent and 1 means completely opaque. 3320 */ 3321 @ViewDebug.ExportedProperty 3322 float mAlpha = 1f; 3323 3324 /** 3325 * The opacity of the view as manipulated by the Fade transition. This is a hidden 3326 * property only used by transitions, which is composited with the other alpha 3327 * values to calculate the final visual alpha value. 3328 */ 3329 float mTransitionAlpha = 1f; 3330 } 3331 3332 TransformationInfo mTransformationInfo; 3333 3334 /** 3335 * Current clip bounds. to which all drawing of this view are constrained. 3336 */ 3337 Rect mClipBounds = null; 3338 3339 private boolean mLastIsOpaque; 3340 3341 /** 3342 * The distance in pixels from the left edge of this view's parent 3343 * to the left edge of this view. 3344 * {@hide} 3345 */ 3346 @ViewDebug.ExportedProperty(category = "layout") 3347 protected int mLeft; 3348 /** 3349 * The distance in pixels from the left edge of this view's parent 3350 * to the right edge of this view. 3351 * {@hide} 3352 */ 3353 @ViewDebug.ExportedProperty(category = "layout") 3354 protected int mRight; 3355 /** 3356 * The distance in pixels from the top edge of this view's parent 3357 * to the top edge of this view. 3358 * {@hide} 3359 */ 3360 @ViewDebug.ExportedProperty(category = "layout") 3361 protected int mTop; 3362 /** 3363 * The distance in pixels from the top edge of this view's parent 3364 * to the bottom edge of this view. 3365 * {@hide} 3366 */ 3367 @ViewDebug.ExportedProperty(category = "layout") 3368 protected int mBottom; 3369 3370 /** 3371 * The offset, in pixels, by which the content of this view is scrolled 3372 * horizontally. 3373 * {@hide} 3374 */ 3375 @ViewDebug.ExportedProperty(category = "scrolling") 3376 protected int mScrollX; 3377 /** 3378 * The offset, in pixels, by which the content of this view is scrolled 3379 * vertically. 3380 * {@hide} 3381 */ 3382 @ViewDebug.ExportedProperty(category = "scrolling") 3383 protected int mScrollY; 3384 3385 /** 3386 * The left padding in pixels, that is the distance in pixels between the 3387 * left edge of this view and the left edge of its content. 3388 * {@hide} 3389 */ 3390 @ViewDebug.ExportedProperty(category = "padding") 3391 protected int mPaddingLeft = 0; 3392 /** 3393 * The right padding in pixels, that is the distance in pixels between the 3394 * right edge of this view and the right edge of its content. 3395 * {@hide} 3396 */ 3397 @ViewDebug.ExportedProperty(category = "padding") 3398 protected int mPaddingRight = 0; 3399 /** 3400 * The top padding in pixels, that is the distance in pixels between the 3401 * top edge of this view and the top edge of its content. 3402 * {@hide} 3403 */ 3404 @ViewDebug.ExportedProperty(category = "padding") 3405 protected int mPaddingTop; 3406 /** 3407 * The bottom padding in pixels, that is the distance in pixels between the 3408 * bottom edge of this view and the bottom edge of its content. 3409 * {@hide} 3410 */ 3411 @ViewDebug.ExportedProperty(category = "padding") 3412 protected int mPaddingBottom; 3413 3414 /** 3415 * The layout insets in pixels, that is the distance in pixels between the 3416 * visible edges of this view its bounds. 3417 */ 3418 private Insets mLayoutInsets; 3419 3420 /** 3421 * Briefly describes the view and is primarily used for accessibility support. 3422 */ 3423 private CharSequence mContentDescription; 3424 3425 /** 3426 * Specifies the id of a view for which this view serves as a label for 3427 * accessibility purposes. 3428 */ 3429 private int mLabelForId = View.NO_ID; 3430 3431 /** 3432 * Predicate for matching labeled view id with its label for 3433 * accessibility purposes. 3434 */ 3435 private MatchLabelForPredicate mMatchLabelForPredicate; 3436 3437 /** 3438 * Specifies a view before which this one is visited in accessibility traversal. 3439 */ 3440 private int mAccessibilityTraversalBeforeId = NO_ID; 3441 3442 /** 3443 * Specifies a view after which this one is visited in accessibility traversal. 3444 */ 3445 private int mAccessibilityTraversalAfterId = NO_ID; 3446 3447 /** 3448 * Predicate for matching a view by its id. 3449 */ 3450 private MatchIdPredicate mMatchIdPredicate; 3451 3452 /** 3453 * Cache the paddingRight set by the user to append to the scrollbar's size. 3454 * 3455 * @hide 3456 */ 3457 @ViewDebug.ExportedProperty(category = "padding") 3458 protected int mUserPaddingRight; 3459 3460 /** 3461 * Cache the paddingBottom set by the user to append to the scrollbar's size. 3462 * 3463 * @hide 3464 */ 3465 @ViewDebug.ExportedProperty(category = "padding") 3466 protected int mUserPaddingBottom; 3467 3468 /** 3469 * Cache the paddingLeft set by the user to append to the scrollbar's size. 3470 * 3471 * @hide 3472 */ 3473 @ViewDebug.ExportedProperty(category = "padding") 3474 protected int mUserPaddingLeft; 3475 3476 /** 3477 * Cache the paddingStart set by the user to append to the scrollbar's size. 3478 * 3479 */ 3480 @ViewDebug.ExportedProperty(category = "padding") 3481 int mUserPaddingStart; 3482 3483 /** 3484 * Cache the paddingEnd set by the user to append to the scrollbar's size. 3485 * 3486 */ 3487 @ViewDebug.ExportedProperty(category = "padding") 3488 int mUserPaddingEnd; 3489 3490 /** 3491 * Cache initial left padding. 3492 * 3493 * @hide 3494 */ 3495 int mUserPaddingLeftInitial; 3496 3497 /** 3498 * Cache initial right padding. 3499 * 3500 * @hide 3501 */ 3502 int mUserPaddingRightInitial; 3503 3504 /** 3505 * Default undefined padding 3506 */ 3507 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 3508 3509 /** 3510 * Cache if a left padding has been defined 3511 */ 3512 private boolean mLeftPaddingDefined = false; 3513 3514 /** 3515 * Cache if a right padding has been defined 3516 */ 3517 private boolean mRightPaddingDefined = false; 3518 3519 /** 3520 * @hide 3521 */ 3522 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 3523 /** 3524 * @hide 3525 */ 3526 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 3527 3528 private LongSparseLongArray mMeasureCache; 3529 3530 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 3531 private Drawable mBackground; 3532 private TintInfo mBackgroundTint; 3533 3534 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") 3535 private ForegroundInfo mForegroundInfo; 3536 3537 private Drawable mScrollIndicatorDrawable; 3538 3539 /** 3540 * RenderNode used for backgrounds. 3541 * <p> 3542 * When non-null and valid, this is expected to contain an up-to-date copy 3543 * of the background drawable. It is cleared on temporary detach, and reset 3544 * on cleanup. 3545 */ 3546 private RenderNode mBackgroundRenderNode; 3547 3548 private int mBackgroundResource; 3549 private boolean mBackgroundSizeChanged; 3550 3551 private String mTransitionName; 3552 3553 static class TintInfo { 3554 ColorStateList mTintList; 3555 PorterDuff.Mode mTintMode; 3556 boolean mHasTintMode; 3557 boolean mHasTintList; 3558 } 3559 3560 private static class ForegroundInfo { 3561 private Drawable mDrawable; 3562 private TintInfo mTintInfo; 3563 private int mGravity = Gravity.FILL; 3564 private boolean mInsidePadding = true; 3565 private boolean mBoundsChanged = true; 3566 private final Rect mSelfBounds = new Rect(); 3567 private final Rect mOverlayBounds = new Rect(); 3568 } 3569 3570 static class ListenerInfo { 3571 /** 3572 * Listener used to dispatch focus change events. 3573 * This field should be made private, so it is hidden from the SDK. 3574 * {@hide} 3575 */ 3576 protected OnFocusChangeListener mOnFocusChangeListener; 3577 3578 /** 3579 * Listeners for layout change events. 3580 */ 3581 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 3582 3583 protected OnScrollChangeListener mOnScrollChangeListener; 3584 3585 /** 3586 * Listeners for attach events. 3587 */ 3588 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 3589 3590 /** 3591 * Listener used to dispatch click events. 3592 * This field should be made private, so it is hidden from the SDK. 3593 * {@hide} 3594 */ 3595 public OnClickListener mOnClickListener; 3596 3597 /** 3598 * Listener used to dispatch long click events. 3599 * This field should be made private, so it is hidden from the SDK. 3600 * {@hide} 3601 */ 3602 protected OnLongClickListener mOnLongClickListener; 3603 3604 /** 3605 * Listener used to dispatch context click events. This field should be made private, so it 3606 * is hidden from the SDK. 3607 * {@hide} 3608 */ 3609 protected OnContextClickListener mOnContextClickListener; 3610 3611 /** 3612 * Listener used to build the context menu. 3613 * This field should be made private, so it is hidden from the SDK. 3614 * {@hide} 3615 */ 3616 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 3617 3618 private OnKeyListener mOnKeyListener; 3619 3620 private OnTouchListener mOnTouchListener; 3621 3622 private OnHoverListener mOnHoverListener; 3623 3624 private OnGenericMotionListener mOnGenericMotionListener; 3625 3626 private OnDragListener mOnDragListener; 3627 3628 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 3629 3630 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener; 3631 } 3632 3633 ListenerInfo mListenerInfo; 3634 3635 // Temporary values used to hold (x,y) coordinates when delegating from the 3636 // two-arg performLongClick() method to the legacy no-arg version. 3637 private float mLongClickX = Float.NaN; 3638 private float mLongClickY = Float.NaN; 3639 3640 /** 3641 * The application environment this view lives in. 3642 * This field should be made private, so it is hidden from the SDK. 3643 * {@hide} 3644 */ 3645 @ViewDebug.ExportedProperty(deepExport = true) 3646 protected Context mContext; 3647 3648 private final Resources mResources; 3649 3650 private ScrollabilityCache mScrollCache; 3651 3652 private int[] mDrawableState = null; 3653 3654 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND; 3655 3656 /** 3657 * Animator that automatically runs based on state changes. 3658 */ 3659 private StateListAnimator mStateListAnimator; 3660 3661 /** 3662 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 3663 * the user may specify which view to go to next. 3664 */ 3665 private int mNextFocusLeftId = View.NO_ID; 3666 3667 /** 3668 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 3669 * the user may specify which view to go to next. 3670 */ 3671 private int mNextFocusRightId = View.NO_ID; 3672 3673 /** 3674 * When this view has focus and the next focus is {@link #FOCUS_UP}, 3675 * the user may specify which view to go to next. 3676 */ 3677 private int mNextFocusUpId = View.NO_ID; 3678 3679 /** 3680 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 3681 * the user may specify which view to go to next. 3682 */ 3683 private int mNextFocusDownId = View.NO_ID; 3684 3685 /** 3686 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 3687 * the user may specify which view to go to next. 3688 */ 3689 int mNextFocusForwardId = View.NO_ID; 3690 3691 private CheckForLongPress mPendingCheckForLongPress; 3692 private CheckForTap mPendingCheckForTap = null; 3693 private PerformClick mPerformClick; 3694 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 3695 3696 private UnsetPressedState mUnsetPressedState; 3697 3698 /** 3699 * Whether the long press's action has been invoked. The tap's action is invoked on the 3700 * up event while a long press is invoked as soon as the long press duration is reached, so 3701 * a long press could be performed before the tap is checked, in which case the tap's action 3702 * should not be invoked. 3703 */ 3704 private boolean mHasPerformedLongPress; 3705 3706 /** 3707 * Whether a context click button is currently pressed down. This is true when the stylus is 3708 * touching the screen and the primary button has been pressed, or if a mouse's right button is 3709 * pressed. This is false once the button is released or if the stylus has been lifted. 3710 */ 3711 private boolean mInContextButtonPress; 3712 3713 /** 3714 * Whether the next up event should be ignored for the purposes of gesture recognition. This is 3715 * true after a stylus button press has occured, when the next up event should not be recognized 3716 * as a tap. 3717 */ 3718 private boolean mIgnoreNextUpEvent; 3719 3720 /** 3721 * The minimum height of the view. We'll try our best to have the height 3722 * of this view to at least this amount. 3723 */ 3724 @ViewDebug.ExportedProperty(category = "measurement") 3725 private int mMinHeight; 3726 3727 /** 3728 * The minimum width of the view. We'll try our best to have the width 3729 * of this view to at least this amount. 3730 */ 3731 @ViewDebug.ExportedProperty(category = "measurement") 3732 private int mMinWidth; 3733 3734 /** 3735 * The delegate to handle touch events that are physically in this view 3736 * but should be handled by another view. 3737 */ 3738 private TouchDelegate mTouchDelegate = null; 3739 3740 /** 3741 * Solid color to use as a background when creating the drawing cache. Enables 3742 * the cache to use 16 bit bitmaps instead of 32 bit. 3743 */ 3744 private int mDrawingCacheBackgroundColor = 0; 3745 3746 /** 3747 * Special tree observer used when mAttachInfo is null. 3748 */ 3749 private ViewTreeObserver mFloatingTreeObserver; 3750 3751 /** 3752 * Cache the touch slop from the context that created the view. 3753 */ 3754 private int mTouchSlop; 3755 3756 /** 3757 * Object that handles automatic animation of view properties. 3758 */ 3759 private ViewPropertyAnimator mAnimator = null; 3760 3761 /** 3762 * List of registered FrameMetricsObservers. 3763 */ 3764 private ArrayList<FrameMetricsObserver> mFrameMetricsObservers; 3765 3766 /** 3767 * Flag indicating that a drag can cross window boundaries. When 3768 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3769 * with this flag set, all visible applications with targetSdkVersion >= 3770 * {@link android.os.Build.VERSION_CODES#N API 24} will be able to participate 3771 * in the drag operation and receive the dragged content. 3772 * 3773 * <p>If this is the only flag set, then the drag recipient will only have access to text data 3774 * and intents contained in the {@link ClipData} object. Access to URIs contained in the 3775 * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags</p> 3776 */ 3777 public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256 3778 3779 /** 3780 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3781 * request read access to the content URI(s) contained in the {@link ClipData} object. 3782 * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION 3783 */ 3784 public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION; 3785 3786 /** 3787 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3788 * request write access to the content URI(s) contained in the {@link ClipData} object. 3789 * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION 3790 */ 3791 public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 3792 3793 /** 3794 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3795 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device 3796 * reboots until explicitly revoked with 3797 * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}. 3798 * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION 3799 */ 3800 public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 3801 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; 3802 3803 /** 3804 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3805 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix 3806 * match against the original granted URI. 3807 * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION 3808 */ 3809 public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 3810 Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; 3811 3812 /** 3813 * Flag indicating that the drag shadow will be opaque. When 3814 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3815 * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent. 3816 */ 3817 public static final int DRAG_FLAG_OPAQUE = 1 << 9; 3818 3819 /** 3820 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 3821 */ 3822 private float mVerticalScrollFactor; 3823 3824 /** 3825 * Position of the vertical scroll bar. 3826 */ 3827 private int mVerticalScrollbarPosition; 3828 3829 /** 3830 * Position the scroll bar at the default position as determined by the system. 3831 */ 3832 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 3833 3834 /** 3835 * Position the scroll bar along the left edge. 3836 */ 3837 public static final int SCROLLBAR_POSITION_LEFT = 1; 3838 3839 /** 3840 * Position the scroll bar along the right edge. 3841 */ 3842 public static final int SCROLLBAR_POSITION_RIGHT = 2; 3843 3844 /** 3845 * Indicates that the view does not have a layer. 3846 * 3847 * @see #getLayerType() 3848 * @see #setLayerType(int, android.graphics.Paint) 3849 * @see #LAYER_TYPE_SOFTWARE 3850 * @see #LAYER_TYPE_HARDWARE 3851 */ 3852 public static final int LAYER_TYPE_NONE = 0; 3853 3854 /** 3855 * <p>Indicates that the view has a software layer. A software layer is backed 3856 * by a bitmap and causes the view to be rendered using Android's software 3857 * rendering pipeline, even if hardware acceleration is enabled.</p> 3858 * 3859 * <p>Software layers have various usages:</p> 3860 * <p>When the application is not using hardware acceleration, a software layer 3861 * is useful to apply a specific color filter and/or blending mode and/or 3862 * translucency to a view and all its children.</p> 3863 * <p>When the application is using hardware acceleration, a software layer 3864 * is useful to render drawing primitives not supported by the hardware 3865 * accelerated pipeline. It can also be used to cache a complex view tree 3866 * into a texture and reduce the complexity of drawing operations. For instance, 3867 * when animating a complex view tree with a translation, a software layer can 3868 * be used to render the view tree only once.</p> 3869 * <p>Software layers should be avoided when the affected view tree updates 3870 * often. Every update will require to re-render the software layer, which can 3871 * potentially be slow (particularly when hardware acceleration is turned on 3872 * since the layer will have to be uploaded into a hardware texture after every 3873 * update.)</p> 3874 * 3875 * @see #getLayerType() 3876 * @see #setLayerType(int, android.graphics.Paint) 3877 * @see #LAYER_TYPE_NONE 3878 * @see #LAYER_TYPE_HARDWARE 3879 */ 3880 public static final int LAYER_TYPE_SOFTWARE = 1; 3881 3882 /** 3883 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 3884 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 3885 * OpenGL hardware) and causes the view to be rendered using Android's hardware 3886 * rendering pipeline, but only if hardware acceleration is turned on for the 3887 * view hierarchy. When hardware acceleration is turned off, hardware layers 3888 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 3889 * 3890 * <p>A hardware layer is useful to apply a specific color filter and/or 3891 * blending mode and/or translucency to a view and all its children.</p> 3892 * <p>A hardware layer can be used to cache a complex view tree into a 3893 * texture and reduce the complexity of drawing operations. For instance, 3894 * when animating a complex view tree with a translation, a hardware layer can 3895 * be used to render the view tree only once.</p> 3896 * <p>A hardware layer can also be used to increase the rendering quality when 3897 * rotation transformations are applied on a view. It can also be used to 3898 * prevent potential clipping issues when applying 3D transforms on a view.</p> 3899 * 3900 * @see #getLayerType() 3901 * @see #setLayerType(int, android.graphics.Paint) 3902 * @see #LAYER_TYPE_NONE 3903 * @see #LAYER_TYPE_SOFTWARE 3904 */ 3905 public static final int LAYER_TYPE_HARDWARE = 2; 3906 3907 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 3908 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 3909 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 3910 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 3911 }) 3912 int mLayerType = LAYER_TYPE_NONE; 3913 Paint mLayerPaint; 3914 3915 /** 3916 * Set to true when drawing cache is enabled and cannot be created. 3917 * 3918 * @hide 3919 */ 3920 public boolean mCachingFailed; 3921 private Bitmap mDrawingCache; 3922 private Bitmap mUnscaledDrawingCache; 3923 3924 /** 3925 * RenderNode holding View properties, potentially holding a DisplayList of View content. 3926 * <p> 3927 * When non-null and valid, this is expected to contain an up-to-date copy 3928 * of the View content. Its DisplayList content is cleared on temporary detach and reset on 3929 * cleanup. 3930 */ 3931 final RenderNode mRenderNode; 3932 3933 /** 3934 * Set to true when the view is sending hover accessibility events because it 3935 * is the innermost hovered view. 3936 */ 3937 private boolean mSendingHoverAccessibilityEvents; 3938 3939 /** 3940 * Delegate for injecting accessibility functionality. 3941 */ 3942 AccessibilityDelegate mAccessibilityDelegate; 3943 3944 /** 3945 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 3946 * and add/remove objects to/from the overlay directly through the Overlay methods. 3947 */ 3948 ViewOverlay mOverlay; 3949 3950 /** 3951 * The currently active parent view for receiving delegated nested scrolling events. 3952 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared 3953 * by {@link #stopNestedScroll()} at the same point where we clear 3954 * requestDisallowInterceptTouchEvent. 3955 */ 3956 private ViewParent mNestedScrollingParent; 3957 3958 /** 3959 * Consistency verifier for debugging purposes. 3960 * @hide 3961 */ 3962 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 3963 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 3964 new InputEventConsistencyVerifier(this, 0) : null; 3965 3966 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 3967 3968 private int[] mTempNestedScrollConsumed; 3969 3970 /** 3971 * An overlay is going to draw this View instead of being drawn as part of this 3972 * View's parent. mGhostView is the View in the Overlay that must be invalidated 3973 * when this view is invalidated. 3974 */ 3975 GhostView mGhostView; 3976 3977 /** 3978 * Holds pairs of adjacent attribute data: attribute name followed by its value. 3979 * @hide 3980 */ 3981 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true) 3982 public String[] mAttributes; 3983 3984 /** 3985 * Maps a Resource id to its name. 3986 */ 3987 private static SparseArray<String> mAttributeMap; 3988 3989 /** 3990 * Queue of pending runnables. Used to postpone calls to post() until this 3991 * view is attached and has a handler. 3992 */ 3993 private HandlerActionQueue mRunQueue; 3994 3995 /** 3996 * The pointer icon when the mouse hovers on this view. The default is null. 3997 */ 3998 private PointerIcon mPointerIcon; 3999 4000 /** 4001 * @hide 4002 */ 4003 String mStartActivityRequestWho; 4004 4005 @Nullable 4006 private RoundScrollbarRenderer mRoundScrollbarRenderer; 4007 4008 /** 4009 * Simple constructor to use when creating a view from code. 4010 * 4011 * @param context The Context the view is running in, through which it can 4012 * access the current theme, resources, etc. 4013 */ View(Context context)4014 public View(Context context) { 4015 mContext = context; 4016 mResources = context != null ? context.getResources() : null; 4017 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; 4018 // Set some flags defaults 4019 mPrivateFlags2 = 4020 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 4021 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 4022 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 4023 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 4024 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 4025 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 4026 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 4027 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 4028 mUserPaddingStart = UNDEFINED_PADDING; 4029 mUserPaddingEnd = UNDEFINED_PADDING; 4030 mRenderNode = RenderNode.create(getClass().getName(), this); 4031 4032 if (!sCompatibilityDone && context != null) { 4033 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4034 4035 // Older apps may need this compatibility hack for measurement. 4036 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1; 4037 4038 // Older apps expect onMeasure() to always be called on a layout pass, regardless 4039 // of whether a layout was requested on that View. 4040 sIgnoreMeasureCache = targetSdkVersion < KITKAT; 4041 4042 Canvas.sCompatibilityRestore = targetSdkVersion < M; 4043 4044 // In M and newer, our widgets can pass a "hint" value in the size 4045 // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers 4046 // know what the expected parent size is going to be, so e.g. list items can size 4047 // themselves at 1/3 the size of their container. It breaks older apps though, 4048 // specifically apps that use some popular open source libraries. 4049 sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M; 4050 4051 // Old versions of the platform would give different results from 4052 // LinearLayout measurement passes using EXACTLY and non-EXACTLY 4053 // modes, so we always need to run an additional EXACTLY pass. 4054 sAlwaysRemeasureExactly = targetSdkVersion <= M; 4055 4056 // Prior to N, layout params could change without requiring a 4057 // subsequent call to setLayoutParams() and they would usually 4058 // work. Partial layout breaks this assumption. 4059 sLayoutParamsAlwaysChanged = targetSdkVersion <= M; 4060 4061 // Prior to N, TextureView would silently ignore calls to setBackground/setForeground. 4062 // On N+, we throw, but that breaks compatibility with apps that use these methods. 4063 sTextureViewIgnoresDrawableSetters = targetSdkVersion <= M; 4064 4065 // Prior to N, we would drop margins in LayoutParam conversions. The fix triggers bugs 4066 // in apps so we target check it to avoid breaking existing apps. 4067 sPreserveMarginParamsInLayoutParamConversion = targetSdkVersion >= N; 4068 4069 sCompatibilityDone = true; 4070 } 4071 } 4072 4073 /** 4074 * Constructor that is called when inflating a view from XML. This is called 4075 * when a view is being constructed from an XML file, supplying attributes 4076 * that were specified in the XML file. This version uses a default style of 4077 * 0, so the only attribute values applied are those in the Context's Theme 4078 * and the given AttributeSet. 4079 * 4080 * <p> 4081 * The method onFinishInflate() will be called after all children have been 4082 * added. 4083 * 4084 * @param context The Context the view is running in, through which it can 4085 * access the current theme, resources, etc. 4086 * @param attrs The attributes of the XML tag that is inflating the view. 4087 * @see #View(Context, AttributeSet, int) 4088 */ 4089 public View(Context context, @Nullable AttributeSet attrs) { 4090 this(context, attrs, 0); 4091 } 4092 4093 /** 4094 * Perform inflation from XML and apply a class-specific base style from a 4095 * theme attribute. This constructor of View allows subclasses to use their 4096 * own base style when they are inflating. For example, a Button class's 4097 * constructor would call this version of the super class constructor and 4098 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this 4099 * allows the theme's button style to modify all of the base view attributes 4100 * (in particular its background) as well as the Button class's attributes. 4101 * 4102 * @param context The Context the view is running in, through which it can 4103 * access the current theme, resources, etc. 4104 * @param attrs The attributes of the XML tag that is inflating the view. 4105 * @param defStyleAttr An attribute in the current theme that contains a 4106 * reference to a style resource that supplies default values for 4107 * the view. Can be 0 to not look for defaults. 4108 * @see #View(Context, AttributeSet) 4109 */ 4110 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 4111 this(context, attrs, defStyleAttr, 0); 4112 } 4113 4114 /** 4115 * Perform inflation from XML and apply a class-specific base style from a 4116 * theme attribute or style resource. This constructor of View allows 4117 * subclasses to use their own base style when they are inflating. 4118 * <p> 4119 * When determining the final value of a particular attribute, there are 4120 * four inputs that come into play: 4121 * <ol> 4122 * <li>Any attribute values in the given AttributeSet. 4123 * <li>The style resource specified in the AttributeSet (named "style"). 4124 * <li>The default style specified by <var>defStyleAttr</var>. 4125 * <li>The default style specified by <var>defStyleRes</var>. 4126 * <li>The base values in this theme. 4127 * </ol> 4128 * <p> 4129 * Each of these inputs is considered in-order, with the first listed taking 4130 * precedence over the following ones. In other words, if in the 4131 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code> 4132 * , then the button's text will <em>always</em> be black, regardless of 4133 * what is specified in any of the styles. 4134 * 4135 * @param context The Context the view is running in, through which it can 4136 * access the current theme, resources, etc. 4137 * @param attrs The attributes of the XML tag that is inflating the view. 4138 * @param defStyleAttr An attribute in the current theme that contains a 4139 * reference to a style resource that supplies default values for 4140 * the view. Can be 0 to not look for defaults. 4141 * @param defStyleRes A resource identifier of a style resource that 4142 * supplies default values for the view, used only if 4143 * defStyleAttr is 0 or can not be found in the theme. Can be 0 4144 * to not look for defaults. 4145 * @see #View(Context, AttributeSet, int) 4146 */ 4147 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 4148 this(context); 4149 4150 final TypedArray a = context.obtainStyledAttributes( 4151 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); 4152 4153 if (mDebugViewAttributes) { 4154 saveAttributeData(attrs, a); 4155 } 4156 4157 Drawable background = null; 4158 4159 int leftPadding = -1; 4160 int topPadding = -1; 4161 int rightPadding = -1; 4162 int bottomPadding = -1; 4163 int startPadding = UNDEFINED_PADDING; 4164 int endPadding = UNDEFINED_PADDING; 4165 4166 int padding = -1; 4167 4168 int viewFlagValues = 0; 4169 int viewFlagMasks = 0; 4170 4171 boolean setScrollContainer = false; 4172 4173 int x = 0; 4174 int y = 0; 4175 4176 float tx = 0; 4177 float ty = 0; 4178 float tz = 0; 4179 float elevation = 0; 4180 float rotation = 0; 4181 float rotationX = 0; 4182 float rotationY = 0; 4183 float sx = 1f; 4184 float sy = 1f; 4185 boolean transformSet = false; 4186 4187 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 4188 int overScrollMode = mOverScrollMode; 4189 boolean initializeScrollbars = false; 4190 boolean initializeScrollIndicators = false; 4191 4192 boolean startPaddingDefined = false; 4193 boolean endPaddingDefined = false; 4194 boolean leftPaddingDefined = false; 4195 boolean rightPaddingDefined = false; 4196 4197 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4198 4199 final int N = a.getIndexCount(); 4200 for (int i = 0; i < N; i++) { 4201 int attr = a.getIndex(i); 4202 switch (attr) { 4203 case com.android.internal.R.styleable.View_background: 4204 background = a.getDrawable(attr); 4205 break; 4206 case com.android.internal.R.styleable.View_padding: 4207 padding = a.getDimensionPixelSize(attr, -1); 4208 mUserPaddingLeftInitial = padding; 4209 mUserPaddingRightInitial = padding; 4210 leftPaddingDefined = true; 4211 rightPaddingDefined = true; 4212 break; 4213 case com.android.internal.R.styleable.View_paddingLeft: 4214 leftPadding = a.getDimensionPixelSize(attr, -1); 4215 mUserPaddingLeftInitial = leftPadding; 4216 leftPaddingDefined = true; 4217 break; 4218 case com.android.internal.R.styleable.View_paddingTop: 4219 topPadding = a.getDimensionPixelSize(attr, -1); 4220 break; 4221 case com.android.internal.R.styleable.View_paddingRight: 4222 rightPadding = a.getDimensionPixelSize(attr, -1); 4223 mUserPaddingRightInitial = rightPadding; 4224 rightPaddingDefined = true; 4225 break; 4226 case com.android.internal.R.styleable.View_paddingBottom: 4227 bottomPadding = a.getDimensionPixelSize(attr, -1); 4228 break; 4229 case com.android.internal.R.styleable.View_paddingStart: 4230 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4231 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 4232 break; 4233 case com.android.internal.R.styleable.View_paddingEnd: 4234 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4235 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 4236 break; 4237 case com.android.internal.R.styleable.View_scrollX: 4238 x = a.getDimensionPixelOffset(attr, 0); 4239 break; 4240 case com.android.internal.R.styleable.View_scrollY: 4241 y = a.getDimensionPixelOffset(attr, 0); 4242 break; 4243 case com.android.internal.R.styleable.View_alpha: 4244 setAlpha(a.getFloat(attr, 1f)); 4245 break; 4246 case com.android.internal.R.styleable.View_transformPivotX: 4247 setPivotX(a.getDimension(attr, 0)); 4248 break; 4249 case com.android.internal.R.styleable.View_transformPivotY: 4250 setPivotY(a.getDimension(attr, 0)); 4251 break; 4252 case com.android.internal.R.styleable.View_translationX: 4253 tx = a.getDimension(attr, 0); 4254 transformSet = true; 4255 break; 4256 case com.android.internal.R.styleable.View_translationY: 4257 ty = a.getDimension(attr, 0); 4258 transformSet = true; 4259 break; 4260 case com.android.internal.R.styleable.View_translationZ: 4261 tz = a.getDimension(attr, 0); 4262 transformSet = true; 4263 break; 4264 case com.android.internal.R.styleable.View_elevation: 4265 elevation = a.getDimension(attr, 0); 4266 transformSet = true; 4267 break; 4268 case com.android.internal.R.styleable.View_rotation: 4269 rotation = a.getFloat(attr, 0); 4270 transformSet = true; 4271 break; 4272 case com.android.internal.R.styleable.View_rotationX: 4273 rotationX = a.getFloat(attr, 0); 4274 transformSet = true; 4275 break; 4276 case com.android.internal.R.styleable.View_rotationY: 4277 rotationY = a.getFloat(attr, 0); 4278 transformSet = true; 4279 break; 4280 case com.android.internal.R.styleable.View_scaleX: 4281 sx = a.getFloat(attr, 1f); 4282 transformSet = true; 4283 break; 4284 case com.android.internal.R.styleable.View_scaleY: 4285 sy = a.getFloat(attr, 1f); 4286 transformSet = true; 4287 break; 4288 case com.android.internal.R.styleable.View_id: 4289 mID = a.getResourceId(attr, NO_ID); 4290 break; 4291 case com.android.internal.R.styleable.View_tag: 4292 mTag = a.getText(attr); 4293 break; 4294 case com.android.internal.R.styleable.View_fitsSystemWindows: 4295 if (a.getBoolean(attr, false)) { 4296 viewFlagValues |= FITS_SYSTEM_WINDOWS; 4297 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 4298 } 4299 break; 4300 case com.android.internal.R.styleable.View_focusable: 4301 if (a.getBoolean(attr, false)) { 4302 viewFlagValues |= FOCUSABLE; 4303 viewFlagMasks |= FOCUSABLE_MASK; 4304 } 4305 break; 4306 case com.android.internal.R.styleable.View_focusableInTouchMode: 4307 if (a.getBoolean(attr, false)) { 4308 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 4309 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 4310 } 4311 break; 4312 case com.android.internal.R.styleable.View_clickable: 4313 if (a.getBoolean(attr, false)) { 4314 viewFlagValues |= CLICKABLE; 4315 viewFlagMasks |= CLICKABLE; 4316 } 4317 break; 4318 case com.android.internal.R.styleable.View_longClickable: 4319 if (a.getBoolean(attr, false)) { 4320 viewFlagValues |= LONG_CLICKABLE; 4321 viewFlagMasks |= LONG_CLICKABLE; 4322 } 4323 break; 4324 case com.android.internal.R.styleable.View_contextClickable: 4325 if (a.getBoolean(attr, false)) { 4326 viewFlagValues |= CONTEXT_CLICKABLE; 4327 viewFlagMasks |= CONTEXT_CLICKABLE; 4328 } 4329 break; 4330 case com.android.internal.R.styleable.View_saveEnabled: 4331 if (!a.getBoolean(attr, true)) { 4332 viewFlagValues |= SAVE_DISABLED; 4333 viewFlagMasks |= SAVE_DISABLED_MASK; 4334 } 4335 break; 4336 case com.android.internal.R.styleable.View_duplicateParentState: 4337 if (a.getBoolean(attr, false)) { 4338 viewFlagValues |= DUPLICATE_PARENT_STATE; 4339 viewFlagMasks |= DUPLICATE_PARENT_STATE; 4340 } 4341 break; 4342 case com.android.internal.R.styleable.View_visibility: 4343 final int visibility = a.getInt(attr, 0); 4344 if (visibility != 0) { 4345 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 4346 viewFlagMasks |= VISIBILITY_MASK; 4347 } 4348 break; 4349 case com.android.internal.R.styleable.View_layoutDirection: 4350 // Clear any layout direction flags (included resolved bits) already set 4351 mPrivateFlags2 &= 4352 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 4353 // Set the layout direction flags depending on the value of the attribute 4354 final int layoutDirection = a.getInt(attr, -1); 4355 final int value = (layoutDirection != -1) ? 4356 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 4357 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 4358 break; 4359 case com.android.internal.R.styleable.View_drawingCacheQuality: 4360 final int cacheQuality = a.getInt(attr, 0); 4361 if (cacheQuality != 0) { 4362 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 4363 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 4364 } 4365 break; 4366 case com.android.internal.R.styleable.View_contentDescription: 4367 setContentDescription(a.getString(attr)); 4368 break; 4369 case com.android.internal.R.styleable.View_accessibilityTraversalBefore: 4370 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); 4371 break; 4372 case com.android.internal.R.styleable.View_accessibilityTraversalAfter: 4373 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); 4374 break; 4375 case com.android.internal.R.styleable.View_labelFor: 4376 setLabelFor(a.getResourceId(attr, NO_ID)); 4377 break; 4378 case com.android.internal.R.styleable.View_soundEffectsEnabled: 4379 if (!a.getBoolean(attr, true)) { 4380 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 4381 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 4382 } 4383 break; 4384 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 4385 if (!a.getBoolean(attr, true)) { 4386 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 4387 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 4388 } 4389 break; 4390 case R.styleable.View_scrollbars: 4391 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 4392 if (scrollbars != SCROLLBARS_NONE) { 4393 viewFlagValues |= scrollbars; 4394 viewFlagMasks |= SCROLLBARS_MASK; 4395 initializeScrollbars = true; 4396 } 4397 break; 4398 //noinspection deprecation 4399 case R.styleable.View_fadingEdge: 4400 if (targetSdkVersion >= ICE_CREAM_SANDWICH) { 4401 // Ignore the attribute starting with ICS 4402 break; 4403 } 4404 // With builds < ICS, fall through and apply fading edges 4405 case R.styleable.View_requiresFadingEdge: 4406 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 4407 if (fadingEdge != FADING_EDGE_NONE) { 4408 viewFlagValues |= fadingEdge; 4409 viewFlagMasks |= FADING_EDGE_MASK; 4410 initializeFadingEdgeInternal(a); 4411 } 4412 break; 4413 case R.styleable.View_scrollbarStyle: 4414 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 4415 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4416 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 4417 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 4418 } 4419 break; 4420 case R.styleable.View_isScrollContainer: 4421 setScrollContainer = true; 4422 if (a.getBoolean(attr, false)) { 4423 setScrollContainer(true); 4424 } 4425 break; 4426 case com.android.internal.R.styleable.View_keepScreenOn: 4427 if (a.getBoolean(attr, false)) { 4428 viewFlagValues |= KEEP_SCREEN_ON; 4429 viewFlagMasks |= KEEP_SCREEN_ON; 4430 } 4431 break; 4432 case R.styleable.View_filterTouchesWhenObscured: 4433 if (a.getBoolean(attr, false)) { 4434 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 4435 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 4436 } 4437 break; 4438 case R.styleable.View_nextFocusLeft: 4439 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 4440 break; 4441 case R.styleable.View_nextFocusRight: 4442 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 4443 break; 4444 case R.styleable.View_nextFocusUp: 4445 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 4446 break; 4447 case R.styleable.View_nextFocusDown: 4448 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 4449 break; 4450 case R.styleable.View_nextFocusForward: 4451 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 4452 break; 4453 case R.styleable.View_minWidth: 4454 mMinWidth = a.getDimensionPixelSize(attr, 0); 4455 break; 4456 case R.styleable.View_minHeight: 4457 mMinHeight = a.getDimensionPixelSize(attr, 0); 4458 break; 4459 case R.styleable.View_onClick: 4460 if (context.isRestricted()) { 4461 throw new IllegalStateException("The android:onClick attribute cannot " 4462 + "be used within a restricted context"); 4463 } 4464 4465 final String handlerName = a.getString(attr); 4466 if (handlerName != null) { 4467 setOnClickListener(new DeclaredOnClickListener(this, handlerName)); 4468 } 4469 break; 4470 case R.styleable.View_overScrollMode: 4471 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 4472 break; 4473 case R.styleable.View_verticalScrollbarPosition: 4474 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 4475 break; 4476 case R.styleable.View_layerType: 4477 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 4478 break; 4479 case R.styleable.View_textDirection: 4480 // Clear any text direction flag already set 4481 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 4482 // Set the text direction flags depending on the value of the attribute 4483 final int textDirection = a.getInt(attr, -1); 4484 if (textDirection != -1) { 4485 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 4486 } 4487 break; 4488 case R.styleable.View_textAlignment: 4489 // Clear any text alignment flag already set 4490 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 4491 // Set the text alignment flag depending on the value of the attribute 4492 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 4493 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 4494 break; 4495 case R.styleable.View_importantForAccessibility: 4496 setImportantForAccessibility(a.getInt(attr, 4497 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 4498 break; 4499 case R.styleable.View_accessibilityLiveRegion: 4500 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 4501 break; 4502 case R.styleable.View_transitionName: 4503 setTransitionName(a.getString(attr)); 4504 break; 4505 case R.styleable.View_nestedScrollingEnabled: 4506 setNestedScrollingEnabled(a.getBoolean(attr, false)); 4507 break; 4508 case R.styleable.View_stateListAnimator: 4509 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, 4510 a.getResourceId(attr, 0))); 4511 break; 4512 case R.styleable.View_backgroundTint: 4513 // This will get applied later during setBackground(). 4514 if (mBackgroundTint == null) { 4515 mBackgroundTint = new TintInfo(); 4516 } 4517 mBackgroundTint.mTintList = a.getColorStateList( 4518 R.styleable.View_backgroundTint); 4519 mBackgroundTint.mHasTintList = true; 4520 break; 4521 case R.styleable.View_backgroundTintMode: 4522 // This will get applied later during setBackground(). 4523 if (mBackgroundTint == null) { 4524 mBackgroundTint = new TintInfo(); 4525 } 4526 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( 4527 R.styleable.View_backgroundTintMode, -1), null); 4528 mBackgroundTint.mHasTintMode = true; 4529 break; 4530 case R.styleable.View_outlineProvider: 4531 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider, 4532 PROVIDER_BACKGROUND)); 4533 break; 4534 case R.styleable.View_foreground: 4535 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4536 setForeground(a.getDrawable(attr)); 4537 } 4538 break; 4539 case R.styleable.View_foregroundGravity: 4540 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4541 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY)); 4542 } 4543 break; 4544 case R.styleable.View_foregroundTintMode: 4545 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4546 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); 4547 } 4548 break; 4549 case R.styleable.View_foregroundTint: 4550 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4551 setForegroundTintList(a.getColorStateList(attr)); 4552 } 4553 break; 4554 case R.styleable.View_foregroundInsidePadding: 4555 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4556 if (mForegroundInfo == null) { 4557 mForegroundInfo = new ForegroundInfo(); 4558 } 4559 mForegroundInfo.mInsidePadding = a.getBoolean(attr, 4560 mForegroundInfo.mInsidePadding); 4561 } 4562 break; 4563 case R.styleable.View_scrollIndicators: 4564 final int scrollIndicators = 4565 (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT) 4566 & SCROLL_INDICATORS_PFLAG3_MASK; 4567 if (scrollIndicators != 0) { 4568 mPrivateFlags3 |= scrollIndicators; 4569 initializeScrollIndicators = true; 4570 } 4571 break; 4572 case R.styleable.View_pointerIcon: 4573 final int resourceId = a.getResourceId(attr, 0); 4574 if (resourceId != 0) { 4575 setPointerIcon(PointerIcon.load( 4576 context.getResources(), resourceId)); 4577 } else { 4578 final int pointerType = a.getInt(attr, PointerIcon.TYPE_NOT_SPECIFIED); 4579 if (pointerType != PointerIcon.TYPE_NOT_SPECIFIED) { 4580 setPointerIcon(PointerIcon.getSystemIcon(context, pointerType)); 4581 } 4582 } 4583 break; 4584 case R.styleable.View_forceHasOverlappingRendering: 4585 if (a.peekValue(attr) != null) { 4586 forceHasOverlappingRendering(a.getBoolean(attr, true)); 4587 } 4588 break; 4589 4590 } 4591 } 4592 4593 setOverScrollMode(overScrollMode); 4594 4595 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 4596 // the resolved layout direction). Those cached values will be used later during padding 4597 // resolution. 4598 mUserPaddingStart = startPadding; 4599 mUserPaddingEnd = endPadding; 4600 4601 if (background != null) { 4602 setBackground(background); 4603 } 4604 4605 // setBackground above will record that padding is currently provided by the background. 4606 // If we have padding specified via xml, record that here instead and use it. 4607 mLeftPaddingDefined = leftPaddingDefined; 4608 mRightPaddingDefined = rightPaddingDefined; 4609 4610 if (padding >= 0) { 4611 leftPadding = padding; 4612 topPadding = padding; 4613 rightPadding = padding; 4614 bottomPadding = padding; 4615 mUserPaddingLeftInitial = padding; 4616 mUserPaddingRightInitial = padding; 4617 } 4618 4619 if (isRtlCompatibilityMode()) { 4620 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 4621 // left / right padding are used if defined (meaning here nothing to do). If they are not 4622 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 4623 // start / end and resolve them as left / right (layout direction is not taken into account). 4624 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4625 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4626 // defined. 4627 if (!mLeftPaddingDefined && startPaddingDefined) { 4628 leftPadding = startPadding; 4629 } 4630 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 4631 if (!mRightPaddingDefined && endPaddingDefined) { 4632 rightPadding = endPadding; 4633 } 4634 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 4635 } else { 4636 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 4637 // values defined. Otherwise, left /right values are used. 4638 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4639 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4640 // defined. 4641 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 4642 4643 if (mLeftPaddingDefined && !hasRelativePadding) { 4644 mUserPaddingLeftInitial = leftPadding; 4645 } 4646 if (mRightPaddingDefined && !hasRelativePadding) { 4647 mUserPaddingRightInitial = rightPadding; 4648 } 4649 } 4650 4651 internalSetPadding( 4652 mUserPaddingLeftInitial, 4653 topPadding >= 0 ? topPadding : mPaddingTop, 4654 mUserPaddingRightInitial, 4655 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 4656 4657 if (viewFlagMasks != 0) { 4658 setFlags(viewFlagValues, viewFlagMasks); 4659 } 4660 4661 if (initializeScrollbars) { 4662 initializeScrollbarsInternal(a); 4663 } 4664 4665 if (initializeScrollIndicators) { 4666 initializeScrollIndicatorsInternal(); 4667 } 4668 4669 a.recycle(); 4670 4671 // Needs to be called after mViewFlags is set 4672 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4673 recomputePadding(); 4674 } 4675 4676 if (x != 0 || y != 0) { 4677 scrollTo(x, y); 4678 } 4679 4680 if (transformSet) { 4681 setTranslationX(tx); 4682 setTranslationY(ty); 4683 setTranslationZ(tz); 4684 setElevation(elevation); 4685 setRotation(rotation); 4686 setRotationX(rotationX); 4687 setRotationY(rotationY); 4688 setScaleX(sx); 4689 setScaleY(sy); 4690 } 4691 4692 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 4693 setScrollContainer(true); 4694 } 4695 4696 computeOpaqueFlags(); 4697 } 4698 4699 /** 4700 * An implementation of OnClickListener that attempts to lazily load a 4701 * named click handling method from a parent or ancestor context. 4702 */ 4703 private static class DeclaredOnClickListener implements OnClickListener { 4704 private final View mHostView; 4705 private final String mMethodName; 4706 4707 private Method mResolvedMethod; 4708 private Context mResolvedContext; 4709 DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4710 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { 4711 mHostView = hostView; 4712 mMethodName = methodName; 4713 } 4714 4715 @Override onClick(@onNull View v)4716 public void onClick(@NonNull View v) { 4717 if (mResolvedMethod == null) { 4718 resolveMethod(mHostView.getContext(), mMethodName); 4719 } 4720 4721 try { 4722 mResolvedMethod.invoke(mResolvedContext, v); 4723 } catch (IllegalAccessException e) { 4724 throw new IllegalStateException( 4725 "Could not execute non-public method for android:onClick", e); 4726 } catch (InvocationTargetException e) { 4727 throw new IllegalStateException( 4728 "Could not execute method for android:onClick", e); 4729 } 4730 } 4731 4732 @NonNull resolveMethod(@ullable Context context, @NonNull String name)4733 private void resolveMethod(@Nullable Context context, @NonNull String name) { 4734 while (context != null) { 4735 try { 4736 if (!context.isRestricted()) { 4737 final Method method = context.getClass().getMethod(mMethodName, View.class); 4738 if (method != null) { 4739 mResolvedMethod = method; 4740 mResolvedContext = context; 4741 return; 4742 } 4743 } 4744 } catch (NoSuchMethodException e) { 4745 // Failed to find method, keep searching up the hierarchy. 4746 } 4747 4748 if (context instanceof ContextWrapper) { 4749 context = ((ContextWrapper) context).getBaseContext(); 4750 } else { 4751 // Can't search up the hierarchy, null out and fail. 4752 context = null; 4753 } 4754 } 4755 4756 final int id = mHostView.getId(); 4757 final String idText = id == NO_ID ? "" : " with id '" 4758 + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; 4759 throw new IllegalStateException("Could not find method " + mMethodName 4760 + "(View) in a parent or ancestor Context for android:onClick " 4761 + "attribute defined on view " + mHostView.getClass() + idText); 4762 } 4763 } 4764 4765 /** 4766 * Non-public constructor for use in testing 4767 */ View()4768 View() { 4769 mResources = null; 4770 mRenderNode = RenderNode.create(getClass().getName(), this); 4771 } 4772 getAttributeMap()4773 private static SparseArray<String> getAttributeMap() { 4774 if (mAttributeMap == null) { 4775 mAttributeMap = new SparseArray<>(); 4776 } 4777 return mAttributeMap; 4778 } 4779 saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4780 private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { 4781 final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); 4782 final int indexCount = t.getIndexCount(); 4783 final String[] attributes = new String[(attrsCount + indexCount) * 2]; 4784 4785 int i = 0; 4786 4787 // Store raw XML attributes. 4788 for (int j = 0; j < attrsCount; ++j) { 4789 attributes[i] = attrs.getAttributeName(j); 4790 attributes[i + 1] = attrs.getAttributeValue(j); 4791 i += 2; 4792 } 4793 4794 // Store resolved styleable attributes. 4795 final Resources res = t.getResources(); 4796 final SparseArray<String> attributeMap = getAttributeMap(); 4797 for (int j = 0; j < indexCount; ++j) { 4798 final int index = t.getIndex(j); 4799 if (!t.hasValueOrEmpty(index)) { 4800 // Value is undefined. Skip it. 4801 continue; 4802 } 4803 4804 final int resourceId = t.getResourceId(index, 0); 4805 if (resourceId == 0) { 4806 // Value is not a reference. Skip it. 4807 continue; 4808 } 4809 4810 String resourceName = attributeMap.get(resourceId); 4811 if (resourceName == null) { 4812 try { 4813 resourceName = res.getResourceName(resourceId); 4814 } catch (Resources.NotFoundException e) { 4815 resourceName = "0x" + Integer.toHexString(resourceId); 4816 } 4817 attributeMap.put(resourceId, resourceName); 4818 } 4819 4820 attributes[i] = resourceName; 4821 attributes[i + 1] = t.getString(index); 4822 i += 2; 4823 } 4824 4825 // Trim to fit contents. 4826 final String[] trimmed = new String[i]; 4827 System.arraycopy(attributes, 0, trimmed, 0, i); 4828 mAttributes = trimmed; 4829 } 4830 toString()4831 public String toString() { 4832 StringBuilder out = new StringBuilder(128); 4833 out.append(getClass().getName()); 4834 out.append('{'); 4835 out.append(Integer.toHexString(System.identityHashCode(this))); 4836 out.append(' '); 4837 switch (mViewFlags&VISIBILITY_MASK) { 4838 case VISIBLE: out.append('V'); break; 4839 case INVISIBLE: out.append('I'); break; 4840 case GONE: out.append('G'); break; 4841 default: out.append('.'); break; 4842 } 4843 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.'); 4844 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 4845 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 4846 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 4847 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 4848 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 4849 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 4850 out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.'); 4851 out.append(' '); 4852 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 4853 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 4854 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 4855 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 4856 out.append('p'); 4857 } else { 4858 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 4859 } 4860 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 4861 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 4862 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 4863 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 4864 out.append(' '); 4865 out.append(mLeft); 4866 out.append(','); 4867 out.append(mTop); 4868 out.append('-'); 4869 out.append(mRight); 4870 out.append(','); 4871 out.append(mBottom); 4872 final int id = getId(); 4873 if (id != NO_ID) { 4874 out.append(" #"); 4875 out.append(Integer.toHexString(id)); 4876 final Resources r = mResources; 4877 if (id > 0 && Resources.resourceHasPackage(id) && r != null) { 4878 try { 4879 String pkgname; 4880 switch (id&0xff000000) { 4881 case 0x7f000000: 4882 pkgname="app"; 4883 break; 4884 case 0x01000000: 4885 pkgname="android"; 4886 break; 4887 default: 4888 pkgname = r.getResourcePackageName(id); 4889 break; 4890 } 4891 String typename = r.getResourceTypeName(id); 4892 String entryname = r.getResourceEntryName(id); 4893 out.append(" "); 4894 out.append(pkgname); 4895 out.append(":"); 4896 out.append(typename); 4897 out.append("/"); 4898 out.append(entryname); 4899 } catch (Resources.NotFoundException e) { 4900 } 4901 } 4902 } 4903 out.append("}"); 4904 return out.toString(); 4905 } 4906 4907 /** 4908 * <p> 4909 * Initializes the fading edges from a given set of styled attributes. This 4910 * method should be called by subclasses that need fading edges and when an 4911 * instance of these subclasses is created programmatically rather than 4912 * being inflated from XML. This method is automatically called when the XML 4913 * is inflated. 4914 * </p> 4915 * 4916 * @param a the styled attributes set to initialize the fading edges from 4917 * 4918 * @removed 4919 */ initializeFadingEdge(TypedArray a)4920 protected void initializeFadingEdge(TypedArray a) { 4921 // This method probably shouldn't have been included in the SDK to begin with. 4922 // It relies on 'a' having been initialized using an attribute filter array that is 4923 // not publicly available to the SDK. The old method has been renamed 4924 // to initializeFadingEdgeInternal and hidden for framework use only; 4925 // this one initializes using defaults to make it safe to call for apps. 4926 4927 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 4928 4929 initializeFadingEdgeInternal(arr); 4930 4931 arr.recycle(); 4932 } 4933 4934 /** 4935 * <p> 4936 * Initializes the fading edges from a given set of styled attributes. This 4937 * method should be called by subclasses that need fading edges and when an 4938 * instance of these subclasses is created programmatically rather than 4939 * being inflated from XML. This method is automatically called when the XML 4940 * is inflated. 4941 * </p> 4942 * 4943 * @param a the styled attributes set to initialize the fading edges from 4944 * @hide This is the real method; the public one is shimmed to be safe to call from apps. 4945 */ initializeFadingEdgeInternal(TypedArray a)4946 protected void initializeFadingEdgeInternal(TypedArray a) { 4947 initScrollCache(); 4948 4949 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 4950 R.styleable.View_fadingEdgeLength, 4951 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 4952 } 4953 4954 /** 4955 * Returns the size of the vertical faded edges used to indicate that more 4956 * content in this view is visible. 4957 * 4958 * @return The size in pixels of the vertical faded edge or 0 if vertical 4959 * faded edges are not enabled for this view. 4960 * @attr ref android.R.styleable#View_fadingEdgeLength 4961 */ getVerticalFadingEdgeLength()4962 public int getVerticalFadingEdgeLength() { 4963 if (isVerticalFadingEdgeEnabled()) { 4964 ScrollabilityCache cache = mScrollCache; 4965 if (cache != null) { 4966 return cache.fadingEdgeLength; 4967 } 4968 } 4969 return 0; 4970 } 4971 4972 /** 4973 * Set the size of the faded edge used to indicate that more content in this 4974 * view is available. Will not change whether the fading edge is enabled; use 4975 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 4976 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 4977 * for the vertical or horizontal fading edges. 4978 * 4979 * @param length The size in pixels of the faded edge used to indicate that more 4980 * content in this view is visible. 4981 */ setFadingEdgeLength(int length)4982 public void setFadingEdgeLength(int length) { 4983 initScrollCache(); 4984 mScrollCache.fadingEdgeLength = length; 4985 } 4986 4987 /** 4988 * Returns the size of the horizontal faded edges used to indicate that more 4989 * content in this view is visible. 4990 * 4991 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 4992 * faded edges are not enabled for this view. 4993 * @attr ref android.R.styleable#View_fadingEdgeLength 4994 */ getHorizontalFadingEdgeLength()4995 public int getHorizontalFadingEdgeLength() { 4996 if (isHorizontalFadingEdgeEnabled()) { 4997 ScrollabilityCache cache = mScrollCache; 4998 if (cache != null) { 4999 return cache.fadingEdgeLength; 5000 } 5001 } 5002 return 0; 5003 } 5004 5005 /** 5006 * Returns the width of the vertical scrollbar. 5007 * 5008 * @return The width in pixels of the vertical scrollbar or 0 if there 5009 * is no vertical scrollbar. 5010 */ getVerticalScrollbarWidth()5011 public int getVerticalScrollbarWidth() { 5012 ScrollabilityCache cache = mScrollCache; 5013 if (cache != null) { 5014 ScrollBarDrawable scrollBar = cache.scrollBar; 5015 if (scrollBar != null) { 5016 int size = scrollBar.getSize(true); 5017 if (size <= 0) { 5018 size = cache.scrollBarSize; 5019 } 5020 return size; 5021 } 5022 return 0; 5023 } 5024 return 0; 5025 } 5026 5027 /** 5028 * Returns the height of the horizontal scrollbar. 5029 * 5030 * @return The height in pixels of the horizontal scrollbar or 0 if 5031 * there is no horizontal scrollbar. 5032 */ getHorizontalScrollbarHeight()5033 protected int getHorizontalScrollbarHeight() { 5034 ScrollabilityCache cache = mScrollCache; 5035 if (cache != null) { 5036 ScrollBarDrawable scrollBar = cache.scrollBar; 5037 if (scrollBar != null) { 5038 int size = scrollBar.getSize(false); 5039 if (size <= 0) { 5040 size = cache.scrollBarSize; 5041 } 5042 return size; 5043 } 5044 return 0; 5045 } 5046 return 0; 5047 } 5048 5049 /** 5050 * <p> 5051 * Initializes the scrollbars from a given set of styled attributes. This 5052 * method should be called by subclasses that need scrollbars and when an 5053 * instance of these subclasses is created programmatically rather than 5054 * being inflated from XML. This method is automatically called when the XML 5055 * is inflated. 5056 * </p> 5057 * 5058 * @param a the styled attributes set to initialize the scrollbars from 5059 * 5060 * @removed 5061 */ initializeScrollbars(TypedArray a)5062 protected void initializeScrollbars(TypedArray a) { 5063 // It's not safe to use this method from apps. The parameter 'a' must have been obtained 5064 // using the View filter array which is not available to the SDK. As such, internal 5065 // framework usage now uses initializeScrollbarsInternal and we grab a default 5066 // TypedArray with the right filter instead here. 5067 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 5068 5069 initializeScrollbarsInternal(arr); 5070 5071 // We ignored the method parameter. Recycle the one we actually did use. 5072 arr.recycle(); 5073 } 5074 5075 /** 5076 * <p> 5077 * Initializes the scrollbars from a given set of styled attributes. This 5078 * method should be called by subclasses that need scrollbars and when an 5079 * instance of these subclasses is created programmatically rather than 5080 * being inflated from XML. This method is automatically called when the XML 5081 * is inflated. 5082 * </p> 5083 * 5084 * @param a the styled attributes set to initialize the scrollbars from 5085 * @hide 5086 */ initializeScrollbarsInternal(TypedArray a)5087 protected void initializeScrollbarsInternal(TypedArray a) { 5088 initScrollCache(); 5089 5090 final ScrollabilityCache scrollabilityCache = mScrollCache; 5091 5092 if (scrollabilityCache.scrollBar == null) { 5093 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 5094 scrollabilityCache.scrollBar.setState(getDrawableState()); 5095 scrollabilityCache.scrollBar.setCallback(this); 5096 } 5097 5098 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 5099 5100 if (!fadeScrollbars) { 5101 scrollabilityCache.state = ScrollabilityCache.ON; 5102 } 5103 scrollabilityCache.fadeScrollBars = fadeScrollbars; 5104 5105 5106 scrollabilityCache.scrollBarFadeDuration = a.getInt( 5107 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 5108 .getScrollBarFadeDuration()); 5109 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 5110 R.styleable.View_scrollbarDefaultDelayBeforeFade, 5111 ViewConfiguration.getScrollDefaultDelay()); 5112 5113 5114 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 5115 com.android.internal.R.styleable.View_scrollbarSize, 5116 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 5117 5118 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 5119 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 5120 5121 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 5122 if (thumb != null) { 5123 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 5124 } 5125 5126 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 5127 false); 5128 if (alwaysDraw) { 5129 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 5130 } 5131 5132 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 5133 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 5134 5135 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 5136 if (thumb != null) { 5137 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 5138 } 5139 5140 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 5141 false); 5142 if (alwaysDraw) { 5143 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 5144 } 5145 5146 // Apply layout direction to the new Drawables if needed 5147 final int layoutDirection = getLayoutDirection(); 5148 if (track != null) { 5149 track.setLayoutDirection(layoutDirection); 5150 } 5151 if (thumb != null) { 5152 thumb.setLayoutDirection(layoutDirection); 5153 } 5154 5155 // Re-apply user/background padding so that scrollbar(s) get added 5156 resolvePadding(); 5157 } 5158 initializeScrollIndicatorsInternal()5159 private void initializeScrollIndicatorsInternal() { 5160 // Some day maybe we'll break this into top/left/start/etc. and let the 5161 // client control it. Until then, you can have any scroll indicator you 5162 // want as long as it's a 1dp foreground-colored rectangle. 5163 if (mScrollIndicatorDrawable == null) { 5164 mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); 5165 } 5166 } 5167 5168 /** 5169 * <p> 5170 * Initalizes the scrollability cache if necessary. 5171 * </p> 5172 */ initScrollCache()5173 private void initScrollCache() { 5174 if (mScrollCache == null) { 5175 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 5176 } 5177 } 5178 getScrollCache()5179 private ScrollabilityCache getScrollCache() { 5180 initScrollCache(); 5181 return mScrollCache; 5182 } 5183 5184 /** 5185 * Set the position of the vertical scroll bar. Should be one of 5186 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 5187 * {@link #SCROLLBAR_POSITION_RIGHT}. 5188 * 5189 * @param position Where the vertical scroll bar should be positioned. 5190 */ setVerticalScrollbarPosition(int position)5191 public void setVerticalScrollbarPosition(int position) { 5192 if (mVerticalScrollbarPosition != position) { 5193 mVerticalScrollbarPosition = position; 5194 computeOpaqueFlags(); 5195 resolvePadding(); 5196 } 5197 } 5198 5199 /** 5200 * @return The position where the vertical scroll bar will show, if applicable. 5201 * @see #setVerticalScrollbarPosition(int) 5202 */ getVerticalScrollbarPosition()5203 public int getVerticalScrollbarPosition() { 5204 return mVerticalScrollbarPosition; 5205 } 5206 isOnScrollbar(float x, float y)5207 boolean isOnScrollbar(float x, float y) { 5208 if (mScrollCache == null) { 5209 return false; 5210 } 5211 x += getScrollX(); 5212 y += getScrollY(); 5213 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 5214 final Rect bounds = mScrollCache.mScrollBarBounds; 5215 getVerticalScrollBarBounds(bounds); 5216 if (bounds.contains((int)x, (int)y)) { 5217 return true; 5218 } 5219 } 5220 if (isHorizontalScrollBarEnabled()) { 5221 final Rect bounds = mScrollCache.mScrollBarBounds; 5222 getHorizontalScrollBarBounds(bounds); 5223 if (bounds.contains((int)x, (int)y)) { 5224 return true; 5225 } 5226 } 5227 return false; 5228 } 5229 isOnScrollbarThumb(float x, float y)5230 boolean isOnScrollbarThumb(float x, float y) { 5231 return isOnVerticalScrollbarThumb(x, y) || isOnHorizontalScrollbarThumb(x, y); 5232 } 5233 isOnVerticalScrollbarThumb(float x, float y)5234 private boolean isOnVerticalScrollbarThumb(float x, float y) { 5235 if (mScrollCache == null) { 5236 return false; 5237 } 5238 if (isVerticalScrollBarEnabled() && !isVerticalScrollBarHidden()) { 5239 x += getScrollX(); 5240 y += getScrollY(); 5241 final Rect bounds = mScrollCache.mScrollBarBounds; 5242 getVerticalScrollBarBounds(bounds); 5243 final int range = computeVerticalScrollRange(); 5244 final int offset = computeVerticalScrollOffset(); 5245 final int extent = computeVerticalScrollExtent(); 5246 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.height(), bounds.width(), 5247 extent, range); 5248 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.height(), thumbLength, 5249 extent, range, offset); 5250 final int thumbTop = bounds.top + thumbOffset; 5251 if (x >= bounds.left && x <= bounds.right && y >= thumbTop 5252 && y <= thumbTop + thumbLength) { 5253 return true; 5254 } 5255 } 5256 return false; 5257 } 5258 isOnHorizontalScrollbarThumb(float x, float y)5259 private boolean isOnHorizontalScrollbarThumb(float x, float y) { 5260 if (mScrollCache == null) { 5261 return false; 5262 } 5263 if (isHorizontalScrollBarEnabled()) { 5264 x += getScrollX(); 5265 y += getScrollY(); 5266 final Rect bounds = mScrollCache.mScrollBarBounds; 5267 getHorizontalScrollBarBounds(bounds); 5268 final int range = computeHorizontalScrollRange(); 5269 final int offset = computeHorizontalScrollOffset(); 5270 final int extent = computeHorizontalScrollExtent(); 5271 final int thumbLength = ScrollBarUtils.getThumbLength(bounds.width(), bounds.height(), 5272 extent, range); 5273 final int thumbOffset = ScrollBarUtils.getThumbOffset(bounds.width(), thumbLength, 5274 extent, range, offset); 5275 final int thumbLeft = bounds.left + thumbOffset; 5276 if (x >= thumbLeft && x <= thumbLeft + thumbLength && y >= bounds.top 5277 && y <= bounds.bottom) { 5278 return true; 5279 } 5280 } 5281 return false; 5282 } 5283 isDraggingScrollBar()5284 boolean isDraggingScrollBar() { 5285 return mScrollCache != null 5286 && mScrollCache.mScrollBarDraggingState != ScrollabilityCache.NOT_DRAGGING; 5287 } 5288 5289 /** 5290 * Sets the state of all scroll indicators. 5291 * <p> 5292 * See {@link #setScrollIndicators(int, int)} for usage information. 5293 * 5294 * @param indicators a bitmask of indicators that should be enabled, or 5295 * {@code 0} to disable all indicators 5296 * @see #setScrollIndicators(int, int) 5297 * @see #getScrollIndicators() 5298 * @attr ref android.R.styleable#View_scrollIndicators 5299 */ setScrollIndicators(@crollIndicators int indicators)5300 public void setScrollIndicators(@ScrollIndicators int indicators) { 5301 setScrollIndicators(indicators, 5302 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT); 5303 } 5304 5305 /** 5306 * Sets the state of the scroll indicators specified by the mask. To change 5307 * all scroll indicators at once, see {@link #setScrollIndicators(int)}. 5308 * <p> 5309 * When a scroll indicator is enabled, it will be displayed if the view 5310 * can scroll in the direction of the indicator. 5311 * <p> 5312 * Multiple indicator types may be enabled or disabled by passing the 5313 * logical OR of the desired types. If multiple types are specified, they 5314 * will all be set to the same enabled state. 5315 * <p> 5316 * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators 5317 * 5318 * @param indicators the indicator direction, or the logical OR of multiple 5319 * indicator directions. One or more of: 5320 * <ul> 5321 * <li>{@link #SCROLL_INDICATOR_TOP}</li> 5322 * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> 5323 * <li>{@link #SCROLL_INDICATOR_LEFT}</li> 5324 * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> 5325 * <li>{@link #SCROLL_INDICATOR_START}</li> 5326 * <li>{@link #SCROLL_INDICATOR_END}</li> 5327 * </ul> 5328 * @see #setScrollIndicators(int) 5329 * @see #getScrollIndicators() 5330 * @attr ref android.R.styleable#View_scrollIndicators 5331 */ setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)5332 public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { 5333 // Shift and sanitize mask. 5334 mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5335 mask &= SCROLL_INDICATORS_PFLAG3_MASK; 5336 5337 // Shift and mask indicators. 5338 indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5339 indicators &= mask; 5340 5341 // Merge with non-masked flags. 5342 final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); 5343 5344 if (mPrivateFlags3 != updatedFlags) { 5345 mPrivateFlags3 = updatedFlags; 5346 5347 if (indicators != 0) { 5348 initializeScrollIndicatorsInternal(); 5349 } 5350 invalidate(); 5351 } 5352 } 5353 5354 /** 5355 * Returns a bitmask representing the enabled scroll indicators. 5356 * <p> 5357 * For example, if the top and left scroll indicators are enabled and all 5358 * other indicators are disabled, the return value will be 5359 * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. 5360 * <p> 5361 * To check whether the bottom scroll indicator is enabled, use the value 5362 * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. 5363 * 5364 * @return a bitmask representing the enabled scroll indicators 5365 */ 5366 @ScrollIndicators getScrollIndicators()5367 public int getScrollIndicators() { 5368 return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) 5369 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5370 } 5371 getListenerInfo()5372 ListenerInfo getListenerInfo() { 5373 if (mListenerInfo != null) { 5374 return mListenerInfo; 5375 } 5376 mListenerInfo = new ListenerInfo(); 5377 return mListenerInfo; 5378 } 5379 5380 /** 5381 * Register a callback to be invoked when the scroll X or Y positions of 5382 * this view change. 5383 * <p> 5384 * <b>Note:</b> Some views handle scrolling independently from View and may 5385 * have their own separate listeners for scroll-type events. For example, 5386 * {@link android.widget.ListView ListView} allows clients to register an 5387 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 5388 * to listen for changes in list scroll position. 5389 * 5390 * @param l The listener to notify when the scroll X or Y position changes. 5391 * @see android.view.View#getScrollX() 5392 * @see android.view.View#getScrollY() 5393 */ setOnScrollChangeListener(OnScrollChangeListener l)5394 public void setOnScrollChangeListener(OnScrollChangeListener l) { 5395 getListenerInfo().mOnScrollChangeListener = l; 5396 } 5397 5398 /** 5399 * Register a callback to be invoked when focus of this view changed. 5400 * 5401 * @param l The callback that will run. 5402 */ setOnFocusChangeListener(OnFocusChangeListener l)5403 public void setOnFocusChangeListener(OnFocusChangeListener l) { 5404 getListenerInfo().mOnFocusChangeListener = l; 5405 } 5406 5407 /** 5408 * Add a listener that will be called when the bounds of the view change due to 5409 * layout processing. 5410 * 5411 * @param listener The listener that will be called when layout bounds change. 5412 */ addOnLayoutChangeListener(OnLayoutChangeListener listener)5413 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 5414 ListenerInfo li = getListenerInfo(); 5415 if (li.mOnLayoutChangeListeners == null) { 5416 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 5417 } 5418 if (!li.mOnLayoutChangeListeners.contains(listener)) { 5419 li.mOnLayoutChangeListeners.add(listener); 5420 } 5421 } 5422 5423 /** 5424 * Remove a listener for layout changes. 5425 * 5426 * @param listener The listener for layout bounds change. 5427 */ removeOnLayoutChangeListener(OnLayoutChangeListener listener)5428 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 5429 ListenerInfo li = mListenerInfo; 5430 if (li == null || li.mOnLayoutChangeListeners == null) { 5431 return; 5432 } 5433 li.mOnLayoutChangeListeners.remove(listener); 5434 } 5435 5436 /** 5437 * Add a listener for attach state changes. 5438 * 5439 * This listener will be called whenever this view is attached or detached 5440 * from a window. Remove the listener using 5441 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 5442 * 5443 * @param listener Listener to attach 5444 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 5445 */ addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5446 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5447 ListenerInfo li = getListenerInfo(); 5448 if (li.mOnAttachStateChangeListeners == null) { 5449 li.mOnAttachStateChangeListeners 5450 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 5451 } 5452 li.mOnAttachStateChangeListeners.add(listener); 5453 } 5454 5455 /** 5456 * Remove a listener for attach state changes. The listener will receive no further 5457 * notification of window attach/detach events. 5458 * 5459 * @param listener Listener to remove 5460 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 5461 */ removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5462 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5463 ListenerInfo li = mListenerInfo; 5464 if (li == null || li.mOnAttachStateChangeListeners == null) { 5465 return; 5466 } 5467 li.mOnAttachStateChangeListeners.remove(listener); 5468 } 5469 5470 /** 5471 * Returns the focus-change callback registered for this view. 5472 * 5473 * @return The callback, or null if one is not registered. 5474 */ getOnFocusChangeListener()5475 public OnFocusChangeListener getOnFocusChangeListener() { 5476 ListenerInfo li = mListenerInfo; 5477 return li != null ? li.mOnFocusChangeListener : null; 5478 } 5479 5480 /** 5481 * Register a callback to be invoked when this view is clicked. If this view is not 5482 * clickable, it becomes clickable. 5483 * 5484 * @param l The callback that will run 5485 * 5486 * @see #setClickable(boolean) 5487 */ setOnClickListener(@ullable OnClickListener l)5488 public void setOnClickListener(@Nullable OnClickListener l) { 5489 if (!isClickable()) { 5490 setClickable(true); 5491 } 5492 getListenerInfo().mOnClickListener = l; 5493 } 5494 5495 /** 5496 * Return whether this view has an attached OnClickListener. Returns 5497 * true if there is a listener, false if there is none. 5498 */ hasOnClickListeners()5499 public boolean hasOnClickListeners() { 5500 ListenerInfo li = mListenerInfo; 5501 return (li != null && li.mOnClickListener != null); 5502 } 5503 5504 /** 5505 * Register a callback to be invoked when this view is clicked and held. If this view is not 5506 * long clickable, it becomes long clickable. 5507 * 5508 * @param l The callback that will run 5509 * 5510 * @see #setLongClickable(boolean) 5511 */ setOnLongClickListener(@ullable OnLongClickListener l)5512 public void setOnLongClickListener(@Nullable OnLongClickListener l) { 5513 if (!isLongClickable()) { 5514 setLongClickable(true); 5515 } 5516 getListenerInfo().mOnLongClickListener = l; 5517 } 5518 5519 /** 5520 * Register a callback to be invoked when this view is context clicked. If the view is not 5521 * context clickable, it becomes context clickable. 5522 * 5523 * @param l The callback that will run 5524 * @see #setContextClickable(boolean) 5525 */ setOnContextClickListener(@ullable OnContextClickListener l)5526 public void setOnContextClickListener(@Nullable OnContextClickListener l) { 5527 if (!isContextClickable()) { 5528 setContextClickable(true); 5529 } 5530 getListenerInfo().mOnContextClickListener = l; 5531 } 5532 5533 /** 5534 * Register a callback to be invoked when the context menu for this view is 5535 * being built. If this view is not long clickable, it becomes long clickable. 5536 * 5537 * @param l The callback that will run 5538 * 5539 */ setOnCreateContextMenuListener(OnCreateContextMenuListener l)5540 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 5541 if (!isLongClickable()) { 5542 setLongClickable(true); 5543 } 5544 getListenerInfo().mOnCreateContextMenuListener = l; 5545 } 5546 5547 /** 5548 * Set an observer to collect stats for each frame rendered for this view. 5549 * 5550 * @hide 5551 */ addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler)5552 public void addFrameMetricsListener(Window window, 5553 Window.OnFrameMetricsAvailableListener listener, 5554 Handler handler) { 5555 if (mAttachInfo != null) { 5556 if (mAttachInfo.mHardwareRenderer != null) { 5557 if (mFrameMetricsObservers == null) { 5558 mFrameMetricsObservers = new ArrayList<>(); 5559 } 5560 5561 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 5562 handler.getLooper(), listener); 5563 mFrameMetricsObservers.add(fmo); 5564 mAttachInfo.mHardwareRenderer.addFrameMetricsObserver(fmo); 5565 } else { 5566 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 5567 } 5568 } else { 5569 if (mFrameMetricsObservers == null) { 5570 mFrameMetricsObservers = new ArrayList<>(); 5571 } 5572 5573 FrameMetricsObserver fmo = new FrameMetricsObserver(window, 5574 handler.getLooper(), listener); 5575 mFrameMetricsObservers.add(fmo); 5576 } 5577 } 5578 5579 /** 5580 * Remove observer configured to collect frame stats for this view. 5581 * 5582 * @hide 5583 */ removeFrameMetricsListener( Window.OnFrameMetricsAvailableListener listener)5584 public void removeFrameMetricsListener( 5585 Window.OnFrameMetricsAvailableListener listener) { 5586 ThreadedRenderer renderer = getHardwareRenderer(); 5587 FrameMetricsObserver fmo = findFrameMetricsObserver(listener); 5588 if (fmo == null) { 5589 throw new IllegalArgumentException( 5590 "attempt to remove OnFrameMetricsAvailableListener that was never added"); 5591 } 5592 5593 if (mFrameMetricsObservers != null) { 5594 mFrameMetricsObservers.remove(fmo); 5595 if (renderer != null) { 5596 renderer.removeFrameMetricsObserver(fmo); 5597 } 5598 } 5599 } 5600 registerPendingFrameMetricsObservers()5601 private void registerPendingFrameMetricsObservers() { 5602 if (mFrameMetricsObservers != null) { 5603 ThreadedRenderer renderer = getHardwareRenderer(); 5604 if (renderer != null) { 5605 for (FrameMetricsObserver fmo : mFrameMetricsObservers) { 5606 renderer.addFrameMetricsObserver(fmo); 5607 } 5608 } else { 5609 Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); 5610 } 5611 } 5612 } 5613 findFrameMetricsObserver( Window.OnFrameMetricsAvailableListener listener)5614 private FrameMetricsObserver findFrameMetricsObserver( 5615 Window.OnFrameMetricsAvailableListener listener) { 5616 for (int i = 0; i < mFrameMetricsObservers.size(); i++) { 5617 FrameMetricsObserver observer = mFrameMetricsObservers.get(i); 5618 if (observer.mListener == listener) { 5619 return observer; 5620 } 5621 } 5622 5623 return null; 5624 } 5625 5626 /** 5627 * Call this view's OnClickListener, if it is defined. Performs all normal 5628 * actions associated with clicking: reporting accessibility event, playing 5629 * a sound, etc. 5630 * 5631 * @return True there was an assigned OnClickListener that was called, false 5632 * otherwise is returned. 5633 */ performClick()5634 public boolean performClick() { 5635 final boolean result; 5636 final ListenerInfo li = mListenerInfo; 5637 if (li != null && li.mOnClickListener != null) { 5638 playSoundEffect(SoundEffectConstants.CLICK); 5639 li.mOnClickListener.onClick(this); 5640 result = true; 5641 } else { 5642 result = false; 5643 } 5644 5645 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 5646 return result; 5647 } 5648 5649 /** 5650 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 5651 * this only calls the listener, and does not do any associated clicking 5652 * actions like reporting an accessibility event. 5653 * 5654 * @return True there was an assigned OnClickListener that was called, false 5655 * otherwise is returned. 5656 */ callOnClick()5657 public boolean callOnClick() { 5658 ListenerInfo li = mListenerInfo; 5659 if (li != null && li.mOnClickListener != null) { 5660 li.mOnClickListener.onClick(this); 5661 return true; 5662 } 5663 return false; 5664 } 5665 5666 /** 5667 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5668 * context menu if the OnLongClickListener did not consume the event. 5669 * 5670 * @return {@code true} if one of the above receivers consumed the event, 5671 * {@code false} otherwise 5672 */ performLongClick()5673 public boolean performLongClick() { 5674 return performLongClickInternal(mLongClickX, mLongClickY); 5675 } 5676 5677 /** 5678 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5679 * context menu if the OnLongClickListener did not consume the event, 5680 * anchoring it to an (x,y) coordinate. 5681 * 5682 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5683 * to disable anchoring 5684 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5685 * to disable anchoring 5686 * @return {@code true} if one of the above receivers consumed the event, 5687 * {@code false} otherwise 5688 */ performLongClick(float x, float y)5689 public boolean performLongClick(float x, float y) { 5690 mLongClickX = x; 5691 mLongClickY = y; 5692 final boolean handled = performLongClick(); 5693 mLongClickX = Float.NaN; 5694 mLongClickY = Float.NaN; 5695 return handled; 5696 } 5697 5698 /** 5699 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5700 * context menu if the OnLongClickListener did not consume the event, 5701 * optionally anchoring it to an (x,y) coordinate. 5702 * 5703 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5704 * to disable anchoring 5705 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5706 * to disable anchoring 5707 * @return {@code true} if one of the above receivers consumed the event, 5708 * {@code false} otherwise 5709 */ performLongClickInternal(float x, float y)5710 private boolean performLongClickInternal(float x, float y) { 5711 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 5712 5713 boolean handled = false; 5714 final ListenerInfo li = mListenerInfo; 5715 if (li != null && li.mOnLongClickListener != null) { 5716 handled = li.mOnLongClickListener.onLongClick(View.this); 5717 } 5718 if (!handled) { 5719 final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y); 5720 handled = isAnchored ? showContextMenu(x, y) : showContextMenu(); 5721 } 5722 if (handled) { 5723 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 5724 } 5725 return handled; 5726 } 5727 5728 /** 5729 * Call this view's OnContextClickListener, if it is defined. 5730 * 5731 * @param x the x coordinate of the context click 5732 * @param y the y coordinate of the context click 5733 * @return True if there was an assigned OnContextClickListener that consumed the event, false 5734 * otherwise. 5735 */ performContextClick(float x, float y)5736 public boolean performContextClick(float x, float y) { 5737 return performContextClick(); 5738 } 5739 5740 /** 5741 * Call this view's OnContextClickListener, if it is defined. 5742 * 5743 * @return True if there was an assigned OnContextClickListener that consumed the event, false 5744 * otherwise. 5745 */ performContextClick()5746 public boolean performContextClick() { 5747 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED); 5748 5749 boolean handled = false; 5750 ListenerInfo li = mListenerInfo; 5751 if (li != null && li.mOnContextClickListener != null) { 5752 handled = li.mOnContextClickListener.onContextClick(View.this); 5753 } 5754 if (handled) { 5755 performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK); 5756 } 5757 return handled; 5758 } 5759 5760 /** 5761 * Performs button-related actions during a touch down event. 5762 * 5763 * @param event The event. 5764 * @return True if the down was consumed. 5765 * 5766 * @hide 5767 */ performButtonActionOnTouchDown(MotionEvent event)5768 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 5769 if (event.isFromSource(InputDevice.SOURCE_MOUSE) && 5770 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 5771 showContextMenu(event.getX(), event.getY()); 5772 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 5773 return true; 5774 } 5775 return false; 5776 } 5777 5778 /** 5779 * Shows the context menu for this view. 5780 * 5781 * @return {@code true} if the context menu was shown, {@code false} 5782 * otherwise 5783 * @see #showContextMenu(float, float) 5784 */ showContextMenu()5785 public boolean showContextMenu() { 5786 return getParent().showContextMenuForChild(this); 5787 } 5788 5789 /** 5790 * Shows the context menu for this view anchored to the specified 5791 * view-relative coordinate. 5792 * 5793 * @param x the X coordinate in pixels relative to the view to which the 5794 * menu should be anchored, or {@link Float#NaN} to disable anchoring 5795 * @param y the Y coordinate in pixels relative to the view to which the 5796 * menu should be anchored, or {@link Float#NaN} to disable anchoring 5797 * @return {@code true} if the context menu was shown, {@code false} 5798 * otherwise 5799 */ showContextMenu(float x, float y)5800 public boolean showContextMenu(float x, float y) { 5801 return getParent().showContextMenuForChild(this, x, y); 5802 } 5803 5804 /** 5805 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}. 5806 * 5807 * @param callback Callback that will control the lifecycle of the action mode 5808 * @return The new action mode if it is started, null otherwise 5809 * 5810 * @see ActionMode 5811 * @see #startActionMode(android.view.ActionMode.Callback, int) 5812 */ startActionMode(ActionMode.Callback callback)5813 public ActionMode startActionMode(ActionMode.Callback callback) { 5814 return startActionMode(callback, ActionMode.TYPE_PRIMARY); 5815 } 5816 5817 /** 5818 * Start an action mode with the given type. 5819 * 5820 * @param callback Callback that will control the lifecycle of the action mode 5821 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}. 5822 * @return The new action mode if it is started, null otherwise 5823 * 5824 * @see ActionMode 5825 */ startActionMode(ActionMode.Callback callback, int type)5826 public ActionMode startActionMode(ActionMode.Callback callback, int type) { 5827 ViewParent parent = getParent(); 5828 if (parent == null) return null; 5829 try { 5830 return parent.startActionModeForChild(this, callback, type); 5831 } catch (AbstractMethodError ame) { 5832 // Older implementations of custom views might not implement this. 5833 return parent.startActionModeForChild(this, callback); 5834 } 5835 } 5836 5837 /** 5838 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's 5839 * Context, creating a unique View identifier to retrieve the result. 5840 * 5841 * @param intent The Intent to be started. 5842 * @param requestCode The request code to use. 5843 * @hide 5844 */ startActivityForResult(Intent intent, int requestCode)5845 public void startActivityForResult(Intent intent, int requestCode) { 5846 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this); 5847 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null); 5848 } 5849 5850 /** 5851 * If this View corresponds to the calling who, dispatches the activity result. 5852 * @param who The identifier for the targeted View to receive the result. 5853 * @param requestCode The integer request code originally supplied to 5854 * startActivityForResult(), allowing you to identify who this 5855 * result came from. 5856 * @param resultCode The integer result code returned by the child activity 5857 * through its setResult(). 5858 * @param data An Intent, which can return result data to the caller 5859 * (various data can be attached to Intent "extras"). 5860 * @return {@code true} if the activity result was dispatched. 5861 * @hide 5862 */ dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5863 public boolean dispatchActivityResult( 5864 String who, int requestCode, int resultCode, Intent data) { 5865 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) { 5866 onActivityResult(requestCode, resultCode, data); 5867 mStartActivityRequestWho = null; 5868 return true; 5869 } 5870 return false; 5871 } 5872 5873 /** 5874 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. 5875 * 5876 * @param requestCode The integer request code originally supplied to 5877 * startActivityForResult(), allowing you to identify who this 5878 * result came from. 5879 * @param resultCode The integer result code returned by the child activity 5880 * through its setResult(). 5881 * @param data An Intent, which can return result data to the caller 5882 * (various data can be attached to Intent "extras"). 5883 * @hide 5884 */ onActivityResult(int requestCode, int resultCode, Intent data)5885 public void onActivityResult(int requestCode, int resultCode, Intent data) { 5886 // Do nothing. 5887 } 5888 5889 /** 5890 * Register a callback to be invoked when a hardware key is pressed in this view. 5891 * Key presses in software input methods will generally not trigger the methods of 5892 * this listener. 5893 * @param l the key listener to attach to this view 5894 */ setOnKeyListener(OnKeyListener l)5895 public void setOnKeyListener(OnKeyListener l) { 5896 getListenerInfo().mOnKeyListener = l; 5897 } 5898 5899 /** 5900 * Register a callback to be invoked when a touch event is sent to this view. 5901 * @param l the touch listener to attach to this view 5902 */ setOnTouchListener(OnTouchListener l)5903 public void setOnTouchListener(OnTouchListener l) { 5904 getListenerInfo().mOnTouchListener = l; 5905 } 5906 5907 /** 5908 * Register a callback to be invoked when a generic motion event is sent to this view. 5909 * @param l the generic motion listener to attach to this view 5910 */ setOnGenericMotionListener(OnGenericMotionListener l)5911 public void setOnGenericMotionListener(OnGenericMotionListener l) { 5912 getListenerInfo().mOnGenericMotionListener = l; 5913 } 5914 5915 /** 5916 * Register a callback to be invoked when a hover event is sent to this view. 5917 * @param l the hover listener to attach to this view 5918 */ setOnHoverListener(OnHoverListener l)5919 public void setOnHoverListener(OnHoverListener l) { 5920 getListenerInfo().mOnHoverListener = l; 5921 } 5922 5923 /** 5924 * Register a drag event listener callback object for this View. The parameter is 5925 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 5926 * View, the system calls the 5927 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 5928 * @param l An implementation of {@link android.view.View.OnDragListener}. 5929 */ setOnDragListener(OnDragListener l)5930 public void setOnDragListener(OnDragListener l) { 5931 getListenerInfo().mOnDragListener = l; 5932 } 5933 5934 /** 5935 * Give this view focus. This will cause 5936 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 5937 * 5938 * Note: this does not check whether this {@link View} should get focus, it just 5939 * gives it focus no matter what. It should only be called internally by framework 5940 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 5941 * 5942 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 5943 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 5944 * focus moved when requestFocus() is called. It may not always 5945 * apply, in which case use the default View.FOCUS_DOWN. 5946 * @param previouslyFocusedRect The rectangle of the view that had focus 5947 * prior in this View's coordinate system. 5948 */ handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5949 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) { 5950 if (DBG) { 5951 System.out.println(this + " requestFocus()"); 5952 } 5953 5954 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 5955 mPrivateFlags |= PFLAG_FOCUSED; 5956 5957 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 5958 5959 if (mParent != null) { 5960 mParent.requestChildFocus(this, this); 5961 } 5962 5963 if (mAttachInfo != null) { 5964 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 5965 } 5966 5967 onFocusChanged(true, direction, previouslyFocusedRect); 5968 refreshDrawableState(); 5969 } 5970 } 5971 5972 /** 5973 * Sets this view's preference for reveal behavior when it gains focus. 5974 * 5975 * <p>When set to true, this is a signal to ancestor views in the hierarchy that 5976 * this view would prefer to be brought fully into view when it gains focus. 5977 * For example, a text field that a user is meant to type into. Other views such 5978 * as scrolling containers may prefer to opt-out of this behavior.</p> 5979 * 5980 * <p>The default value for views is true, though subclasses may change this 5981 * based on their preferred behavior.</p> 5982 * 5983 * @param revealOnFocus true to request reveal on focus in ancestors, false otherwise 5984 * 5985 * @see #getRevealOnFocusHint() 5986 */ setRevealOnFocusHint(boolean revealOnFocus)5987 public final void setRevealOnFocusHint(boolean revealOnFocus) { 5988 if (revealOnFocus) { 5989 mPrivateFlags3 &= ~PFLAG3_NO_REVEAL_ON_FOCUS; 5990 } else { 5991 mPrivateFlags3 |= PFLAG3_NO_REVEAL_ON_FOCUS; 5992 } 5993 } 5994 5995 /** 5996 * Returns this view's preference for reveal behavior when it gains focus. 5997 * 5998 * <p>When this method returns true for a child view requesting focus, ancestor 5999 * views responding to a focus change in {@link ViewParent#requestChildFocus(View, View)} 6000 * should make a best effort to make the newly focused child fully visible to the user. 6001 * When it returns false, ancestor views should preferably not disrupt scroll positioning or 6002 * other properties affecting visibility to the user as part of the focus change.</p> 6003 * 6004 * @return true if this view would prefer to become fully visible when it gains focus, 6005 * false if it would prefer not to disrupt scroll positioning 6006 * 6007 * @see #setRevealOnFocusHint(boolean) 6008 */ getRevealOnFocusHint()6009 public final boolean getRevealOnFocusHint() { 6010 return (mPrivateFlags3 & PFLAG3_NO_REVEAL_ON_FOCUS) == 0; 6011 } 6012 6013 /** 6014 * Populates <code>outRect</code> with the hotspot bounds. By default, 6015 * the hotspot bounds are identical to the screen bounds. 6016 * 6017 * @param outRect rect to populate with hotspot bounds 6018 * @hide Only for internal use by views and widgets. 6019 */ getHotspotBounds(Rect outRect)6020 public void getHotspotBounds(Rect outRect) { 6021 final Drawable background = getBackground(); 6022 if (background != null) { 6023 background.getHotspotBounds(outRect); 6024 } else { 6025 getBoundsOnScreen(outRect); 6026 } 6027 } 6028 6029 /** 6030 * Request that a rectangle of this view be visible on the screen, 6031 * scrolling if necessary just enough. 6032 * 6033 * <p>A View should call this if it maintains some notion of which part 6034 * of its content is interesting. For example, a text editing view 6035 * should call this when its cursor moves. 6036 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 6037 * It should not be affected by which part of the View is currently visible or its scroll 6038 * position. 6039 * 6040 * @param rectangle The rectangle in the View's content coordinate space 6041 * @return Whether any parent scrolled. 6042 */ requestRectangleOnScreen(Rect rectangle)6043 public boolean requestRectangleOnScreen(Rect rectangle) { 6044 return requestRectangleOnScreen(rectangle, false); 6045 } 6046 6047 /** 6048 * Request that a rectangle of this view be visible on the screen, 6049 * scrolling if necessary just enough. 6050 * 6051 * <p>A View should call this if it maintains some notion of which part 6052 * of its content is interesting. For example, a text editing view 6053 * should call this when its cursor moves. 6054 * <p>The Rectangle passed into this method should be in the View's content coordinate space. 6055 * It should not be affected by which part of the View is currently visible or its scroll 6056 * position. 6057 * <p>When <code>immediate</code> is set to true, scrolling will not be 6058 * animated. 6059 * 6060 * @param rectangle The rectangle in the View's content coordinate space 6061 * @param immediate True to forbid animated scrolling, false otherwise 6062 * @return Whether any parent scrolled. 6063 */ requestRectangleOnScreen(Rect rectangle, boolean immediate)6064 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 6065 if (mParent == null) { 6066 return false; 6067 } 6068 6069 View child = this; 6070 6071 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 6072 position.set(rectangle); 6073 6074 ViewParent parent = mParent; 6075 boolean scrolled = false; 6076 while (parent != null) { 6077 rectangle.set((int) position.left, (int) position.top, 6078 (int) position.right, (int) position.bottom); 6079 6080 scrolled |= parent.requestChildRectangleOnScreen(child, rectangle, immediate); 6081 6082 if (!(parent instanceof View)) { 6083 break; 6084 } 6085 6086 // move it from child's content coordinate space to parent's content coordinate space 6087 position.offset(child.mLeft - child.getScrollX(), child.mTop -child.getScrollY()); 6088 6089 child = (View) parent; 6090 parent = child.getParent(); 6091 } 6092 6093 return scrolled; 6094 } 6095 6096 /** 6097 * Called when this view wants to give up focus. If focus is cleared 6098 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 6099 * <p> 6100 * <strong>Note:</strong> When a View clears focus the framework is trying 6101 * to give focus to the first focusable View from the top. Hence, if this 6102 * View is the first from the top that can take focus, then all callbacks 6103 * related to clearing focus will be invoked after which the framework will 6104 * give focus to this view. 6105 * </p> 6106 */ clearFocus()6107 public void clearFocus() { 6108 if (DBG) { 6109 System.out.println(this + " clearFocus()"); 6110 } 6111 6112 clearFocusInternal(null, true, true); 6113 } 6114 6115 /** 6116 * Clears focus from the view, optionally propagating the change up through 6117 * the parent hierarchy and requesting that the root view place new focus. 6118 * 6119 * @param propagate whether to propagate the change up through the parent 6120 * hierarchy 6121 * @param refocus when propagate is true, specifies whether to request the 6122 * root view place new focus 6123 */ clearFocusInternal(View focused, boolean propagate, boolean refocus)6124 void clearFocusInternal(View focused, boolean propagate, boolean refocus) { 6125 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 6126 mPrivateFlags &= ~PFLAG_FOCUSED; 6127 6128 if (propagate && mParent != null) { 6129 mParent.clearChildFocus(this); 6130 } 6131 6132 onFocusChanged(false, 0, null); 6133 refreshDrawableState(); 6134 6135 if (propagate && (!refocus || !rootViewRequestFocus())) { 6136 notifyGlobalFocusCleared(this); 6137 } 6138 } 6139 } 6140 notifyGlobalFocusCleared(View oldFocus)6141 void notifyGlobalFocusCleared(View oldFocus) { 6142 if (oldFocus != null && mAttachInfo != null) { 6143 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 6144 } 6145 } 6146 rootViewRequestFocus()6147 boolean rootViewRequestFocus() { 6148 final View root = getRootView(); 6149 return root != null && root.requestFocus(); 6150 } 6151 6152 /** 6153 * Called internally by the view system when a new view is getting focus. 6154 * This is what clears the old focus. 6155 * <p> 6156 * <b>NOTE:</b> The parent view's focused child must be updated manually 6157 * after calling this method. Otherwise, the view hierarchy may be left in 6158 * an inconstent state. 6159 */ unFocus(View focused)6160 void unFocus(View focused) { 6161 if (DBG) { 6162 System.out.println(this + " unFocus()"); 6163 } 6164 6165 clearFocusInternal(focused, false, false); 6166 } 6167 6168 /** 6169 * Returns true if this view has focus itself, or is the ancestor of the 6170 * view that has focus. 6171 * 6172 * @return True if this view has or contains focus, false otherwise. 6173 */ 6174 @ViewDebug.ExportedProperty(category = "focus") hasFocus()6175 public boolean hasFocus() { 6176 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 6177 } 6178 6179 /** 6180 * Returns true if this view is focusable or if it contains a reachable View 6181 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 6182 * is a View whose parents do not block descendants focus. 6183 * 6184 * Only {@link #VISIBLE} views are considered focusable. 6185 * 6186 * @return True if the view is focusable or if the view contains a focusable 6187 * View, false otherwise. 6188 * 6189 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 6190 * @see ViewGroup#getTouchscreenBlocksFocus() 6191 */ hasFocusable()6192 public boolean hasFocusable() { 6193 if (!isFocusableInTouchMode()) { 6194 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) { 6195 final ViewGroup g = (ViewGroup) p; 6196 if (g.shouldBlockFocusForTouchscreen()) { 6197 return false; 6198 } 6199 } 6200 } 6201 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 6202 } 6203 6204 /** 6205 * Called by the view system when the focus state of this view changes. 6206 * When the focus change event is caused by directional navigation, direction 6207 * and previouslyFocusedRect provide insight into where the focus is coming from. 6208 * When overriding, be sure to call up through to the super class so that 6209 * the standard focus handling will occur. 6210 * 6211 * @param gainFocus True if the View has focus; false otherwise. 6212 * @param direction The direction focus has moved when requestFocus() 6213 * is called to give this view focus. Values are 6214 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 6215 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 6216 * It may not always apply, in which case use the default. 6217 * @param previouslyFocusedRect The rectangle, in this view's coordinate 6218 * system, of the previously focused view. If applicable, this will be 6219 * passed in as finer grained information about where the focus is coming 6220 * from (in addition to direction). Will be <code>null</code> otherwise. 6221 */ 6222 @CallSuper onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)6223 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, 6224 @Nullable Rect previouslyFocusedRect) { 6225 if (gainFocus) { 6226 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 6227 } else { 6228 notifyViewAccessibilityStateChangedIfNeeded( 6229 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 6230 } 6231 6232 InputMethodManager imm = InputMethodManager.peekInstance(); 6233 if (!gainFocus) { 6234 if (isPressed()) { 6235 setPressed(false); 6236 } 6237 if (imm != null && mAttachInfo != null 6238 && mAttachInfo.mHasWindowFocus) { 6239 imm.focusOut(this); 6240 } 6241 onFocusLost(); 6242 } else if (imm != null && mAttachInfo != null 6243 && mAttachInfo.mHasWindowFocus) { 6244 imm.focusIn(this); 6245 } 6246 6247 invalidate(true); 6248 ListenerInfo li = mListenerInfo; 6249 if (li != null && li.mOnFocusChangeListener != null) { 6250 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 6251 } 6252 6253 if (mAttachInfo != null) { 6254 mAttachInfo.mKeyDispatchState.reset(this); 6255 } 6256 } 6257 6258 /** 6259 * Sends an accessibility event of the given type. If accessibility is 6260 * not enabled this method has no effect. The default implementation calls 6261 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 6262 * to populate information about the event source (this View), then calls 6263 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 6264 * populate the text content of the event source including its descendants, 6265 * and last calls 6266 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 6267 * on its parent to request sending of the event to interested parties. 6268 * <p> 6269 * If an {@link AccessibilityDelegate} has been specified via calling 6270 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6271 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 6272 * responsible for handling this call. 6273 * </p> 6274 * 6275 * @param eventType The type of the event to send, as defined by several types from 6276 * {@link android.view.accessibility.AccessibilityEvent}, such as 6277 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 6278 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 6279 * 6280 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 6281 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6282 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 6283 * @see AccessibilityDelegate 6284 */ sendAccessibilityEvent(int eventType)6285 public void sendAccessibilityEvent(int eventType) { 6286 if (mAccessibilityDelegate != null) { 6287 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 6288 } else { 6289 sendAccessibilityEventInternal(eventType); 6290 } 6291 } 6292 6293 /** 6294 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 6295 * {@link AccessibilityEvent} to make an announcement which is related to some 6296 * sort of a context change for which none of the events representing UI transitions 6297 * is a good fit. For example, announcing a new page in a book. If accessibility 6298 * is not enabled this method does nothing. 6299 * 6300 * @param text The announcement text. 6301 */ announceForAccessibility(CharSequence text)6302 public void announceForAccessibility(CharSequence text) { 6303 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 6304 AccessibilityEvent event = AccessibilityEvent.obtain( 6305 AccessibilityEvent.TYPE_ANNOUNCEMENT); 6306 onInitializeAccessibilityEvent(event); 6307 event.getText().add(text); 6308 event.setContentDescription(null); 6309 mParent.requestSendAccessibilityEvent(this, event); 6310 } 6311 } 6312 6313 /** 6314 * @see #sendAccessibilityEvent(int) 6315 * 6316 * Note: Called from the default {@link AccessibilityDelegate}. 6317 * 6318 * @hide 6319 */ sendAccessibilityEventInternal(int eventType)6320 public void sendAccessibilityEventInternal(int eventType) { 6321 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 6322 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 6323 } 6324 } 6325 6326 /** 6327 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 6328 * takes as an argument an empty {@link AccessibilityEvent} and does not 6329 * perform a check whether accessibility is enabled. 6330 * <p> 6331 * If an {@link AccessibilityDelegate} has been specified via calling 6332 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6333 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 6334 * is responsible for handling this call. 6335 * </p> 6336 * 6337 * @param event The event to send. 6338 * 6339 * @see #sendAccessibilityEvent(int) 6340 */ sendAccessibilityEventUnchecked(AccessibilityEvent event)6341 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 6342 if (mAccessibilityDelegate != null) { 6343 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 6344 } else { 6345 sendAccessibilityEventUncheckedInternal(event); 6346 } 6347 } 6348 6349 /** 6350 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 6351 * 6352 * Note: Called from the default {@link AccessibilityDelegate}. 6353 * 6354 * @hide 6355 */ sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)6356 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 6357 if (!isShown()) { 6358 return; 6359 } 6360 onInitializeAccessibilityEvent(event); 6361 // Only a subset of accessibility events populates text content. 6362 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 6363 dispatchPopulateAccessibilityEvent(event); 6364 } 6365 // In the beginning we called #isShown(), so we know that getParent() is not null. 6366 getParent().requestSendAccessibilityEvent(this, event); 6367 } 6368 6369 /** 6370 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 6371 * to its children for adding their text content to the event. Note that the 6372 * event text is populated in a separate dispatch path since we add to the 6373 * event not only the text of the source but also the text of all its descendants. 6374 * A typical implementation will call 6375 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 6376 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6377 * on each child. Override this method if custom population of the event text 6378 * content is required. 6379 * <p> 6380 * If an {@link AccessibilityDelegate} has been specified via calling 6381 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6382 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 6383 * is responsible for handling this call. 6384 * </p> 6385 * <p> 6386 * <em>Note:</em> Accessibility events of certain types are not dispatched for 6387 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 6388 * </p> 6389 * 6390 * @param event The event. 6391 * 6392 * @return True if the event population was completed. 6393 */ dispatchPopulateAccessibilityEvent(AccessibilityEvent event)6394 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 6395 if (mAccessibilityDelegate != null) { 6396 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 6397 } else { 6398 return dispatchPopulateAccessibilityEventInternal(event); 6399 } 6400 } 6401 6402 /** 6403 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6404 * 6405 * Note: Called from the default {@link AccessibilityDelegate}. 6406 * 6407 * @hide 6408 */ dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)6409 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6410 onPopulateAccessibilityEvent(event); 6411 return false; 6412 } 6413 6414 /** 6415 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6416 * giving a chance to this View to populate the accessibility event with its 6417 * text content. While this method is free to modify event 6418 * attributes other than text content, doing so should normally be performed in 6419 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 6420 * <p> 6421 * Example: Adding formatted date string to an accessibility event in addition 6422 * to the text added by the super implementation: 6423 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6424 * super.onPopulateAccessibilityEvent(event); 6425 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 6426 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 6427 * mCurrentDate.getTimeInMillis(), flags); 6428 * event.getText().add(selectedDateUtterance); 6429 * }</pre> 6430 * <p> 6431 * If an {@link AccessibilityDelegate} has been specified via calling 6432 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6433 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 6434 * is responsible for handling this call. 6435 * </p> 6436 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6437 * information to the event, in case the default implementation has basic information to add. 6438 * </p> 6439 * 6440 * @param event The accessibility event which to populate. 6441 * 6442 * @see #sendAccessibilityEvent(int) 6443 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6444 */ 6445 @CallSuper onPopulateAccessibilityEvent(AccessibilityEvent event)6446 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6447 if (mAccessibilityDelegate != null) { 6448 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 6449 } else { 6450 onPopulateAccessibilityEventInternal(event); 6451 } 6452 } 6453 6454 /** 6455 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 6456 * 6457 * Note: Called from the default {@link AccessibilityDelegate}. 6458 * 6459 * @hide 6460 */ onPopulateAccessibilityEventInternal(AccessibilityEvent event)6461 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6462 } 6463 6464 /** 6465 * Initializes an {@link AccessibilityEvent} with information about 6466 * this View which is the event source. In other words, the source of 6467 * an accessibility event is the view whose state change triggered firing 6468 * the event. 6469 * <p> 6470 * Example: Setting the password property of an event in addition 6471 * to properties set by the super implementation: 6472 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6473 * super.onInitializeAccessibilityEvent(event); 6474 * event.setPassword(true); 6475 * }</pre> 6476 * <p> 6477 * If an {@link AccessibilityDelegate} has been specified via calling 6478 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6479 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 6480 * is responsible for handling this call. 6481 * </p> 6482 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6483 * information to the event, in case the default implementation has basic information to add. 6484 * </p> 6485 * @param event The event to initialize. 6486 * 6487 * @see #sendAccessibilityEvent(int) 6488 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6489 */ 6490 @CallSuper onInitializeAccessibilityEvent(AccessibilityEvent event)6491 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6492 if (mAccessibilityDelegate != null) { 6493 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 6494 } else { 6495 onInitializeAccessibilityEventInternal(event); 6496 } 6497 } 6498 6499 /** 6500 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 6501 * 6502 * Note: Called from the default {@link AccessibilityDelegate}. 6503 * 6504 * @hide 6505 */ onInitializeAccessibilityEventInternal(AccessibilityEvent event)6506 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 6507 event.setSource(this); 6508 event.setClassName(getAccessibilityClassName()); 6509 event.setPackageName(getContext().getPackageName()); 6510 event.setEnabled(isEnabled()); 6511 event.setContentDescription(mContentDescription); 6512 6513 switch (event.getEventType()) { 6514 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 6515 ArrayList<View> focusablesTempList = (mAttachInfo != null) 6516 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 6517 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 6518 event.setItemCount(focusablesTempList.size()); 6519 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 6520 if (mAttachInfo != null) { 6521 focusablesTempList.clear(); 6522 } 6523 } break; 6524 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 6525 CharSequence text = getIterableTextForAccessibility(); 6526 if (text != null && text.length() > 0) { 6527 event.setFromIndex(getAccessibilitySelectionStart()); 6528 event.setToIndex(getAccessibilitySelectionEnd()); 6529 event.setItemCount(text.length()); 6530 } 6531 } break; 6532 } 6533 } 6534 6535 /** 6536 * Returns an {@link AccessibilityNodeInfo} representing this view from the 6537 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 6538 * This method is responsible for obtaining an accessibility node info from a 6539 * pool of reusable instances and calling 6540 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 6541 * initialize the former. 6542 * <p> 6543 * Note: The client is responsible for recycling the obtained instance by calling 6544 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 6545 * </p> 6546 * 6547 * @return A populated {@link AccessibilityNodeInfo}. 6548 * 6549 * @see AccessibilityNodeInfo 6550 */ createAccessibilityNodeInfo()6551 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 6552 if (mAccessibilityDelegate != null) { 6553 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 6554 } else { 6555 return createAccessibilityNodeInfoInternal(); 6556 } 6557 } 6558 6559 /** 6560 * @see #createAccessibilityNodeInfo() 6561 * 6562 * @hide 6563 */ createAccessibilityNodeInfoInternal()6564 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 6565 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6566 if (provider != null) { 6567 return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID); 6568 } else { 6569 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 6570 onInitializeAccessibilityNodeInfo(info); 6571 return info; 6572 } 6573 } 6574 6575 /** 6576 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 6577 * The base implementation sets: 6578 * <ul> 6579 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 6580 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 6581 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 6582 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 6583 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 6584 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 6585 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 6586 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 6587 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 6588 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 6589 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 6590 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 6591 * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li> 6592 * </ul> 6593 * <p> 6594 * Subclasses should override this method, call the super implementation, 6595 * and set additional attributes. 6596 * </p> 6597 * <p> 6598 * If an {@link AccessibilityDelegate} has been specified via calling 6599 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6600 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 6601 * is responsible for handling this call. 6602 * </p> 6603 * 6604 * @param info The instance to initialize. 6605 */ 6606 @CallSuper onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6607 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 6608 if (mAccessibilityDelegate != null) { 6609 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 6610 } else { 6611 onInitializeAccessibilityNodeInfoInternal(info); 6612 } 6613 } 6614 6615 /** 6616 * Gets the location of this view in screen coordinates. 6617 * 6618 * @param outRect The output location 6619 * @hide 6620 */ getBoundsOnScreen(Rect outRect)6621 public void getBoundsOnScreen(Rect outRect) { 6622 getBoundsOnScreen(outRect, false); 6623 } 6624 6625 /** 6626 * Gets the location of this view in screen coordinates. 6627 * 6628 * @param outRect The output location 6629 * @param clipToParent Whether to clip child bounds to the parent ones. 6630 * @hide 6631 */ getBoundsOnScreen(Rect outRect, boolean clipToParent)6632 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { 6633 if (mAttachInfo == null) { 6634 return; 6635 } 6636 6637 RectF position = mAttachInfo.mTmpTransformRect; 6638 position.set(0, 0, mRight - mLeft, mBottom - mTop); 6639 6640 if (!hasIdentityMatrix()) { 6641 getMatrix().mapRect(position); 6642 } 6643 6644 position.offset(mLeft, mTop); 6645 6646 ViewParent parent = mParent; 6647 while (parent instanceof View) { 6648 View parentView = (View) parent; 6649 6650 position.offset(-parentView.mScrollX, -parentView.mScrollY); 6651 6652 if (clipToParent) { 6653 position.left = Math.max(position.left, 0); 6654 position.top = Math.max(position.top, 0); 6655 position.right = Math.min(position.right, parentView.getWidth()); 6656 position.bottom = Math.min(position.bottom, parentView.getHeight()); 6657 } 6658 6659 if (!parentView.hasIdentityMatrix()) { 6660 parentView.getMatrix().mapRect(position); 6661 } 6662 6663 position.offset(parentView.mLeft, parentView.mTop); 6664 6665 parent = parentView.mParent; 6666 } 6667 6668 if (parent instanceof ViewRootImpl) { 6669 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 6670 position.offset(0, -viewRootImpl.mCurScrollY); 6671 } 6672 6673 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 6674 6675 outRect.set(Math.round(position.left), Math.round(position.top), 6676 Math.round(position.right), Math.round(position.bottom)); 6677 } 6678 6679 /** 6680 * Return the class name of this object to be used for accessibility purposes. 6681 * Subclasses should only override this if they are implementing something that 6682 * should be seen as a completely new class of view when used by accessibility, 6683 * unrelated to the class it is deriving from. This is used to fill in 6684 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}. 6685 */ getAccessibilityClassName()6686 public CharSequence getAccessibilityClassName() { 6687 return View.class.getName(); 6688 } 6689 6690 /** 6691 * Called when assist structure is being retrieved from a view as part of 6692 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. 6693 * @param structure Fill in with structured view data. The default implementation 6694 * fills in all data that can be inferred from the view itself. 6695 */ onProvideStructure(ViewStructure structure)6696 public void onProvideStructure(ViewStructure structure) { 6697 final int id = mID; 6698 if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0 6699 && (id&0x0000ffff) != 0) { 6700 String pkg, type, entry; 6701 try { 6702 final Resources res = getResources(); 6703 entry = res.getResourceEntryName(id); 6704 type = res.getResourceTypeName(id); 6705 pkg = res.getResourcePackageName(id); 6706 } catch (Resources.NotFoundException e) { 6707 entry = type = pkg = null; 6708 } 6709 structure.setId(id, pkg, type, entry); 6710 } else { 6711 structure.setId(id, null, null, null); 6712 } 6713 structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); 6714 if (!hasIdentityMatrix()) { 6715 structure.setTransformation(getMatrix()); 6716 } 6717 structure.setElevation(getZ()); 6718 structure.setVisibility(getVisibility()); 6719 structure.setEnabled(isEnabled()); 6720 if (isClickable()) { 6721 structure.setClickable(true); 6722 } 6723 if (isFocusable()) { 6724 structure.setFocusable(true); 6725 } 6726 if (isFocused()) { 6727 structure.setFocused(true); 6728 } 6729 if (isAccessibilityFocused()) { 6730 structure.setAccessibilityFocused(true); 6731 } 6732 if (isSelected()) { 6733 structure.setSelected(true); 6734 } 6735 if (isActivated()) { 6736 structure.setActivated(true); 6737 } 6738 if (isLongClickable()) { 6739 structure.setLongClickable(true); 6740 } 6741 if (this instanceof Checkable) { 6742 structure.setCheckable(true); 6743 if (((Checkable)this).isChecked()) { 6744 structure.setChecked(true); 6745 } 6746 } 6747 if (isContextClickable()) { 6748 structure.setContextClickable(true); 6749 } 6750 structure.setClassName(getAccessibilityClassName().toString()); 6751 structure.setContentDescription(getContentDescription()); 6752 } 6753 6754 /** 6755 * Called when assist structure is being retrieved from a view as part of 6756 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to 6757 * generate additional virtual structure under this view. The defaullt implementation 6758 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the 6759 * view's virtual accessibility nodes, if any. You can override this for a more 6760 * optimal implementation providing this data. 6761 */ onProvideVirtualStructure(ViewStructure structure)6762 public void onProvideVirtualStructure(ViewStructure structure) { 6763 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6764 if (provider != null) { 6765 AccessibilityNodeInfo info = createAccessibilityNodeInfo(); 6766 structure.setChildCount(1); 6767 ViewStructure root = structure.newChild(0); 6768 populateVirtualStructure(root, provider, info); 6769 info.recycle(); 6770 } 6771 } 6772 populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6773 private void populateVirtualStructure(ViewStructure structure, 6774 AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { 6775 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), 6776 null, null, null); 6777 Rect rect = structure.getTempRect(); 6778 info.getBoundsInParent(rect); 6779 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height()); 6780 structure.setVisibility(VISIBLE); 6781 structure.setEnabled(info.isEnabled()); 6782 if (info.isClickable()) { 6783 structure.setClickable(true); 6784 } 6785 if (info.isFocusable()) { 6786 structure.setFocusable(true); 6787 } 6788 if (info.isFocused()) { 6789 structure.setFocused(true); 6790 } 6791 if (info.isAccessibilityFocused()) { 6792 structure.setAccessibilityFocused(true); 6793 } 6794 if (info.isSelected()) { 6795 structure.setSelected(true); 6796 } 6797 if (info.isLongClickable()) { 6798 structure.setLongClickable(true); 6799 } 6800 if (info.isCheckable()) { 6801 structure.setCheckable(true); 6802 if (info.isChecked()) { 6803 structure.setChecked(true); 6804 } 6805 } 6806 if (info.isContextClickable()) { 6807 structure.setContextClickable(true); 6808 } 6809 CharSequence cname = info.getClassName(); 6810 structure.setClassName(cname != null ? cname.toString() : null); 6811 structure.setContentDescription(info.getContentDescription()); 6812 if (info.getText() != null || info.getError() != null) { 6813 structure.setText(info.getText(), info.getTextSelectionStart(), 6814 info.getTextSelectionEnd()); 6815 } 6816 final int NCHILDREN = info.getChildCount(); 6817 if (NCHILDREN > 0) { 6818 structure.setChildCount(NCHILDREN); 6819 for (int i=0; i<NCHILDREN; i++) { 6820 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( 6821 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); 6822 ViewStructure child = structure.newChild(i); 6823 populateVirtualStructure(child, provider, cinfo); 6824 cinfo.recycle(); 6825 } 6826 } 6827 } 6828 6829 /** 6830 * Dispatch creation of {@link ViewStructure} down the hierarchy. The default 6831 * implementation calls {@link #onProvideStructure} and 6832 * {@link #onProvideVirtualStructure}. 6833 */ dispatchProvideStructure(ViewStructure structure)6834 public void dispatchProvideStructure(ViewStructure structure) { 6835 if (!isAssistBlocked()) { 6836 onProvideStructure(structure); 6837 onProvideVirtualStructure(structure); 6838 } else { 6839 structure.setClassName(getAccessibilityClassName().toString()); 6840 structure.setAssistBlocked(true); 6841 } 6842 } 6843 6844 /** 6845 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 6846 * 6847 * Note: Called from the default {@link AccessibilityDelegate}. 6848 * 6849 * @hide 6850 */ onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6851 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 6852 if (mAttachInfo == null) { 6853 return; 6854 } 6855 6856 Rect bounds = mAttachInfo.mTmpInvalRect; 6857 6858 getDrawingRect(bounds); 6859 info.setBoundsInParent(bounds); 6860 6861 getBoundsOnScreen(bounds, true); 6862 info.setBoundsInScreen(bounds); 6863 6864 ViewParent parent = getParentForAccessibility(); 6865 if (parent instanceof View) { 6866 info.setParent((View) parent); 6867 } 6868 6869 if (mID != View.NO_ID) { 6870 View rootView = getRootView(); 6871 if (rootView == null) { 6872 rootView = this; 6873 } 6874 6875 View label = rootView.findLabelForView(this, mID); 6876 if (label != null) { 6877 info.setLabeledBy(label); 6878 } 6879 6880 if ((mAttachInfo.mAccessibilityFetchFlags 6881 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 6882 && Resources.resourceHasPackage(mID)) { 6883 try { 6884 String viewId = getResources().getResourceName(mID); 6885 info.setViewIdResourceName(viewId); 6886 } catch (Resources.NotFoundException nfe) { 6887 /* ignore */ 6888 } 6889 } 6890 } 6891 6892 if (mLabelForId != View.NO_ID) { 6893 View rootView = getRootView(); 6894 if (rootView == null) { 6895 rootView = this; 6896 } 6897 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 6898 if (labeled != null) { 6899 info.setLabelFor(labeled); 6900 } 6901 } 6902 6903 if (mAccessibilityTraversalBeforeId != View.NO_ID) { 6904 View rootView = getRootView(); 6905 if (rootView == null) { 6906 rootView = this; 6907 } 6908 View next = rootView.findViewInsideOutShouldExist(this, 6909 mAccessibilityTraversalBeforeId); 6910 if (next != null && next.includeForAccessibility()) { 6911 info.setTraversalBefore(next); 6912 } 6913 } 6914 6915 if (mAccessibilityTraversalAfterId != View.NO_ID) { 6916 View rootView = getRootView(); 6917 if (rootView == null) { 6918 rootView = this; 6919 } 6920 View next = rootView.findViewInsideOutShouldExist(this, 6921 mAccessibilityTraversalAfterId); 6922 if (next != null && next.includeForAccessibility()) { 6923 info.setTraversalAfter(next); 6924 } 6925 } 6926 6927 info.setVisibleToUser(isVisibleToUser()); 6928 6929 if ((mAttachInfo != null) && ((mAttachInfo.mAccessibilityFetchFlags 6930 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0)) { 6931 info.setImportantForAccessibility(isImportantForAccessibility()); 6932 } else { 6933 info.setImportantForAccessibility(true); 6934 } 6935 6936 info.setPackageName(mContext.getPackageName()); 6937 info.setClassName(getAccessibilityClassName()); 6938 info.setContentDescription(getContentDescription()); 6939 6940 info.setEnabled(isEnabled()); 6941 info.setClickable(isClickable()); 6942 info.setFocusable(isFocusable()); 6943 info.setFocused(isFocused()); 6944 info.setAccessibilityFocused(isAccessibilityFocused()); 6945 info.setSelected(isSelected()); 6946 info.setLongClickable(isLongClickable()); 6947 info.setContextClickable(isContextClickable()); 6948 info.setLiveRegion(getAccessibilityLiveRegion()); 6949 6950 // TODO: These make sense only if we are in an AdapterView but all 6951 // views can be selected. Maybe from accessibility perspective 6952 // we should report as selectable view in an AdapterView. 6953 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 6954 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 6955 6956 if (isFocusable()) { 6957 if (isFocused()) { 6958 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 6959 } else { 6960 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 6961 } 6962 } 6963 6964 if (!isAccessibilityFocused()) { 6965 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 6966 } else { 6967 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 6968 } 6969 6970 if (isClickable() && isEnabled()) { 6971 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 6972 } 6973 6974 if (isLongClickable() && isEnabled()) { 6975 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 6976 } 6977 6978 if (isContextClickable() && isEnabled()) { 6979 info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK); 6980 } 6981 6982 CharSequence text = getIterableTextForAccessibility(); 6983 if (text != null && text.length() > 0) { 6984 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 6985 6986 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 6987 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 6988 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 6989 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 6990 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 6991 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 6992 } 6993 6994 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); 6995 populateAccessibilityNodeInfoDrawingOrderInParent(info); 6996 } 6997 6998 /** 6999 * Determine the order in which this view will be drawn relative to its siblings for a11y 7000 * 7001 * @param info The info whose drawing order should be populated 7002 */ populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info)7003 private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) { 7004 /* 7005 * If the view's bounds haven't been set yet, layout has not completed. In that situation, 7006 * drawing order may not be well-defined, and some Views with custom drawing order may 7007 * not be initialized sufficiently to respond properly getChildDrawingOrder. 7008 */ 7009 if ((mPrivateFlags & PFLAG_HAS_BOUNDS) == 0) { 7010 info.setDrawingOrder(0); 7011 return; 7012 } 7013 int drawingOrderInParent = 1; 7014 // Iterate up the hierarchy if parents are not important for a11y 7015 View viewAtDrawingLevel = this; 7016 final ViewParent parent = getParentForAccessibility(); 7017 while (viewAtDrawingLevel != parent) { 7018 final ViewParent currentParent = viewAtDrawingLevel.getParent(); 7019 if (!(currentParent instanceof ViewGroup)) { 7020 // Should only happen for the Decor 7021 drawingOrderInParent = 0; 7022 break; 7023 } else { 7024 final ViewGroup parentGroup = (ViewGroup) currentParent; 7025 final int childCount = parentGroup.getChildCount(); 7026 if (childCount > 1) { 7027 List<View> preorderedList = parentGroup.buildOrderedChildList(); 7028 if (preorderedList != null) { 7029 final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel); 7030 for (int i = 0; i < childDrawIndex; i++) { 7031 drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i)); 7032 } 7033 } else { 7034 final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel); 7035 final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled(); 7036 final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup 7037 .getChildDrawingOrder(childCount, childIndex) : childIndex; 7038 final int numChildrenToIterate = customOrder ? childCount : childDrawIndex; 7039 if (childDrawIndex != 0) { 7040 for (int i = 0; i < numChildrenToIterate; i++) { 7041 final int otherDrawIndex = (customOrder ? 7042 parentGroup.getChildDrawingOrder(childCount, i) : i); 7043 if (otherDrawIndex < childDrawIndex) { 7044 drawingOrderInParent += 7045 numViewsForAccessibility(parentGroup.getChildAt(i)); 7046 } 7047 } 7048 } 7049 } 7050 } 7051 } 7052 viewAtDrawingLevel = (View) currentParent; 7053 } 7054 info.setDrawingOrder(drawingOrderInParent); 7055 } 7056 numViewsForAccessibility(View view)7057 private static int numViewsForAccessibility(View view) { 7058 if (view != null) { 7059 if (view.includeForAccessibility()) { 7060 return 1; 7061 } else if (view instanceof ViewGroup) { 7062 return ((ViewGroup) view).getNumChildrenForAccessibility(); 7063 } 7064 } 7065 return 0; 7066 } 7067 findLabelForView(View view, int labeledId)7068 private View findLabelForView(View view, int labeledId) { 7069 if (mMatchLabelForPredicate == null) { 7070 mMatchLabelForPredicate = new MatchLabelForPredicate(); 7071 } 7072 mMatchLabelForPredicate.mLabeledId = labeledId; 7073 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 7074 } 7075 7076 /** 7077 * Computes whether this view is visible to the user. Such a view is 7078 * attached, visible, all its predecessors are visible, it is not clipped 7079 * entirely by its predecessors, and has an alpha greater than zero. 7080 * 7081 * @return Whether the view is visible on the screen. 7082 * 7083 * @hide 7084 */ isVisibleToUser()7085 protected boolean isVisibleToUser() { 7086 return isVisibleToUser(null); 7087 } 7088 7089 /** 7090 * Computes whether the given portion of this view is visible to the user. 7091 * Such a view is attached, visible, all its predecessors are visible, 7092 * has an alpha greater than zero, and the specified portion is not 7093 * clipped entirely by its predecessors. 7094 * 7095 * @param boundInView the portion of the view to test; coordinates should be relative; may be 7096 * <code>null</code>, and the entire view will be tested in this case. 7097 * When <code>true</code> is returned by the function, the actual visible 7098 * region will be stored in this parameter; that is, if boundInView is fully 7099 * contained within the view, no modification will be made, otherwise regions 7100 * outside of the visible area of the view will be clipped. 7101 * 7102 * @return Whether the specified portion of the view is visible on the screen. 7103 * 7104 * @hide 7105 */ isVisibleToUser(Rect boundInView)7106 protected boolean isVisibleToUser(Rect boundInView) { 7107 if (mAttachInfo != null) { 7108 // Attached to invisible window means this view is not visible. 7109 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 7110 return false; 7111 } 7112 // An invisible predecessor or one with alpha zero means 7113 // that this view is not visible to the user. 7114 Object current = this; 7115 while (current instanceof View) { 7116 View view = (View) current; 7117 // We have attach info so this view is attached and there is no 7118 // need to check whether we reach to ViewRootImpl on the way up. 7119 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 7120 view.getVisibility() != VISIBLE) { 7121 return false; 7122 } 7123 current = view.mParent; 7124 } 7125 // Check if the view is entirely covered by its predecessors. 7126 Rect visibleRect = mAttachInfo.mTmpInvalRect; 7127 Point offset = mAttachInfo.mPoint; 7128 if (!getGlobalVisibleRect(visibleRect, offset)) { 7129 return false; 7130 } 7131 // Check if the visible portion intersects the rectangle of interest. 7132 if (boundInView != null) { 7133 visibleRect.offset(-offset.x, -offset.y); 7134 return boundInView.intersect(visibleRect); 7135 } 7136 return true; 7137 } 7138 return false; 7139 } 7140 7141 /** 7142 * Returns the delegate for implementing accessibility support via 7143 * composition. For more details see {@link AccessibilityDelegate}. 7144 * 7145 * @return The delegate, or null if none set. 7146 * 7147 * @hide 7148 */ getAccessibilityDelegate()7149 public AccessibilityDelegate getAccessibilityDelegate() { 7150 return mAccessibilityDelegate; 7151 } 7152 7153 /** 7154 * Sets a delegate for implementing accessibility support via composition 7155 * (as opposed to inheritance). For more details, see 7156 * {@link AccessibilityDelegate}. 7157 * <p> 7158 * <strong>Note:</strong> On platform versions prior to 7159 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 7160 * views in the {@code android.widget.*} package are called <i>before</i> 7161 * host methods. This prevents certain properties such as class name from 7162 * being modified by overriding 7163 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 7164 * as any changes will be overwritten by the host class. 7165 * <p> 7166 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 7167 * methods are called <i>after</i> host methods, which all properties to be 7168 * modified without being overwritten by the host class. 7169 * 7170 * @param delegate the object to which accessibility method calls should be 7171 * delegated 7172 * @see AccessibilityDelegate 7173 */ setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)7174 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) { 7175 mAccessibilityDelegate = delegate; 7176 } 7177 7178 /** 7179 * Gets the provider for managing a virtual view hierarchy rooted at this View 7180 * and reported to {@link android.accessibilityservice.AccessibilityService}s 7181 * that explore the window content. 7182 * <p> 7183 * If this method returns an instance, this instance is responsible for managing 7184 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 7185 * View including the one representing the View itself. Similarly the returned 7186 * instance is responsible for performing accessibility actions on any virtual 7187 * view or the root view itself. 7188 * </p> 7189 * <p> 7190 * If an {@link AccessibilityDelegate} has been specified via calling 7191 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7192 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 7193 * is responsible for handling this call. 7194 * </p> 7195 * 7196 * @return The provider. 7197 * 7198 * @see AccessibilityNodeProvider 7199 */ getAccessibilityNodeProvider()7200 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 7201 if (mAccessibilityDelegate != null) { 7202 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 7203 } else { 7204 return null; 7205 } 7206 } 7207 7208 /** 7209 * Gets the unique identifier of this view on the screen for accessibility purposes. 7210 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 7211 * 7212 * @return The view accessibility id. 7213 * 7214 * @hide 7215 */ getAccessibilityViewId()7216 public int getAccessibilityViewId() { 7217 if (mAccessibilityViewId == NO_ID) { 7218 mAccessibilityViewId = sNextAccessibilityViewId++; 7219 } 7220 return mAccessibilityViewId; 7221 } 7222 7223 /** 7224 * Gets the unique identifier of the window in which this View reseides. 7225 * 7226 * @return The window accessibility id. 7227 * 7228 * @hide 7229 */ getAccessibilityWindowId()7230 public int getAccessibilityWindowId() { 7231 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId 7232 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 7233 } 7234 7235 /** 7236 * Returns the {@link View}'s content description. 7237 * <p> 7238 * <strong>Note:</strong> Do not override this method, as it will have no 7239 * effect on the content description presented to accessibility services. 7240 * You must call {@link #setContentDescription(CharSequence)} to modify the 7241 * content description. 7242 * 7243 * @return the content description 7244 * @see #setContentDescription(CharSequence) 7245 * @attr ref android.R.styleable#View_contentDescription 7246 */ 7247 @ViewDebug.ExportedProperty(category = "accessibility") getContentDescription()7248 public CharSequence getContentDescription() { 7249 return mContentDescription; 7250 } 7251 7252 /** 7253 * Sets the {@link View}'s content description. 7254 * <p> 7255 * A content description briefly describes the view and is primarily used 7256 * for accessibility support to determine how a view should be presented to 7257 * the user. In the case of a view with no textual representation, such as 7258 * {@link android.widget.ImageButton}, a useful content description 7259 * explains what the view does. For example, an image button with a phone 7260 * icon that is used to place a call may use "Call" as its content 7261 * description. An image of a floppy disk that is used to save a file may 7262 * use "Save". 7263 * 7264 * @param contentDescription The content description. 7265 * @see #getContentDescription() 7266 * @attr ref android.R.styleable#View_contentDescription 7267 */ 7268 @RemotableViewMethod setContentDescription(CharSequence contentDescription)7269 public void setContentDescription(CharSequence contentDescription) { 7270 if (mContentDescription == null) { 7271 if (contentDescription == null) { 7272 return; 7273 } 7274 } else if (mContentDescription.equals(contentDescription)) { 7275 return; 7276 } 7277 mContentDescription = contentDescription; 7278 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 7279 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 7280 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 7281 notifySubtreeAccessibilityStateChangedIfNeeded(); 7282 } else { 7283 notifyViewAccessibilityStateChangedIfNeeded( 7284 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 7285 } 7286 } 7287 7288 /** 7289 * Sets the id of a view before which this one is visited in accessibility traversal. 7290 * A screen-reader must visit the content of this view before the content of the one 7291 * it precedes. For example, if view B is set to be before view A, then a screen-reader 7292 * will traverse the entire content of B before traversing the entire content of A, 7293 * regardles of what traversal strategy it is using. 7294 * <p> 7295 * Views that do not have specified before/after relationships are traversed in order 7296 * determined by the screen-reader. 7297 * </p> 7298 * <p> 7299 * Setting that this view is before a view that is not important for accessibility 7300 * or if this view is not important for accessibility will have no effect as the 7301 * screen-reader is not aware of unimportant views. 7302 * </p> 7303 * 7304 * @param beforeId The id of a view this one precedes in accessibility traversal. 7305 * 7306 * @attr ref android.R.styleable#View_accessibilityTraversalBefore 7307 * 7308 * @see #setImportantForAccessibility(int) 7309 */ 7310 @RemotableViewMethod setAccessibilityTraversalBefore(int beforeId)7311 public void setAccessibilityTraversalBefore(int beforeId) { 7312 if (mAccessibilityTraversalBeforeId == beforeId) { 7313 return; 7314 } 7315 mAccessibilityTraversalBeforeId = beforeId; 7316 notifyViewAccessibilityStateChangedIfNeeded( 7317 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7318 } 7319 7320 /** 7321 * Gets the id of a view before which this one is visited in accessibility traversal. 7322 * 7323 * @return The id of a view this one precedes in accessibility traversal if 7324 * specified, otherwise {@link #NO_ID}. 7325 * 7326 * @see #setAccessibilityTraversalBefore(int) 7327 */ getAccessibilityTraversalBefore()7328 public int getAccessibilityTraversalBefore() { 7329 return mAccessibilityTraversalBeforeId; 7330 } 7331 7332 /** 7333 * Sets the id of a view after which this one is visited in accessibility traversal. 7334 * A screen-reader must visit the content of the other view before the content of this 7335 * one. For example, if view B is set to be after view A, then a screen-reader 7336 * will traverse the entire content of A before traversing the entire content of B, 7337 * regardles of what traversal strategy it is using. 7338 * <p> 7339 * Views that do not have specified before/after relationships are traversed in order 7340 * determined by the screen-reader. 7341 * </p> 7342 * <p> 7343 * Setting that this view is after a view that is not important for accessibility 7344 * or if this view is not important for accessibility will have no effect as the 7345 * screen-reader is not aware of unimportant views. 7346 * </p> 7347 * 7348 * @param afterId The id of a view this one succedees in accessibility traversal. 7349 * 7350 * @attr ref android.R.styleable#View_accessibilityTraversalAfter 7351 * 7352 * @see #setImportantForAccessibility(int) 7353 */ 7354 @RemotableViewMethod setAccessibilityTraversalAfter(int afterId)7355 public void setAccessibilityTraversalAfter(int afterId) { 7356 if (mAccessibilityTraversalAfterId == afterId) { 7357 return; 7358 } 7359 mAccessibilityTraversalAfterId = afterId; 7360 notifyViewAccessibilityStateChangedIfNeeded( 7361 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7362 } 7363 7364 /** 7365 * Gets the id of a view after which this one is visited in accessibility traversal. 7366 * 7367 * @return The id of a view this one succeedes in accessibility traversal if 7368 * specified, otherwise {@link #NO_ID}. 7369 * 7370 * @see #setAccessibilityTraversalAfter(int) 7371 */ getAccessibilityTraversalAfter()7372 public int getAccessibilityTraversalAfter() { 7373 return mAccessibilityTraversalAfterId; 7374 } 7375 7376 /** 7377 * Gets the id of a view for which this view serves as a label for 7378 * accessibility purposes. 7379 * 7380 * @return The labeled view id. 7381 */ 7382 @ViewDebug.ExportedProperty(category = "accessibility") getLabelFor()7383 public int getLabelFor() { 7384 return mLabelForId; 7385 } 7386 7387 /** 7388 * Sets the id of a view for which this view serves as a label for 7389 * accessibility purposes. 7390 * 7391 * @param id The labeled view id. 7392 */ 7393 @RemotableViewMethod setLabelFor(@dRes int id)7394 public void setLabelFor(@IdRes int id) { 7395 if (mLabelForId == id) { 7396 return; 7397 } 7398 mLabelForId = id; 7399 if (mLabelForId != View.NO_ID 7400 && mID == View.NO_ID) { 7401 mID = generateViewId(); 7402 } 7403 notifyViewAccessibilityStateChangedIfNeeded( 7404 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7405 } 7406 7407 /** 7408 * Invoked whenever this view loses focus, either by losing window focus or by losing 7409 * focus within its window. This method can be used to clear any state tied to the 7410 * focus. For instance, if a button is held pressed with the trackball and the window 7411 * loses focus, this method can be used to cancel the press. 7412 * 7413 * Subclasses of View overriding this method should always call super.onFocusLost(). 7414 * 7415 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 7416 * @see #onWindowFocusChanged(boolean) 7417 * 7418 * @hide pending API council approval 7419 */ 7420 @CallSuper onFocusLost()7421 protected void onFocusLost() { 7422 resetPressedState(); 7423 } 7424 resetPressedState()7425 private void resetPressedState() { 7426 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 7427 return; 7428 } 7429 7430 if (isPressed()) { 7431 setPressed(false); 7432 7433 if (!mHasPerformedLongPress) { 7434 removeLongPressCallback(); 7435 } 7436 } 7437 } 7438 7439 /** 7440 * Returns true if this view has focus 7441 * 7442 * @return True if this view has focus, false otherwise. 7443 */ 7444 @ViewDebug.ExportedProperty(category = "focus") isFocused()7445 public boolean isFocused() { 7446 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 7447 } 7448 7449 /** 7450 * Find the view in the hierarchy rooted at this view that currently has 7451 * focus. 7452 * 7453 * @return The view that currently has focus, or null if no focused view can 7454 * be found. 7455 */ findFocus()7456 public View findFocus() { 7457 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 7458 } 7459 7460 /** 7461 * Indicates whether this view is one of the set of scrollable containers in 7462 * its window. 7463 * 7464 * @return whether this view is one of the set of scrollable containers in 7465 * its window 7466 * 7467 * @attr ref android.R.styleable#View_isScrollContainer 7468 */ isScrollContainer()7469 public boolean isScrollContainer() { 7470 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 7471 } 7472 7473 /** 7474 * Change whether this view is one of the set of scrollable containers in 7475 * its window. This will be used to determine whether the window can 7476 * resize or must pan when a soft input area is open -- scrollable 7477 * containers allow the window to use resize mode since the container 7478 * will appropriately shrink. 7479 * 7480 * @attr ref android.R.styleable#View_isScrollContainer 7481 */ setScrollContainer(boolean isScrollContainer)7482 public void setScrollContainer(boolean isScrollContainer) { 7483 if (isScrollContainer) { 7484 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 7485 mAttachInfo.mScrollContainers.add(this); 7486 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 7487 } 7488 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 7489 } else { 7490 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 7491 mAttachInfo.mScrollContainers.remove(this); 7492 } 7493 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 7494 } 7495 } 7496 7497 /** 7498 * Returns the quality of the drawing cache. 7499 * 7500 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7501 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7502 * 7503 * @see #setDrawingCacheQuality(int) 7504 * @see #setDrawingCacheEnabled(boolean) 7505 * @see #isDrawingCacheEnabled() 7506 * 7507 * @attr ref android.R.styleable#View_drawingCacheQuality 7508 */ 7509 @DrawingCacheQuality getDrawingCacheQuality()7510 public int getDrawingCacheQuality() { 7511 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 7512 } 7513 7514 /** 7515 * Set the drawing cache quality of this view. This value is used only when the 7516 * drawing cache is enabled 7517 * 7518 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7519 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7520 * 7521 * @see #getDrawingCacheQuality() 7522 * @see #setDrawingCacheEnabled(boolean) 7523 * @see #isDrawingCacheEnabled() 7524 * 7525 * @attr ref android.R.styleable#View_drawingCacheQuality 7526 */ setDrawingCacheQuality(@rawingCacheQuality int quality)7527 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) { 7528 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 7529 } 7530 7531 /** 7532 * Returns whether the screen should remain on, corresponding to the current 7533 * value of {@link #KEEP_SCREEN_ON}. 7534 * 7535 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 7536 * 7537 * @see #setKeepScreenOn(boolean) 7538 * 7539 * @attr ref android.R.styleable#View_keepScreenOn 7540 */ getKeepScreenOn()7541 public boolean getKeepScreenOn() { 7542 return (mViewFlags & KEEP_SCREEN_ON) != 0; 7543 } 7544 7545 /** 7546 * Controls whether the screen should remain on, modifying the 7547 * value of {@link #KEEP_SCREEN_ON}. 7548 * 7549 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 7550 * 7551 * @see #getKeepScreenOn() 7552 * 7553 * @attr ref android.R.styleable#View_keepScreenOn 7554 */ setKeepScreenOn(boolean keepScreenOn)7555 public void setKeepScreenOn(boolean keepScreenOn) { 7556 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 7557 } 7558 7559 /** 7560 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7561 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7562 * 7563 * @attr ref android.R.styleable#View_nextFocusLeft 7564 */ getNextFocusLeftId()7565 public int getNextFocusLeftId() { 7566 return mNextFocusLeftId; 7567 } 7568 7569 /** 7570 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7571 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 7572 * decide automatically. 7573 * 7574 * @attr ref android.R.styleable#View_nextFocusLeft 7575 */ setNextFocusLeftId(int nextFocusLeftId)7576 public void setNextFocusLeftId(int nextFocusLeftId) { 7577 mNextFocusLeftId = nextFocusLeftId; 7578 } 7579 7580 /** 7581 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7582 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7583 * 7584 * @attr ref android.R.styleable#View_nextFocusRight 7585 */ getNextFocusRightId()7586 public int getNextFocusRightId() { 7587 return mNextFocusRightId; 7588 } 7589 7590 /** 7591 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7592 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 7593 * decide automatically. 7594 * 7595 * @attr ref android.R.styleable#View_nextFocusRight 7596 */ setNextFocusRightId(int nextFocusRightId)7597 public void setNextFocusRightId(int nextFocusRightId) { 7598 mNextFocusRightId = nextFocusRightId; 7599 } 7600 7601 /** 7602 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7603 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7604 * 7605 * @attr ref android.R.styleable#View_nextFocusUp 7606 */ getNextFocusUpId()7607 public int getNextFocusUpId() { 7608 return mNextFocusUpId; 7609 } 7610 7611 /** 7612 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7613 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 7614 * decide automatically. 7615 * 7616 * @attr ref android.R.styleable#View_nextFocusUp 7617 */ setNextFocusUpId(int nextFocusUpId)7618 public void setNextFocusUpId(int nextFocusUpId) { 7619 mNextFocusUpId = nextFocusUpId; 7620 } 7621 7622 /** 7623 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7624 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7625 * 7626 * @attr ref android.R.styleable#View_nextFocusDown 7627 */ getNextFocusDownId()7628 public int getNextFocusDownId() { 7629 return mNextFocusDownId; 7630 } 7631 7632 /** 7633 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7634 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 7635 * decide automatically. 7636 * 7637 * @attr ref android.R.styleable#View_nextFocusDown 7638 */ setNextFocusDownId(int nextFocusDownId)7639 public void setNextFocusDownId(int nextFocusDownId) { 7640 mNextFocusDownId = nextFocusDownId; 7641 } 7642 7643 /** 7644 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7645 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7646 * 7647 * @attr ref android.R.styleable#View_nextFocusForward 7648 */ getNextFocusForwardId()7649 public int getNextFocusForwardId() { 7650 return mNextFocusForwardId; 7651 } 7652 7653 /** 7654 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7655 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 7656 * decide automatically. 7657 * 7658 * @attr ref android.R.styleable#View_nextFocusForward 7659 */ setNextFocusForwardId(int nextFocusForwardId)7660 public void setNextFocusForwardId(int nextFocusForwardId) { 7661 mNextFocusForwardId = nextFocusForwardId; 7662 } 7663 7664 /** 7665 * Returns the visibility of this view and all of its ancestors 7666 * 7667 * @return True if this view and all of its ancestors are {@link #VISIBLE} 7668 */ isShown()7669 public boolean isShown() { 7670 View current = this; 7671 //noinspection ConstantConditions 7672 do { 7673 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 7674 return false; 7675 } 7676 ViewParent parent = current.mParent; 7677 if (parent == null) { 7678 return false; // We are not attached to the view root 7679 } 7680 if (!(parent instanceof View)) { 7681 return true; 7682 } 7683 current = (View) parent; 7684 } while (current != null); 7685 7686 return false; 7687 } 7688 7689 /** 7690 * Called by the view hierarchy when the content insets for a window have 7691 * changed, to allow it to adjust its content to fit within those windows. 7692 * The content insets tell you the space that the status bar, input method, 7693 * and other system windows infringe on the application's window. 7694 * 7695 * <p>You do not normally need to deal with this function, since the default 7696 * window decoration given to applications takes care of applying it to the 7697 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 7698 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 7699 * and your content can be placed under those system elements. You can then 7700 * use this method within your view hierarchy if you have parts of your UI 7701 * which you would like to ensure are not being covered. 7702 * 7703 * <p>The default implementation of this method simply applies the content 7704 * insets to the view's padding, consuming that content (modifying the 7705 * insets to be 0), and returning true. This behavior is off by default, but can 7706 * be enabled through {@link #setFitsSystemWindows(boolean)}. 7707 * 7708 * <p>This function's traversal down the hierarchy is depth-first. The same content 7709 * insets object is propagated down the hierarchy, so any changes made to it will 7710 * be seen by all following views (including potentially ones above in 7711 * the hierarchy since this is a depth-first traversal). The first view 7712 * that returns true will abort the entire traversal. 7713 * 7714 * <p>The default implementation works well for a situation where it is 7715 * used with a container that covers the entire window, allowing it to 7716 * apply the appropriate insets to its content on all edges. If you need 7717 * a more complicated layout (such as two different views fitting system 7718 * windows, one on the top of the window, and one on the bottom), 7719 * you can override the method and handle the insets however you would like. 7720 * Note that the insets provided by the framework are always relative to the 7721 * far edges of the window, not accounting for the location of the called view 7722 * within that window. (In fact when this method is called you do not yet know 7723 * where the layout will place the view, as it is done before layout happens.) 7724 * 7725 * <p>Note: unlike many View methods, there is no dispatch phase to this 7726 * call. If you are overriding it in a ViewGroup and want to allow the 7727 * call to continue to your children, you must be sure to call the super 7728 * implementation. 7729 * 7730 * <p>Here is a sample layout that makes use of fitting system windows 7731 * to have controls for a video view placed inside of the window decorations 7732 * that it hides and shows. This can be used with code like the second 7733 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 7734 * 7735 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 7736 * 7737 * @param insets Current content insets of the window. Prior to 7738 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 7739 * the insets or else you and Android will be unhappy. 7740 * 7741 * @return {@code true} if this view applied the insets and it should not 7742 * continue propagating further down the hierarchy, {@code false} otherwise. 7743 * @see #getFitsSystemWindows() 7744 * @see #setFitsSystemWindows(boolean) 7745 * @see #setSystemUiVisibility(int) 7746 * 7747 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply 7748 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use 7749 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)} 7750 * to implement handling their own insets. 7751 */ fitSystemWindows(Rect insets)7752 protected boolean fitSystemWindows(Rect insets) { 7753 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) { 7754 if (insets == null) { 7755 // Null insets by definition have already been consumed. 7756 // This call cannot apply insets since there are none to apply, 7757 // so return false. 7758 return false; 7759 } 7760 // If we're not in the process of dispatching the newer apply insets call, 7761 // that means we're not in the compatibility path. Dispatch into the newer 7762 // apply insets path and take things from there. 7763 try { 7764 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS; 7765 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed(); 7766 } finally { 7767 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS; 7768 } 7769 } else { 7770 // We're being called from the newer apply insets path. 7771 // Perform the standard fallback behavior. 7772 return fitSystemWindowsInt(insets); 7773 } 7774 } 7775 fitSystemWindowsInt(Rect insets)7776 private boolean fitSystemWindowsInt(Rect insets) { 7777 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 7778 mUserPaddingStart = UNDEFINED_PADDING; 7779 mUserPaddingEnd = UNDEFINED_PADDING; 7780 Rect localInsets = sThreadLocal.get(); 7781 if (localInsets == null) { 7782 localInsets = new Rect(); 7783 sThreadLocal.set(localInsets); 7784 } 7785 boolean res = computeFitSystemWindows(insets, localInsets); 7786 mUserPaddingLeftInitial = localInsets.left; 7787 mUserPaddingRightInitial = localInsets.right; 7788 internalSetPadding(localInsets.left, localInsets.top, 7789 localInsets.right, localInsets.bottom); 7790 return res; 7791 } 7792 return false; 7793 } 7794 7795 /** 7796 * Called when the view should apply {@link WindowInsets} according to its internal policy. 7797 * 7798 * <p>This method should be overridden by views that wish to apply a policy different from or 7799 * in addition to the default behavior. Clients that wish to force a view subtree 7800 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p> 7801 * 7802 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set 7803 * it will be called during dispatch instead of this method. The listener may optionally 7804 * call this method from its own implementation if it wishes to apply the view's default 7805 * insets policy in addition to its own.</p> 7806 * 7807 * <p>Implementations of this method should either return the insets parameter unchanged 7808 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed 7809 * that this view applied itself. This allows new inset types added in future platform 7810 * versions to pass through existing implementations unchanged without being erroneously 7811 * consumed.</p> 7812 * 7813 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows} 7814 * property is set then the view will consume the system window insets and apply them 7815 * as padding for the view.</p> 7816 * 7817 * @param insets Insets to apply 7818 * @return The supplied insets with any applied insets consumed 7819 */ onApplyWindowInsets(WindowInsets insets)7820 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 7821 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) { 7822 // We weren't called from within a direct call to fitSystemWindows, 7823 // call into it as a fallback in case we're in a class that overrides it 7824 // and has logic to perform. 7825 if (fitSystemWindows(insets.getSystemWindowInsets())) { 7826 return insets.consumeSystemWindowInsets(); 7827 } 7828 } else { 7829 // We were called from within a direct call to fitSystemWindows. 7830 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) { 7831 return insets.consumeSystemWindowInsets(); 7832 } 7833 } 7834 return insets; 7835 } 7836 7837 /** 7838 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying 7839 * window insets to this view. The listener's 7840 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 7841 * method will be called instead of the view's 7842 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 7843 * 7844 * @param listener Listener to set 7845 * 7846 * @see #onApplyWindowInsets(WindowInsets) 7847 */ setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7848 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) { 7849 getListenerInfo().mOnApplyWindowInsetsListener = listener; 7850 } 7851 7852 /** 7853 * Request to apply the given window insets to this view or another view in its subtree. 7854 * 7855 * <p>This method should be called by clients wishing to apply insets corresponding to areas 7856 * obscured by window decorations or overlays. This can include the status and navigation bars, 7857 * action bars, input methods and more. New inset categories may be added in the future. 7858 * The method returns the insets provided minus any that were applied by this view or its 7859 * children.</p> 7860 * 7861 * <p>Clients wishing to provide custom behavior should override the 7862 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a 7863 * {@link OnApplyWindowInsetsListener} via the 7864 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener} 7865 * method.</p> 7866 * 7867 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method. 7868 * </p> 7869 * 7870 * @param insets Insets to apply 7871 * @return The provided insets minus the insets that were consumed 7872 */ dispatchApplyWindowInsets(WindowInsets insets)7873 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { 7874 try { 7875 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS; 7876 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) { 7877 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets); 7878 } else { 7879 return onApplyWindowInsets(insets); 7880 } 7881 } finally { 7882 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS; 7883 } 7884 } 7885 7886 /** 7887 * Compute the view's coordinate within the surface. 7888 * 7889 * <p>Computes the coordinates of this view in its surface. The argument 7890 * must be an array of two integers. After the method returns, the array 7891 * contains the x and y location in that order.</p> 7892 * @hide 7893 * @param location an array of two integers in which to hold the coordinates 7894 */ getLocationInSurface(@ize2) int[] location)7895 public void getLocationInSurface(@Size(2) int[] location) { 7896 getLocationInWindow(location); 7897 if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) { 7898 location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left; 7899 location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top; 7900 } 7901 } 7902 7903 /** 7904 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are 7905 * only available if the view is attached. 7906 * 7907 * @return WindowInsets from the top of the view hierarchy or null if View is detached 7908 */ getRootWindowInsets()7909 public WindowInsets getRootWindowInsets() { 7910 if (mAttachInfo != null) { 7911 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */); 7912 } 7913 return null; 7914 } 7915 7916 /** 7917 * @hide Compute the insets that should be consumed by this view and the ones 7918 * that should propagate to those under it. 7919 */ computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7920 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 7921 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7922 || mAttachInfo == null 7923 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 7924 && !mAttachInfo.mOverscanRequested)) { 7925 outLocalInsets.set(inoutInsets); 7926 inoutInsets.set(0, 0, 0, 0); 7927 return true; 7928 } else { 7929 // The application wants to take care of fitting system window for 7930 // the content... however we still need to take care of any overscan here. 7931 final Rect overscan = mAttachInfo.mOverscanInsets; 7932 outLocalInsets.set(overscan); 7933 inoutInsets.left -= overscan.left; 7934 inoutInsets.top -= overscan.top; 7935 inoutInsets.right -= overscan.right; 7936 inoutInsets.bottom -= overscan.bottom; 7937 return false; 7938 } 7939 } 7940 7941 /** 7942 * Compute insets that should be consumed by this view and the ones that should propagate 7943 * to those under it. 7944 * 7945 * @param in Insets currently being processed by this View, likely received as a parameter 7946 * to {@link #onApplyWindowInsets(WindowInsets)}. 7947 * @param outLocalInsets A Rect that will receive the insets that should be consumed 7948 * by this view 7949 * @return Insets that should be passed along to views under this one 7950 */ computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7951 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) { 7952 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7953 || mAttachInfo == null 7954 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) { 7955 outLocalInsets.set(in.getSystemWindowInsets()); 7956 return in.consumeSystemWindowInsets(); 7957 } else { 7958 outLocalInsets.set(0, 0, 0, 0); 7959 return in; 7960 } 7961 } 7962 7963 /** 7964 * Sets whether or not this view should account for system screen decorations 7965 * such as the status bar and inset its content; that is, controlling whether 7966 * the default implementation of {@link #fitSystemWindows(Rect)} will be 7967 * executed. See that method for more details. 7968 * 7969 * <p>Note that if you are providing your own implementation of 7970 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 7971 * flag to true -- your implementation will be overriding the default 7972 * implementation that checks this flag. 7973 * 7974 * @param fitSystemWindows If true, then the default implementation of 7975 * {@link #fitSystemWindows(Rect)} will be executed. 7976 * 7977 * @attr ref android.R.styleable#View_fitsSystemWindows 7978 * @see #getFitsSystemWindows() 7979 * @see #fitSystemWindows(Rect) 7980 * @see #setSystemUiVisibility(int) 7981 */ setFitsSystemWindows(boolean fitSystemWindows)7982 public void setFitsSystemWindows(boolean fitSystemWindows) { 7983 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 7984 } 7985 7986 /** 7987 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 7988 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 7989 * will be executed. 7990 * 7991 * @return {@code true} if the default implementation of 7992 * {@link #fitSystemWindows(Rect)} will be executed. 7993 * 7994 * @attr ref android.R.styleable#View_fitsSystemWindows 7995 * @see #setFitsSystemWindows(boolean) 7996 * @see #fitSystemWindows(Rect) 7997 * @see #setSystemUiVisibility(int) 7998 */ 7999 @ViewDebug.ExportedProperty getFitsSystemWindows()8000 public boolean getFitsSystemWindows() { 8001 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 8002 } 8003 8004 /** @hide */ fitsSystemWindows()8005 public boolean fitsSystemWindows() { 8006 return getFitsSystemWindows(); 8007 } 8008 8009 /** 8010 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 8011 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions. 8012 */ requestFitSystemWindows()8013 public void requestFitSystemWindows() { 8014 if (mParent != null) { 8015 mParent.requestFitSystemWindows(); 8016 } 8017 } 8018 8019 /** 8020 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed. 8021 */ requestApplyInsets()8022 public void requestApplyInsets() { 8023 requestFitSystemWindows(); 8024 } 8025 8026 /** 8027 * For use by PhoneWindow to make its own system window fitting optional. 8028 * @hide 8029 */ makeOptionalFitsSystemWindows()8030 public void makeOptionalFitsSystemWindows() { 8031 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 8032 } 8033 8034 /** 8035 * Returns the outsets, which areas of the device that aren't a surface, but we would like to 8036 * treat them as such. 8037 * @hide 8038 */ getOutsets(Rect outOutsetRect)8039 public void getOutsets(Rect outOutsetRect) { 8040 if (mAttachInfo != null) { 8041 outOutsetRect.set(mAttachInfo.mOutsets); 8042 } else { 8043 outOutsetRect.setEmpty(); 8044 } 8045 } 8046 8047 /** 8048 * Returns the visibility status for this view. 8049 * 8050 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 8051 * @attr ref android.R.styleable#View_visibility 8052 */ 8053 @ViewDebug.ExportedProperty(mapping = { 8054 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 8055 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 8056 @ViewDebug.IntToString(from = GONE, to = "GONE") 8057 }) 8058 @Visibility getVisibility()8059 public int getVisibility() { 8060 return mViewFlags & VISIBILITY_MASK; 8061 } 8062 8063 /** 8064 * Set the enabled state of this view. 8065 * 8066 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 8067 * @attr ref android.R.styleable#View_visibility 8068 */ 8069 @RemotableViewMethod setVisibility(@isibility int visibility)8070 public void setVisibility(@Visibility int visibility) { 8071 setFlags(visibility, VISIBILITY_MASK); 8072 } 8073 8074 /** 8075 * Returns the enabled status for this view. The interpretation of the 8076 * enabled state varies by subclass. 8077 * 8078 * @return True if this view is enabled, false otherwise. 8079 */ 8080 @ViewDebug.ExportedProperty isEnabled()8081 public boolean isEnabled() { 8082 return (mViewFlags & ENABLED_MASK) == ENABLED; 8083 } 8084 8085 /** 8086 * Set the enabled state of this view. The interpretation of the enabled 8087 * state varies by subclass. 8088 * 8089 * @param enabled True if this view is enabled, false otherwise. 8090 */ 8091 @RemotableViewMethod setEnabled(boolean enabled)8092 public void setEnabled(boolean enabled) { 8093 if (enabled == isEnabled()) return; 8094 8095 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 8096 8097 /* 8098 * The View most likely has to change its appearance, so refresh 8099 * the drawable state. 8100 */ 8101 refreshDrawableState(); 8102 8103 // Invalidate too, since the default behavior for views is to be 8104 // be drawn at 50% alpha rather than to change the drawable. 8105 invalidate(true); 8106 8107 if (!enabled) { 8108 cancelPendingInputEvents(); 8109 } 8110 } 8111 8112 /** 8113 * Set whether this view can receive the focus. 8114 * 8115 * Setting this to false will also ensure that this view is not focusable 8116 * in touch mode. 8117 * 8118 * @param focusable If true, this view can receive the focus. 8119 * 8120 * @see #setFocusableInTouchMode(boolean) 8121 * @attr ref android.R.styleable#View_focusable 8122 */ setFocusable(boolean focusable)8123 public void setFocusable(boolean focusable) { 8124 if (!focusable) { 8125 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 8126 } 8127 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 8128 } 8129 8130 /** 8131 * Set whether this view can receive focus while in touch mode. 8132 * 8133 * Setting this to true will also ensure that this view is focusable. 8134 * 8135 * @param focusableInTouchMode If true, this view can receive the focus while 8136 * in touch mode. 8137 * 8138 * @see #setFocusable(boolean) 8139 * @attr ref android.R.styleable#View_focusableInTouchMode 8140 */ setFocusableInTouchMode(boolean focusableInTouchMode)8141 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 8142 // Focusable in touch mode should always be set before the focusable flag 8143 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 8144 // which, in touch mode, will not successfully request focus on this view 8145 // because the focusable in touch mode flag is not set 8146 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 8147 if (focusableInTouchMode) { 8148 setFlags(FOCUSABLE, FOCUSABLE_MASK); 8149 } 8150 } 8151 8152 /** 8153 * Set whether this view should have sound effects enabled for events such as 8154 * clicking and touching. 8155 * 8156 * <p>You may wish to disable sound effects for a view if you already play sounds, 8157 * for instance, a dial key that plays dtmf tones. 8158 * 8159 * @param soundEffectsEnabled whether sound effects are enabled for this view. 8160 * @see #isSoundEffectsEnabled() 8161 * @see #playSoundEffect(int) 8162 * @attr ref android.R.styleable#View_soundEffectsEnabled 8163 */ setSoundEffectsEnabled(boolean soundEffectsEnabled)8164 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 8165 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 8166 } 8167 8168 /** 8169 * @return whether this view should have sound effects enabled for events such as 8170 * clicking and touching. 8171 * 8172 * @see #setSoundEffectsEnabled(boolean) 8173 * @see #playSoundEffect(int) 8174 * @attr ref android.R.styleable#View_soundEffectsEnabled 8175 */ 8176 @ViewDebug.ExportedProperty isSoundEffectsEnabled()8177 public boolean isSoundEffectsEnabled() { 8178 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 8179 } 8180 8181 /** 8182 * Set whether this view should have haptic feedback for events such as 8183 * long presses. 8184 * 8185 * <p>You may wish to disable haptic feedback if your view already controls 8186 * its own haptic feedback. 8187 * 8188 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 8189 * @see #isHapticFeedbackEnabled() 8190 * @see #performHapticFeedback(int) 8191 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 8192 */ setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)8193 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 8194 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 8195 } 8196 8197 /** 8198 * @return whether this view should have haptic feedback enabled for events 8199 * long presses. 8200 * 8201 * @see #setHapticFeedbackEnabled(boolean) 8202 * @see #performHapticFeedback(int) 8203 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 8204 */ 8205 @ViewDebug.ExportedProperty isHapticFeedbackEnabled()8206 public boolean isHapticFeedbackEnabled() { 8207 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 8208 } 8209 8210 /** 8211 * Returns the layout direction for this view. 8212 * 8213 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 8214 * {@link #LAYOUT_DIRECTION_RTL}, 8215 * {@link #LAYOUT_DIRECTION_INHERIT} or 8216 * {@link #LAYOUT_DIRECTION_LOCALE}. 8217 * 8218 * @attr ref android.R.styleable#View_layoutDirection 8219 * 8220 * @hide 8221 */ 8222 @ViewDebug.ExportedProperty(category = "layout", mapping = { 8223 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 8224 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 8225 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 8226 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 8227 }) 8228 @LayoutDir getRawLayoutDirection()8229 public int getRawLayoutDirection() { 8230 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 8231 } 8232 8233 /** 8234 * Set the layout direction for this view. This will propagate a reset of layout direction 8235 * resolution to the view's children and resolve layout direction for this view. 8236 * 8237 * @param layoutDirection the layout direction to set. Should be one of: 8238 * 8239 * {@link #LAYOUT_DIRECTION_LTR}, 8240 * {@link #LAYOUT_DIRECTION_RTL}, 8241 * {@link #LAYOUT_DIRECTION_INHERIT}, 8242 * {@link #LAYOUT_DIRECTION_LOCALE}. 8243 * 8244 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 8245 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 8246 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 8247 * 8248 * @attr ref android.R.styleable#View_layoutDirection 8249 */ 8250 @RemotableViewMethod setLayoutDirection(@ayoutDir int layoutDirection)8251 public void setLayoutDirection(@LayoutDir int layoutDirection) { 8252 if (getRawLayoutDirection() != layoutDirection) { 8253 // Reset the current layout direction and the resolved one 8254 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 8255 resetRtlProperties(); 8256 // Set the new layout direction (filtered) 8257 mPrivateFlags2 |= 8258 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 8259 // We need to resolve all RTL properties as they all depend on layout direction 8260 resolveRtlPropertiesIfNeeded(); 8261 requestLayout(); 8262 invalidate(true); 8263 } 8264 } 8265 8266 /** 8267 * Returns the resolved layout direction for this view. 8268 * 8269 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 8270 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 8271 * 8272 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 8273 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 8274 * 8275 * @attr ref android.R.styleable#View_layoutDirection 8276 */ 8277 @ViewDebug.ExportedProperty(category = "layout", mapping = { 8278 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 8279 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 8280 }) 8281 @ResolvedLayoutDir getLayoutDirection()8282 public int getLayoutDirection() { 8283 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 8284 if (targetSdkVersion < JELLY_BEAN_MR1) { 8285 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 8286 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 8287 } 8288 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 8289 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 8290 } 8291 8292 /** 8293 * Indicates whether or not this view's layout is right-to-left. This is resolved from 8294 * layout attribute and/or the inherited value from the parent 8295 * 8296 * @return true if the layout is right-to-left. 8297 * 8298 * @hide 8299 */ 8300 @ViewDebug.ExportedProperty(category = "layout") isLayoutRtl()8301 public boolean isLayoutRtl() { 8302 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 8303 } 8304 8305 /** 8306 * Indicates whether the view is currently tracking transient state that the 8307 * app should not need to concern itself with saving and restoring, but that 8308 * the framework should take special note to preserve when possible. 8309 * 8310 * <p>A view with transient state cannot be trivially rebound from an external 8311 * data source, such as an adapter binding item views in a list. This may be 8312 * because the view is performing an animation, tracking user selection 8313 * of content, or similar.</p> 8314 * 8315 * @return true if the view has transient state 8316 */ 8317 @ViewDebug.ExportedProperty(category = "layout") hasTransientState()8318 public boolean hasTransientState() { 8319 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 8320 } 8321 8322 /** 8323 * Set whether this view is currently tracking transient state that the 8324 * framework should attempt to preserve when possible. This flag is reference counted, 8325 * so every call to setHasTransientState(true) should be paired with a later call 8326 * to setHasTransientState(false). 8327 * 8328 * <p>A view with transient state cannot be trivially rebound from an external 8329 * data source, such as an adapter binding item views in a list. This may be 8330 * because the view is performing an animation, tracking user selection 8331 * of content, or similar.</p> 8332 * 8333 * @param hasTransientState true if this view has transient state 8334 */ setHasTransientState(boolean hasTransientState)8335 public void setHasTransientState(boolean hasTransientState) { 8336 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 8337 mTransientStateCount - 1; 8338 if (mTransientStateCount < 0) { 8339 mTransientStateCount = 0; 8340 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 8341 "unmatched pair of setHasTransientState calls"); 8342 } else if ((hasTransientState && mTransientStateCount == 1) || 8343 (!hasTransientState && mTransientStateCount == 0)) { 8344 // update flag if we've just incremented up from 0 or decremented down to 0 8345 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 8346 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 8347 if (mParent != null) { 8348 try { 8349 mParent.childHasTransientStateChanged(this, hasTransientState); 8350 } catch (AbstractMethodError e) { 8351 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 8352 " does not fully implement ViewParent", e); 8353 } 8354 } 8355 } 8356 } 8357 8358 /** 8359 * Returns true if this view is currently attached to a window. 8360 */ isAttachedToWindow()8361 public boolean isAttachedToWindow() { 8362 return mAttachInfo != null; 8363 } 8364 8365 /** 8366 * Returns true if this view has been through at least one layout since it 8367 * was last attached to or detached from a window. 8368 */ isLaidOut()8369 public boolean isLaidOut() { 8370 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 8371 } 8372 8373 /** 8374 * If this view doesn't do any drawing on its own, set this flag to 8375 * allow further optimizations. By default, this flag is not set on 8376 * View, but could be set on some View subclasses such as ViewGroup. 8377 * 8378 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 8379 * you should clear this flag. 8380 * 8381 * @param willNotDraw whether or not this View draw on its own 8382 */ setWillNotDraw(boolean willNotDraw)8383 public void setWillNotDraw(boolean willNotDraw) { 8384 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 8385 } 8386 8387 /** 8388 * Returns whether or not this View draws on its own. 8389 * 8390 * @return true if this view has nothing to draw, false otherwise 8391 */ 8392 @ViewDebug.ExportedProperty(category = "drawing") willNotDraw()8393 public boolean willNotDraw() { 8394 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 8395 } 8396 8397 /** 8398 * When a View's drawing cache is enabled, drawing is redirected to an 8399 * offscreen bitmap. Some views, like an ImageView, must be able to 8400 * bypass this mechanism if they already draw a single bitmap, to avoid 8401 * unnecessary usage of the memory. 8402 * 8403 * @param willNotCacheDrawing true if this view does not cache its 8404 * drawing, false otherwise 8405 */ setWillNotCacheDrawing(boolean willNotCacheDrawing)8406 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 8407 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 8408 } 8409 8410 /** 8411 * Returns whether or not this View can cache its drawing or not. 8412 * 8413 * @return true if this view does not cache its drawing, false otherwise 8414 */ 8415 @ViewDebug.ExportedProperty(category = "drawing") willNotCacheDrawing()8416 public boolean willNotCacheDrawing() { 8417 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 8418 } 8419 8420 /** 8421 * Indicates whether this view reacts to click events or not. 8422 * 8423 * @return true if the view is clickable, false otherwise 8424 * 8425 * @see #setClickable(boolean) 8426 * @attr ref android.R.styleable#View_clickable 8427 */ 8428 @ViewDebug.ExportedProperty isClickable()8429 public boolean isClickable() { 8430 return (mViewFlags & CLICKABLE) == CLICKABLE; 8431 } 8432 8433 /** 8434 * Enables or disables click events for this view. When a view 8435 * is clickable it will change its state to "pressed" on every click. 8436 * Subclasses should set the view clickable to visually react to 8437 * user's clicks. 8438 * 8439 * @param clickable true to make the view clickable, false otherwise 8440 * 8441 * @see #isClickable() 8442 * @attr ref android.R.styleable#View_clickable 8443 */ setClickable(boolean clickable)8444 public void setClickable(boolean clickable) { 8445 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 8446 } 8447 8448 /** 8449 * Indicates whether this view reacts to long click events or not. 8450 * 8451 * @return true if the view is long clickable, false otherwise 8452 * 8453 * @see #setLongClickable(boolean) 8454 * @attr ref android.R.styleable#View_longClickable 8455 */ isLongClickable()8456 public boolean isLongClickable() { 8457 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 8458 } 8459 8460 /** 8461 * Enables or disables long click events for this view. When a view is long 8462 * clickable it reacts to the user holding down the button for a longer 8463 * duration than a tap. This event can either launch the listener or a 8464 * context menu. 8465 * 8466 * @param longClickable true to make the view long clickable, false otherwise 8467 * @see #isLongClickable() 8468 * @attr ref android.R.styleable#View_longClickable 8469 */ setLongClickable(boolean longClickable)8470 public void setLongClickable(boolean longClickable) { 8471 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 8472 } 8473 8474 /** 8475 * Indicates whether this view reacts to context clicks or not. 8476 * 8477 * @return true if the view is context clickable, false otherwise 8478 * @see #setContextClickable(boolean) 8479 * @attr ref android.R.styleable#View_contextClickable 8480 */ isContextClickable()8481 public boolean isContextClickable() { 8482 return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 8483 } 8484 8485 /** 8486 * Enables or disables context clicking for this view. This event can launch the listener. 8487 * 8488 * @param contextClickable true to make the view react to a context click, false otherwise 8489 * @see #isContextClickable() 8490 * @attr ref android.R.styleable#View_contextClickable 8491 */ setContextClickable(boolean contextClickable)8492 public void setContextClickable(boolean contextClickable) { 8493 setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE); 8494 } 8495 8496 /** 8497 * Sets the pressed state for this view and provides a touch coordinate for 8498 * animation hinting. 8499 * 8500 * @param pressed Pass true to set the View's internal state to "pressed", 8501 * or false to reverts the View's internal state from a 8502 * previously set "pressed" state. 8503 * @param x The x coordinate of the touch that caused the press 8504 * @param y The y coordinate of the touch that caused the press 8505 */ setPressed(boolean pressed, float x, float y)8506 private void setPressed(boolean pressed, float x, float y) { 8507 if (pressed) { 8508 drawableHotspotChanged(x, y); 8509 } 8510 8511 setPressed(pressed); 8512 } 8513 8514 /** 8515 * Sets the pressed state for this view. 8516 * 8517 * @see #isClickable() 8518 * @see #setClickable(boolean) 8519 * 8520 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 8521 * the View's internal state from a previously set "pressed" state. 8522 */ setPressed(boolean pressed)8523 public void setPressed(boolean pressed) { 8524 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 8525 8526 if (pressed) { 8527 mPrivateFlags |= PFLAG_PRESSED; 8528 } else { 8529 mPrivateFlags &= ~PFLAG_PRESSED; 8530 } 8531 8532 if (needsRefresh) { 8533 refreshDrawableState(); 8534 } 8535 dispatchSetPressed(pressed); 8536 } 8537 8538 /** 8539 * Dispatch setPressed to all of this View's children. 8540 * 8541 * @see #setPressed(boolean) 8542 * 8543 * @param pressed The new pressed state 8544 */ dispatchSetPressed(boolean pressed)8545 protected void dispatchSetPressed(boolean pressed) { 8546 } 8547 8548 /** 8549 * Indicates whether the view is currently in pressed state. Unless 8550 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 8551 * the pressed state. 8552 * 8553 * @see #setPressed(boolean) 8554 * @see #isClickable() 8555 * @see #setClickable(boolean) 8556 * 8557 * @return true if the view is currently pressed, false otherwise 8558 */ 8559 @ViewDebug.ExportedProperty isPressed()8560 public boolean isPressed() { 8561 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 8562 } 8563 8564 /** 8565 * @hide 8566 * Indicates whether this view will participate in data collection through 8567 * {@link ViewStructure}. If true, it will not provide any data 8568 * for itself or its children. If false, the normal data collection will be allowed. 8569 * 8570 * @return Returns false if assist data collection is not blocked, else true. 8571 * 8572 * @see #setAssistBlocked(boolean) 8573 * @attr ref android.R.styleable#View_assistBlocked 8574 */ isAssistBlocked()8575 public boolean isAssistBlocked() { 8576 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0; 8577 } 8578 8579 /** 8580 * @hide 8581 * Controls whether assist data collection from this view and its children is enabled 8582 * (that is, whether {@link #onProvideStructure} and 8583 * {@link #onProvideVirtualStructure} will be called). The default value is false, 8584 * allowing normal assist collection. Setting this to false will disable assist collection. 8585 * 8586 * @param enabled Set to true to <em>disable</em> assist data collection, or false 8587 * (the default) to allow it. 8588 * 8589 * @see #isAssistBlocked() 8590 * @see #onProvideStructure 8591 * @see #onProvideVirtualStructure 8592 * @attr ref android.R.styleable#View_assistBlocked 8593 */ setAssistBlocked(boolean enabled)8594 public void setAssistBlocked(boolean enabled) { 8595 if (enabled) { 8596 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; 8597 } else { 8598 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED; 8599 } 8600 } 8601 8602 /** 8603 * Indicates whether this view will save its state (that is, 8604 * whether its {@link #onSaveInstanceState} method will be called). 8605 * 8606 * @return Returns true if the view state saving is enabled, else false. 8607 * 8608 * @see #setSaveEnabled(boolean) 8609 * @attr ref android.R.styleable#View_saveEnabled 8610 */ isSaveEnabled()8611 public boolean isSaveEnabled() { 8612 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 8613 } 8614 8615 /** 8616 * Controls whether the saving of this view's state is 8617 * enabled (that is, whether its {@link #onSaveInstanceState} method 8618 * will be called). Note that even if freezing is enabled, the 8619 * view still must have an id assigned to it (via {@link #setId(int)}) 8620 * for its state to be saved. This flag can only disable the 8621 * saving of this view; any child views may still have their state saved. 8622 * 8623 * @param enabled Set to false to <em>disable</em> state saving, or true 8624 * (the default) to allow it. 8625 * 8626 * @see #isSaveEnabled() 8627 * @see #setId(int) 8628 * @see #onSaveInstanceState() 8629 * @attr ref android.R.styleable#View_saveEnabled 8630 */ setSaveEnabled(boolean enabled)8631 public void setSaveEnabled(boolean enabled) { 8632 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 8633 } 8634 8635 /** 8636 * Gets whether the framework should discard touches when the view's 8637 * window is obscured by another visible window. 8638 * Refer to the {@link View} security documentation for more details. 8639 * 8640 * @return True if touch filtering is enabled. 8641 * 8642 * @see #setFilterTouchesWhenObscured(boolean) 8643 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8644 */ 8645 @ViewDebug.ExportedProperty getFilterTouchesWhenObscured()8646 public boolean getFilterTouchesWhenObscured() { 8647 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 8648 } 8649 8650 /** 8651 * Sets whether the framework should discard touches when the view's 8652 * window is obscured by another visible window. 8653 * Refer to the {@link View} security documentation for more details. 8654 * 8655 * @param enabled True if touch filtering should be enabled. 8656 * 8657 * @see #getFilterTouchesWhenObscured 8658 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8659 */ setFilterTouchesWhenObscured(boolean enabled)8660 public void setFilterTouchesWhenObscured(boolean enabled) { 8661 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 8662 FILTER_TOUCHES_WHEN_OBSCURED); 8663 } 8664 8665 /** 8666 * Indicates whether the entire hierarchy under this view will save its 8667 * state when a state saving traversal occurs from its parent. The default 8668 * is true; if false, these views will not be saved unless 8669 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8670 * 8671 * @return Returns true if the view state saving from parent is enabled, else false. 8672 * 8673 * @see #setSaveFromParentEnabled(boolean) 8674 */ isSaveFromParentEnabled()8675 public boolean isSaveFromParentEnabled() { 8676 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 8677 } 8678 8679 /** 8680 * Controls whether the entire hierarchy under this view will save its 8681 * state when a state saving traversal occurs from its parent. The default 8682 * is true; if false, these views will not be saved unless 8683 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8684 * 8685 * @param enabled Set to false to <em>disable</em> state saving, or true 8686 * (the default) to allow it. 8687 * 8688 * @see #isSaveFromParentEnabled() 8689 * @see #setId(int) 8690 * @see #onSaveInstanceState() 8691 */ setSaveFromParentEnabled(boolean enabled)8692 public void setSaveFromParentEnabled(boolean enabled) { 8693 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 8694 } 8695 8696 8697 /** 8698 * Returns whether this View is able to take focus. 8699 * 8700 * @return True if this view can take focus, or false otherwise. 8701 * @attr ref android.R.styleable#View_focusable 8702 */ 8703 @ViewDebug.ExportedProperty(category = "focus") isFocusable()8704 public final boolean isFocusable() { 8705 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 8706 } 8707 8708 /** 8709 * When a view is focusable, it may not want to take focus when in touch mode. 8710 * For example, a button would like focus when the user is navigating via a D-pad 8711 * so that the user can click on it, but once the user starts touching the screen, 8712 * the button shouldn't take focus 8713 * @return Whether the view is focusable in touch mode. 8714 * @attr ref android.R.styleable#View_focusableInTouchMode 8715 */ 8716 @ViewDebug.ExportedProperty isFocusableInTouchMode()8717 public final boolean isFocusableInTouchMode() { 8718 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 8719 } 8720 8721 /** 8722 * Find the nearest view in the specified direction that can take focus. 8723 * This does not actually give focus to that view. 8724 * 8725 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 8726 * 8727 * @return The nearest focusable in the specified direction, or null if none 8728 * can be found. 8729 */ focusSearch(@ocusRealDirection int direction)8730 public View focusSearch(@FocusRealDirection int direction) { 8731 if (mParent != null) { 8732 return mParent.focusSearch(this, direction); 8733 } else { 8734 return null; 8735 } 8736 } 8737 8738 /** 8739 * This method is the last chance for the focused view and its ancestors to 8740 * respond to an arrow key. This is called when the focused view did not 8741 * consume the key internally, nor could the view system find a new view in 8742 * the requested direction to give focus to. 8743 * 8744 * @param focused The currently focused view. 8745 * @param direction The direction focus wants to move. One of FOCUS_UP, 8746 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 8747 * @return True if the this view consumed this unhandled move. 8748 */ dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8749 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) { 8750 return false; 8751 } 8752 8753 /** 8754 * If a user manually specified the next view id for a particular direction, 8755 * use the root to look up the view. 8756 * @param root The root view of the hierarchy containing this view. 8757 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 8758 * or FOCUS_BACKWARD. 8759 * @return The user specified next view, or null if there is none. 8760 */ findUserSetNextFocus(View root, @FocusDirection int direction)8761 View findUserSetNextFocus(View root, @FocusDirection int direction) { 8762 switch (direction) { 8763 case FOCUS_LEFT: 8764 if (mNextFocusLeftId == View.NO_ID) return null; 8765 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 8766 case FOCUS_RIGHT: 8767 if (mNextFocusRightId == View.NO_ID) return null; 8768 return findViewInsideOutShouldExist(root, mNextFocusRightId); 8769 case FOCUS_UP: 8770 if (mNextFocusUpId == View.NO_ID) return null; 8771 return findViewInsideOutShouldExist(root, mNextFocusUpId); 8772 case FOCUS_DOWN: 8773 if (mNextFocusDownId == View.NO_ID) return null; 8774 return findViewInsideOutShouldExist(root, mNextFocusDownId); 8775 case FOCUS_FORWARD: 8776 if (mNextFocusForwardId == View.NO_ID) return null; 8777 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 8778 case FOCUS_BACKWARD: { 8779 if (mID == View.NO_ID) return null; 8780 final int id = mID; 8781 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 8782 @Override 8783 public boolean apply(View t) { 8784 return t.mNextFocusForwardId == id; 8785 } 8786 }); 8787 } 8788 } 8789 return null; 8790 } 8791 findViewInsideOutShouldExist(View root, int id)8792 private View findViewInsideOutShouldExist(View root, int id) { 8793 if (mMatchIdPredicate == null) { 8794 mMatchIdPredicate = new MatchIdPredicate(); 8795 } 8796 mMatchIdPredicate.mId = id; 8797 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 8798 if (result == null) { 8799 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 8800 } 8801 return result; 8802 } 8803 8804 /** 8805 * Find and return all focusable views that are descendants of this view, 8806 * possibly including this view if it is focusable itself. 8807 * 8808 * @param direction The direction of the focus 8809 * @return A list of focusable views 8810 */ getFocusables(@ocusDirection int direction)8811 public ArrayList<View> getFocusables(@FocusDirection int direction) { 8812 ArrayList<View> result = new ArrayList<View>(24); 8813 addFocusables(result, direction); 8814 return result; 8815 } 8816 8817 /** 8818 * Add any focusable views that are descendants of this view (possibly 8819 * including this view if it is focusable itself) to views. If we are in touch mode, 8820 * only add views that are also focusable in touch mode. 8821 * 8822 * @param views Focusable views found so far 8823 * @param direction The direction of the focus 8824 */ addFocusables(ArrayList<View> views, @FocusDirection int direction)8825 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) { 8826 addFocusables(views, direction, isInTouchMode() ? FOCUSABLES_TOUCH_MODE : FOCUSABLES_ALL); 8827 } 8828 8829 /** 8830 * Adds any focusable views that are descendants of this view (possibly 8831 * including this view if it is focusable itself) to views. This method 8832 * adds all focusable views regardless if we are in touch mode or 8833 * only views focusable in touch mode if we are in touch mode or 8834 * only views that can take accessibility focus if accessibility is enabled 8835 * depending on the focusable mode parameter. 8836 * 8837 * @param views Focusable views found so far or null if all we are interested is 8838 * the number of focusables. 8839 * @param direction The direction of the focus. 8840 * @param focusableMode The type of focusables to be added. 8841 * 8842 * @see #FOCUSABLES_ALL 8843 * @see #FOCUSABLES_TOUCH_MODE 8844 */ addFocusables(ArrayList<View> views, @FocusDirection int direction, @FocusableMode int focusableMode)8845 public void addFocusables(ArrayList<View> views, @FocusDirection int direction, 8846 @FocusableMode int focusableMode) { 8847 if (views == null) { 8848 return; 8849 } 8850 if (!isFocusable()) { 8851 return; 8852 } 8853 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 8854 && !isFocusableInTouchMode()) { 8855 return; 8856 } 8857 views.add(this); 8858 } 8859 8860 /** 8861 * Finds the Views that contain given text. The containment is case insensitive. 8862 * The search is performed by either the text that the View renders or the content 8863 * description that describes the view for accessibility purposes and the view does 8864 * not render or both. Clients can specify how the search is to be performed via 8865 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 8866 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 8867 * 8868 * @param outViews The output list of matching Views. 8869 * @param searched The text to match against. 8870 * 8871 * @see #FIND_VIEWS_WITH_TEXT 8872 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 8873 * @see #setContentDescription(CharSequence) 8874 */ findViewsWithText(ArrayList<View> outViews, CharSequence searched, @FindViewFlags int flags)8875 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, 8876 @FindViewFlags int flags) { 8877 if (getAccessibilityNodeProvider() != null) { 8878 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 8879 outViews.add(this); 8880 } 8881 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 8882 && (searched != null && searched.length() > 0) 8883 && (mContentDescription != null && mContentDescription.length() > 0)) { 8884 String searchedLowerCase = searched.toString().toLowerCase(); 8885 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 8886 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 8887 outViews.add(this); 8888 } 8889 } 8890 } 8891 8892 /** 8893 * Find and return all touchable views that are descendants of this view, 8894 * possibly including this view if it is touchable itself. 8895 * 8896 * @return A list of touchable views 8897 */ getTouchables()8898 public ArrayList<View> getTouchables() { 8899 ArrayList<View> result = new ArrayList<View>(); 8900 addTouchables(result); 8901 return result; 8902 } 8903 8904 /** 8905 * Add any touchable views that are descendants of this view (possibly 8906 * including this view if it is touchable itself) to views. 8907 * 8908 * @param views Touchable views found so far 8909 */ addTouchables(ArrayList<View> views)8910 public void addTouchables(ArrayList<View> views) { 8911 final int viewFlags = mViewFlags; 8912 8913 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 8914 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) 8915 && (viewFlags & ENABLED_MASK) == ENABLED) { 8916 views.add(this); 8917 } 8918 } 8919 8920 /** 8921 * Returns whether this View is accessibility focused. 8922 * 8923 * @return True if this View is accessibility focused. 8924 */ isAccessibilityFocused()8925 public boolean isAccessibilityFocused() { 8926 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 8927 } 8928 8929 /** 8930 * Call this to try to give accessibility focus to this view. 8931 * 8932 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 8933 * returns false or the view is no visible or the view already has accessibility 8934 * focus. 8935 * 8936 * See also {@link #focusSearch(int)}, which is what you call to say that you 8937 * have focus, and you want your parent to look for the next one. 8938 * 8939 * @return Whether this view actually took accessibility focus. 8940 * 8941 * @hide 8942 */ requestAccessibilityFocus()8943 public boolean requestAccessibilityFocus() { 8944 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 8945 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 8946 return false; 8947 } 8948 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 8949 return false; 8950 } 8951 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 8952 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 8953 ViewRootImpl viewRootImpl = getViewRootImpl(); 8954 if (viewRootImpl != null) { 8955 viewRootImpl.setAccessibilityFocus(this, null); 8956 } 8957 invalidate(); 8958 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 8959 return true; 8960 } 8961 return false; 8962 } 8963 8964 /** 8965 * Call this to try to clear accessibility focus of this view. 8966 * 8967 * See also {@link #focusSearch(int)}, which is what you call to say that you 8968 * have focus, and you want your parent to look for the next one. 8969 * 8970 * @hide 8971 */ clearAccessibilityFocus()8972 public void clearAccessibilityFocus() { 8973 clearAccessibilityFocusNoCallbacks(0); 8974 8975 // Clear the global reference of accessibility focus if this view or 8976 // any of its descendants had accessibility focus. This will NOT send 8977 // an event or update internal state if focus is cleared from a 8978 // descendant view, which may leave views in inconsistent states. 8979 final ViewRootImpl viewRootImpl = getViewRootImpl(); 8980 if (viewRootImpl != null) { 8981 final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 8982 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 8983 viewRootImpl.setAccessibilityFocus(null, null); 8984 } 8985 } 8986 } 8987 sendAccessibilityHoverEvent(int eventType)8988 private void sendAccessibilityHoverEvent(int eventType) { 8989 // Since we are not delivering to a client accessibility events from not 8990 // important views (unless the clinet request that) we need to fire the 8991 // event from the deepest view exposed to the client. As a consequence if 8992 // the user crosses a not exposed view the client will see enter and exit 8993 // of the exposed predecessor followed by and enter and exit of that same 8994 // predecessor when entering and exiting the not exposed descendant. This 8995 // is fine since the client has a clear idea which view is hovered at the 8996 // price of a couple more events being sent. This is a simple and 8997 // working solution. 8998 View source = this; 8999 while (true) { 9000 if (source.includeForAccessibility()) { 9001 source.sendAccessibilityEvent(eventType); 9002 return; 9003 } 9004 ViewParent parent = source.getParent(); 9005 if (parent instanceof View) { 9006 source = (View) parent; 9007 } else { 9008 return; 9009 } 9010 } 9011 } 9012 9013 /** 9014 * Clears accessibility focus without calling any callback methods 9015 * normally invoked in {@link #clearAccessibilityFocus()}. This method 9016 * is used separately from that one for clearing accessibility focus when 9017 * giving this focus to another view. 9018 * 9019 * @param action The action, if any, that led to focus being cleared. Set to 9020 * AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS to specify that focus is moving within 9021 * the window. 9022 */ clearAccessibilityFocusNoCallbacks(int action)9023 void clearAccessibilityFocusNoCallbacks(int action) { 9024 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 9025 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 9026 invalidate(); 9027 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 9028 AccessibilityEvent event = AccessibilityEvent.obtain( 9029 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 9030 event.setAction(action); 9031 if (mAccessibilityDelegate != null) { 9032 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 9033 } else { 9034 sendAccessibilityEventUnchecked(event); 9035 } 9036 } 9037 } 9038 } 9039 9040 /** 9041 * Call this to try to give focus to a specific view or to one of its 9042 * descendants. 9043 * 9044 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 9045 * false), or if it is focusable and it is not focusable in touch mode 9046 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 9047 * 9048 * See also {@link #focusSearch(int)}, which is what you call to say that you 9049 * have focus, and you want your parent to look for the next one. 9050 * 9051 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 9052 * {@link #FOCUS_DOWN} and <code>null</code>. 9053 * 9054 * @return Whether this view or one of its descendants actually took focus. 9055 */ requestFocus()9056 public final boolean requestFocus() { 9057 return requestFocus(View.FOCUS_DOWN); 9058 } 9059 9060 /** 9061 * Call this to try to give focus to a specific view or to one of its 9062 * descendants and give it a hint about what direction focus is heading. 9063 * 9064 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 9065 * false), or if it is focusable and it is not focusable in touch mode 9066 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 9067 * 9068 * See also {@link #focusSearch(int)}, which is what you call to say that you 9069 * have focus, and you want your parent to look for the next one. 9070 * 9071 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 9072 * <code>null</code> set for the previously focused rectangle. 9073 * 9074 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 9075 * @return Whether this view or one of its descendants actually took focus. 9076 */ requestFocus(int direction)9077 public final boolean requestFocus(int direction) { 9078 return requestFocus(direction, null); 9079 } 9080 9081 /** 9082 * Call this to try to give focus to a specific view or to one of its descendants 9083 * and give it hints about the direction and a specific rectangle that the focus 9084 * is coming from. The rectangle can help give larger views a finer grained hint 9085 * about where focus is coming from, and therefore, where to show selection, or 9086 * forward focus change internally. 9087 * 9088 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 9089 * false), or if it is focusable and it is not focusable in touch mode 9090 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 9091 * 9092 * A View will not take focus if it is not visible. 9093 * 9094 * A View will not take focus if one of its parents has 9095 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 9096 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 9097 * 9098 * See also {@link #focusSearch(int)}, which is what you call to say that you 9099 * have focus, and you want your parent to look for the next one. 9100 * 9101 * You may wish to override this method if your custom {@link View} has an internal 9102 * {@link View} that it wishes to forward the request to. 9103 * 9104 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 9105 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 9106 * to give a finer grained hint about where focus is coming from. May be null 9107 * if there is no hint. 9108 * @return Whether this view or one of its descendants actually took focus. 9109 */ requestFocus(int direction, Rect previouslyFocusedRect)9110 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 9111 return requestFocusNoSearch(direction, previouslyFocusedRect); 9112 } 9113 requestFocusNoSearch(int direction, Rect previouslyFocusedRect)9114 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 9115 // need to be focusable 9116 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 9117 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 9118 return false; 9119 } 9120 9121 // need to be focusable in touch mode if in touch mode 9122 if (isInTouchMode() && 9123 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 9124 return false; 9125 } 9126 9127 // need to not have any parents blocking us 9128 if (hasAncestorThatBlocksDescendantFocus()) { 9129 return false; 9130 } 9131 9132 handleFocusGainInternal(direction, previouslyFocusedRect); 9133 return true; 9134 } 9135 9136 /** 9137 * Call this to try to give focus to a specific view or to one of its descendants. This is a 9138 * special variant of {@link #requestFocus() } that will allow views that are not focusable in 9139 * touch mode to request focus when they are touched. 9140 * 9141 * @return Whether this view or one of its descendants actually took focus. 9142 * 9143 * @see #isInTouchMode() 9144 * 9145 */ requestFocusFromTouch()9146 public final boolean requestFocusFromTouch() { 9147 // Leave touch mode if we need to 9148 if (isInTouchMode()) { 9149 ViewRootImpl viewRoot = getViewRootImpl(); 9150 if (viewRoot != null) { 9151 viewRoot.ensureTouchMode(false); 9152 } 9153 } 9154 return requestFocus(View.FOCUS_DOWN); 9155 } 9156 9157 /** 9158 * @return Whether any ancestor of this view blocks descendant focus. 9159 */ hasAncestorThatBlocksDescendantFocus()9160 private boolean hasAncestorThatBlocksDescendantFocus() { 9161 final boolean focusableInTouchMode = isFocusableInTouchMode(); 9162 ViewParent ancestor = mParent; 9163 while (ancestor instanceof ViewGroup) { 9164 final ViewGroup vgAncestor = (ViewGroup) ancestor; 9165 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS 9166 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) { 9167 return true; 9168 } else { 9169 ancestor = vgAncestor.getParent(); 9170 } 9171 } 9172 return false; 9173 } 9174 9175 /** 9176 * Gets the mode for determining whether this View is important for accessibility 9177 * which is if it fires accessibility events and if it is reported to 9178 * accessibility services that query the screen. 9179 * 9180 * @return The mode for determining whether a View is important for accessibility. 9181 * 9182 * @attr ref android.R.styleable#View_importantForAccessibility 9183 * 9184 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 9185 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 9186 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 9187 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 9188 */ 9189 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 9190 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 9191 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 9192 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 9193 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 9194 to = "noHideDescendants") 9195 }) getImportantForAccessibility()9196 public int getImportantForAccessibility() { 9197 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 9198 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 9199 } 9200 9201 /** 9202 * Sets the live region mode for this view. This indicates to accessibility 9203 * services whether they should automatically notify the user about changes 9204 * to the view's content description or text, or to the content descriptions 9205 * or text of the view's children (where applicable). 9206 * <p> 9207 * For example, in a login screen with a TextView that displays an "incorrect 9208 * password" notification, that view should be marked as a live region with 9209 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 9210 * <p> 9211 * To disable change notifications for this view, use 9212 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 9213 * mode for most views. 9214 * <p> 9215 * To indicate that the user should be notified of changes, use 9216 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 9217 * <p> 9218 * If the view's changes should interrupt ongoing speech and notify the user 9219 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 9220 * 9221 * @param mode The live region mode for this view, one of: 9222 * <ul> 9223 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 9224 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 9225 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 9226 * </ul> 9227 * @attr ref android.R.styleable#View_accessibilityLiveRegion 9228 */ setAccessibilityLiveRegion(int mode)9229 public void setAccessibilityLiveRegion(int mode) { 9230 if (mode != getAccessibilityLiveRegion()) { 9231 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 9232 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 9233 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 9234 notifyViewAccessibilityStateChangedIfNeeded( 9235 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9236 } 9237 } 9238 9239 /** 9240 * Gets the live region mode for this View. 9241 * 9242 * @return The live region mode for the view. 9243 * 9244 * @attr ref android.R.styleable#View_accessibilityLiveRegion 9245 * 9246 * @see #setAccessibilityLiveRegion(int) 9247 */ getAccessibilityLiveRegion()9248 public int getAccessibilityLiveRegion() { 9249 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 9250 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 9251 } 9252 9253 /** 9254 * Sets how to determine whether this view is important for accessibility 9255 * which is if it fires accessibility events and if it is reported to 9256 * accessibility services that query the screen. 9257 * 9258 * @param mode How to determine whether this view is important for accessibility. 9259 * 9260 * @attr ref android.R.styleable#View_importantForAccessibility 9261 * 9262 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 9263 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 9264 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 9265 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 9266 */ setImportantForAccessibility(int mode)9267 public void setImportantForAccessibility(int mode) { 9268 final int oldMode = getImportantForAccessibility(); 9269 if (mode != oldMode) { 9270 final boolean hideDescendants = 9271 mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; 9272 9273 // If this node or its descendants are no longer important, try to 9274 // clear accessibility focus. 9275 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) { 9276 final View focusHost = findAccessibilityFocusHost(hideDescendants); 9277 if (focusHost != null) { 9278 focusHost.clearAccessibilityFocus(); 9279 } 9280 } 9281 9282 // If we're moving between AUTO and another state, we might not need 9283 // to send a subtree changed notification. We'll store the computed 9284 // importance, since we'll need to check it later to make sure. 9285 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 9286 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 9287 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 9288 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 9289 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 9290 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 9291 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 9292 notifySubtreeAccessibilityStateChangedIfNeeded(); 9293 } else { 9294 notifyViewAccessibilityStateChangedIfNeeded( 9295 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9296 } 9297 } 9298 } 9299 9300 /** 9301 * Returns the view within this view's hierarchy that is hosting 9302 * accessibility focus. 9303 * 9304 * @param searchDescendants whether to search for focus in descendant views 9305 * @return the view hosting accessibility focus, or {@code null} 9306 */ findAccessibilityFocusHost(boolean searchDescendants)9307 private View findAccessibilityFocusHost(boolean searchDescendants) { 9308 if (isAccessibilityFocusedViewOrHost()) { 9309 return this; 9310 } 9311 9312 if (searchDescendants) { 9313 final ViewRootImpl viewRoot = getViewRootImpl(); 9314 if (viewRoot != null) { 9315 final View focusHost = viewRoot.getAccessibilityFocusedHost(); 9316 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 9317 return focusHost; 9318 } 9319 } 9320 } 9321 9322 return null; 9323 } 9324 9325 /** 9326 * Computes whether this view should be exposed for accessibility. In 9327 * general, views that are interactive or provide information are exposed 9328 * while views that serve only as containers are hidden. 9329 * <p> 9330 * If an ancestor of this view has importance 9331 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method 9332 * returns <code>false</code>. 9333 * <p> 9334 * Otherwise, the value is computed according to the view's 9335 * {@link #getImportantForAccessibility()} value: 9336 * <ol> 9337 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or 9338 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false 9339 * </code> 9340 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code> 9341 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if 9342 * view satisfies any of the following: 9343 * <ul> 9344 * <li>Is actionable, e.g. {@link #isClickable()}, 9345 * {@link #isLongClickable()}, or {@link #isFocusable()} 9346 * <li>Has an {@link AccessibilityDelegate} 9347 * <li>Has an interaction listener, e.g. {@link OnTouchListener}, 9348 * {@link OnKeyListener}, etc. 9349 * <li>Is an accessibility live region, e.g. 9350 * {@link #getAccessibilityLiveRegion()} is not 9351 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. 9352 * </ul> 9353 * </ol> 9354 * 9355 * @return Whether the view is exposed for accessibility. 9356 * @see #setImportantForAccessibility(int) 9357 * @see #getImportantForAccessibility() 9358 */ isImportantForAccessibility()9359 public boolean isImportantForAccessibility() { 9360 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 9361 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 9362 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 9363 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 9364 return false; 9365 } 9366 9367 // Check parent mode to ensure we're not hidden. 9368 ViewParent parent = mParent; 9369 while (parent instanceof View) { 9370 if (((View) parent).getImportantForAccessibility() 9371 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 9372 return false; 9373 } 9374 parent = parent.getParent(); 9375 } 9376 9377 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 9378 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 9379 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE; 9380 } 9381 9382 /** 9383 * Gets the parent for accessibility purposes. Note that the parent for 9384 * accessibility is not necessary the immediate parent. It is the first 9385 * predecessor that is important for accessibility. 9386 * 9387 * @return The parent for accessibility purposes. 9388 */ getParentForAccessibility()9389 public ViewParent getParentForAccessibility() { 9390 if (mParent instanceof View) { 9391 View parentView = (View) mParent; 9392 if (parentView.includeForAccessibility()) { 9393 return mParent; 9394 } else { 9395 return mParent.getParentForAccessibility(); 9396 } 9397 } 9398 return null; 9399 } 9400 9401 /** 9402 * Adds the children of this View relevant for accessibility to the given list 9403 * as output. Since some Views are not important for accessibility the added 9404 * child views are not necessarily direct children of this view, rather they are 9405 * the first level of descendants important for accessibility. 9406 * 9407 * @param outChildren The output list that will receive children for accessibility. 9408 */ addChildrenForAccessibility(ArrayList<View> outChildren)9409 public void addChildrenForAccessibility(ArrayList<View> outChildren) { 9410 9411 } 9412 9413 /** 9414 * Whether to regard this view for accessibility. A view is regarded for 9415 * accessibility if it is important for accessibility or the querying 9416 * accessibility service has explicitly requested that view not 9417 * important for accessibility are regarded. 9418 * 9419 * @return Whether to regard the view for accessibility. 9420 * 9421 * @hide 9422 */ includeForAccessibility()9423 public boolean includeForAccessibility() { 9424 if (mAttachInfo != null) { 9425 return (mAttachInfo.mAccessibilityFetchFlags 9426 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 9427 || isImportantForAccessibility(); 9428 } 9429 return false; 9430 } 9431 9432 /** 9433 * Returns whether the View is considered actionable from 9434 * accessibility perspective. Such view are important for 9435 * accessibility. 9436 * 9437 * @return True if the view is actionable for accessibility. 9438 * 9439 * @hide 9440 */ isActionableForAccessibility()9441 public boolean isActionableForAccessibility() { 9442 return (isClickable() || isLongClickable() || isFocusable()); 9443 } 9444 9445 /** 9446 * Returns whether the View has registered callbacks which makes it 9447 * important for accessibility. 9448 * 9449 * @return True if the view is actionable for accessibility. 9450 */ hasListenersForAccessibility()9451 private boolean hasListenersForAccessibility() { 9452 ListenerInfo info = getListenerInfo(); 9453 return mTouchDelegate != null || info.mOnKeyListener != null 9454 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 9455 || info.mOnHoverListener != null || info.mOnDragListener != null; 9456 } 9457 9458 /** 9459 * Notifies that the accessibility state of this view changed. The change 9460 * is local to this view and does not represent structural changes such 9461 * as children and parent. For example, the view became focusable. The 9462 * notification is at at most once every 9463 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9464 * to avoid unnecessary load to the system. Also once a view has a pending 9465 * notification this method is a NOP until the notification has been sent. 9466 * 9467 * @hide 9468 */ notifyViewAccessibilityStateChangedIfNeeded(int changeType)9469 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 9470 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9471 return; 9472 } 9473 if (mSendViewStateChangedAccessibilityEvent == null) { 9474 mSendViewStateChangedAccessibilityEvent = 9475 new SendViewStateChangedAccessibilityEvent(); 9476 } 9477 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType); 9478 } 9479 9480 /** 9481 * Notifies that the accessibility state of this view changed. The change 9482 * is *not* local to this view and does represent structural changes such 9483 * as children and parent. For example, the view size changed. The 9484 * notification is at at most once every 9485 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9486 * to avoid unnecessary load to the system. Also once a view has a pending 9487 * notification this method is a NOP until the notification has been sent. 9488 * 9489 * @hide 9490 */ notifySubtreeAccessibilityStateChangedIfNeeded()9491 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 9492 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9493 return; 9494 } 9495 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 9496 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9497 if (mParent != null) { 9498 try { 9499 mParent.notifySubtreeAccessibilityStateChanged( 9500 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 9501 } catch (AbstractMethodError e) { 9502 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 9503 " does not fully implement ViewParent", e); 9504 } 9505 } 9506 } 9507 } 9508 9509 /** 9510 * Change the visibility of the View without triggering any other changes. This is 9511 * important for transitions, where visibility changes should not adjust focus or 9512 * trigger a new layout. This is only used when the visibility has already been changed 9513 * and we need a transient value during an animation. When the animation completes, 9514 * the original visibility value is always restored. 9515 * 9516 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 9517 * @hide 9518 */ setTransitionVisibility(@isibility int visibility)9519 public void setTransitionVisibility(@Visibility int visibility) { 9520 mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility; 9521 } 9522 9523 /** 9524 * Reset the flag indicating the accessibility state of the subtree rooted 9525 * at this view changed. 9526 */ resetSubtreeAccessibilityStateChanged()9527 void resetSubtreeAccessibilityStateChanged() { 9528 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9529 } 9530 9531 /** 9532 * Report an accessibility action to this view's parents for delegated processing. 9533 * 9534 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally 9535 * call this method to delegate an accessibility action to a supporting parent. If the parent 9536 * returns true from its 9537 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} 9538 * method this method will return true to signify that the action was consumed.</p> 9539 * 9540 * <p>This method is useful for implementing nested scrolling child views. If 9541 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action 9542 * a custom view implementation may invoke this method to allow a parent to consume the 9543 * scroll first. If this method returns true the custom view should skip its own scrolling 9544 * behavior.</p> 9545 * 9546 * @param action Accessibility action to delegate 9547 * @param arguments Optional action arguments 9548 * @return true if the action was consumed by a parent 9549 */ dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments)9550 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) { 9551 for (ViewParent p = getParent(); p != null; p = p.getParent()) { 9552 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) { 9553 return true; 9554 } 9555 } 9556 return false; 9557 } 9558 9559 /** 9560 * Performs the specified accessibility action on the view. For 9561 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 9562 * <p> 9563 * If an {@link AccessibilityDelegate} has been specified via calling 9564 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 9565 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 9566 * is responsible for handling this call. 9567 * </p> 9568 * 9569 * <p>The default implementation will delegate 9570 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and 9571 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if 9572 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p> 9573 * 9574 * @param action The action to perform. 9575 * @param arguments Optional action arguments. 9576 * @return Whether the action was performed. 9577 */ performAccessibilityAction(int action, Bundle arguments)9578 public boolean performAccessibilityAction(int action, Bundle arguments) { 9579 if (mAccessibilityDelegate != null) { 9580 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 9581 } else { 9582 return performAccessibilityActionInternal(action, arguments); 9583 } 9584 } 9585 9586 /** 9587 * @see #performAccessibilityAction(int, Bundle) 9588 * 9589 * Note: Called from the default {@link AccessibilityDelegate}. 9590 * 9591 * @hide 9592 */ performAccessibilityActionInternal(int action, Bundle arguments)9593 public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 9594 if (isNestedScrollingEnabled() 9595 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD 9596 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD 9597 || action == R.id.accessibilityActionScrollUp 9598 || action == R.id.accessibilityActionScrollLeft 9599 || action == R.id.accessibilityActionScrollDown 9600 || action == R.id.accessibilityActionScrollRight)) { 9601 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { 9602 return true; 9603 } 9604 } 9605 9606 switch (action) { 9607 case AccessibilityNodeInfo.ACTION_CLICK: { 9608 if (isClickable()) { 9609 performClick(); 9610 return true; 9611 } 9612 } break; 9613 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 9614 if (isLongClickable()) { 9615 performLongClick(); 9616 return true; 9617 } 9618 } break; 9619 case AccessibilityNodeInfo.ACTION_FOCUS: { 9620 if (!hasFocus()) { 9621 // Get out of touch mode since accessibility 9622 // wants to move focus around. 9623 getViewRootImpl().ensureTouchMode(false); 9624 return requestFocus(); 9625 } 9626 } break; 9627 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 9628 if (hasFocus()) { 9629 clearFocus(); 9630 return !isFocused(); 9631 } 9632 } break; 9633 case AccessibilityNodeInfo.ACTION_SELECT: { 9634 if (!isSelected()) { 9635 setSelected(true); 9636 return isSelected(); 9637 } 9638 } break; 9639 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 9640 if (isSelected()) { 9641 setSelected(false); 9642 return !isSelected(); 9643 } 9644 } break; 9645 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 9646 if (!isAccessibilityFocused()) { 9647 return requestAccessibilityFocus(); 9648 } 9649 } break; 9650 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 9651 if (isAccessibilityFocused()) { 9652 clearAccessibilityFocus(); 9653 return true; 9654 } 9655 } break; 9656 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 9657 if (arguments != null) { 9658 final int granularity = arguments.getInt( 9659 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9660 final boolean extendSelection = arguments.getBoolean( 9661 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9662 return traverseAtGranularity(granularity, true, extendSelection); 9663 } 9664 } break; 9665 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 9666 if (arguments != null) { 9667 final int granularity = arguments.getInt( 9668 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9669 final boolean extendSelection = arguments.getBoolean( 9670 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9671 return traverseAtGranularity(granularity, false, extendSelection); 9672 } 9673 } break; 9674 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 9675 CharSequence text = getIterableTextForAccessibility(); 9676 if (text == null) { 9677 return false; 9678 } 9679 final int start = (arguments != null) ? arguments.getInt( 9680 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 9681 final int end = (arguments != null) ? arguments.getInt( 9682 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 9683 // Only cursor position can be specified (selection length == 0) 9684 if ((getAccessibilitySelectionStart() != start 9685 || getAccessibilitySelectionEnd() != end) 9686 && (start == end)) { 9687 setAccessibilitySelection(start, end); 9688 notifyViewAccessibilityStateChangedIfNeeded( 9689 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9690 return true; 9691 } 9692 } break; 9693 case R.id.accessibilityActionShowOnScreen: { 9694 if (mAttachInfo != null) { 9695 final Rect r = mAttachInfo.mTmpInvalRect; 9696 getDrawingRect(r); 9697 return requestRectangleOnScreen(r, true); 9698 } 9699 } break; 9700 case R.id.accessibilityActionContextClick: { 9701 if (isContextClickable()) { 9702 performContextClick(); 9703 return true; 9704 } 9705 } break; 9706 } 9707 return false; 9708 } 9709 traverseAtGranularity(int granularity, boolean forward, boolean extendSelection)9710 private boolean traverseAtGranularity(int granularity, boolean forward, 9711 boolean extendSelection) { 9712 CharSequence text = getIterableTextForAccessibility(); 9713 if (text == null || text.length() == 0) { 9714 return false; 9715 } 9716 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 9717 if (iterator == null) { 9718 return false; 9719 } 9720 int current = getAccessibilitySelectionEnd(); 9721 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9722 current = forward ? 0 : text.length(); 9723 } 9724 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 9725 if (range == null) { 9726 return false; 9727 } 9728 final int segmentStart = range[0]; 9729 final int segmentEnd = range[1]; 9730 int selectionStart; 9731 int selectionEnd; 9732 if (extendSelection && isAccessibilitySelectionExtendable()) { 9733 selectionStart = getAccessibilitySelectionStart(); 9734 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9735 selectionStart = forward ? segmentStart : segmentEnd; 9736 } 9737 selectionEnd = forward ? segmentEnd : segmentStart; 9738 } else { 9739 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 9740 } 9741 setAccessibilitySelection(selectionStart, selectionEnd); 9742 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 9743 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 9744 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 9745 return true; 9746 } 9747 9748 /** 9749 * Gets the text reported for accessibility purposes. 9750 * 9751 * @return The accessibility text. 9752 * 9753 * @hide 9754 */ getIterableTextForAccessibility()9755 public CharSequence getIterableTextForAccessibility() { 9756 return getContentDescription(); 9757 } 9758 9759 /** 9760 * Gets whether accessibility selection can be extended. 9761 * 9762 * @return If selection is extensible. 9763 * 9764 * @hide 9765 */ isAccessibilitySelectionExtendable()9766 public boolean isAccessibilitySelectionExtendable() { 9767 return false; 9768 } 9769 9770 /** 9771 * @hide 9772 */ getAccessibilitySelectionStart()9773 public int getAccessibilitySelectionStart() { 9774 return mAccessibilityCursorPosition; 9775 } 9776 9777 /** 9778 * @hide 9779 */ getAccessibilitySelectionEnd()9780 public int getAccessibilitySelectionEnd() { 9781 return getAccessibilitySelectionStart(); 9782 } 9783 9784 /** 9785 * @hide 9786 */ setAccessibilitySelection(int start, int end)9787 public void setAccessibilitySelection(int start, int end) { 9788 if (start == end && end == mAccessibilityCursorPosition) { 9789 return; 9790 } 9791 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 9792 mAccessibilityCursorPosition = start; 9793 } else { 9794 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 9795 } 9796 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 9797 } 9798 sendViewTextTraversedAtGranularityEvent(int action, int granularity, int fromIndex, int toIndex)9799 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 9800 int fromIndex, int toIndex) { 9801 if (mParent == null) { 9802 return; 9803 } 9804 AccessibilityEvent event = AccessibilityEvent.obtain( 9805 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 9806 onInitializeAccessibilityEvent(event); 9807 onPopulateAccessibilityEvent(event); 9808 event.setFromIndex(fromIndex); 9809 event.setToIndex(toIndex); 9810 event.setAction(action); 9811 event.setMovementGranularity(granularity); 9812 mParent.requestSendAccessibilityEvent(this, event); 9813 } 9814 9815 /** 9816 * @hide 9817 */ getIteratorForGranularity(int granularity)9818 public TextSegmentIterator getIteratorForGranularity(int granularity) { 9819 switch (granularity) { 9820 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 9821 CharSequence text = getIterableTextForAccessibility(); 9822 if (text != null && text.length() > 0) { 9823 CharacterTextSegmentIterator iterator = 9824 CharacterTextSegmentIterator.getInstance( 9825 mContext.getResources().getConfiguration().locale); 9826 iterator.initialize(text.toString()); 9827 return iterator; 9828 } 9829 } break; 9830 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 9831 CharSequence text = getIterableTextForAccessibility(); 9832 if (text != null && text.length() > 0) { 9833 WordTextSegmentIterator iterator = 9834 WordTextSegmentIterator.getInstance( 9835 mContext.getResources().getConfiguration().locale); 9836 iterator.initialize(text.toString()); 9837 return iterator; 9838 } 9839 } break; 9840 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 9841 CharSequence text = getIterableTextForAccessibility(); 9842 if (text != null && text.length() > 0) { 9843 ParagraphTextSegmentIterator iterator = 9844 ParagraphTextSegmentIterator.getInstance(); 9845 iterator.initialize(text.toString()); 9846 return iterator; 9847 } 9848 } break; 9849 } 9850 return null; 9851 } 9852 9853 /** 9854 * Tells whether the {@link View} is in the state between {@link #onStartTemporaryDetach()} 9855 * and {@link #onFinishTemporaryDetach()}. 9856 * 9857 * <p>This method always returns {@code true} when called directly or indirectly from 9858 * {@link #onStartTemporaryDetach()}. The return value when called directly or indirectly from 9859 * {@link #onFinishTemporaryDetach()}, however, depends on the OS version. 9860 * <ul> 9861 * <li>{@code true} on {@link android.os.Build.VERSION_CODES#N API 24}</li> 9862 * <li>{@code false} on {@link android.os.Build.VERSION_CODES#N_MR1 API 25}} and later</li> 9863 * </ul> 9864 * </p> 9865 * 9866 * @return {@code true} when the View is in the state between {@link #onStartTemporaryDetach()} 9867 * and {@link #onFinishTemporaryDetach()}. 9868 */ isTemporarilyDetached()9869 public final boolean isTemporarilyDetached() { 9870 return (mPrivateFlags3 & PFLAG3_TEMPORARY_DETACH) != 0; 9871 } 9872 9873 /** 9874 * Dispatch {@link #onStartTemporaryDetach()} to this View and its direct children if this is 9875 * a container View. 9876 */ 9877 @CallSuper dispatchStartTemporaryDetach()9878 public void dispatchStartTemporaryDetach() { 9879 mPrivateFlags3 |= PFLAG3_TEMPORARY_DETACH; 9880 onStartTemporaryDetach(); 9881 } 9882 9883 /** 9884 * This is called when a container is going to temporarily detach a child, with 9885 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 9886 * It will either be followed by {@link #onFinishTemporaryDetach()} or 9887 * {@link #onDetachedFromWindow()} when the container is done. 9888 */ onStartTemporaryDetach()9889 public void onStartTemporaryDetach() { 9890 removeUnsetPressCallback(); 9891 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 9892 } 9893 9894 /** 9895 * Dispatch {@link #onFinishTemporaryDetach()} to this View and its direct children if this is 9896 * a container View. 9897 */ 9898 @CallSuper dispatchFinishTemporaryDetach()9899 public void dispatchFinishTemporaryDetach() { 9900 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 9901 onFinishTemporaryDetach(); 9902 if (hasWindowFocus() && hasFocus()) { 9903 InputMethodManager.getInstance().focusIn(this); 9904 } 9905 } 9906 9907 /** 9908 * Called after {@link #onStartTemporaryDetach} when the container is done 9909 * changing the view. 9910 */ onFinishTemporaryDetach()9911 public void onFinishTemporaryDetach() { 9912 } 9913 9914 /** 9915 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 9916 * for this view's window. Returns null if the view is not currently attached 9917 * to the window. Normally you will not need to use this directly, but 9918 * just use the standard high-level event callbacks like 9919 * {@link #onKeyDown(int, KeyEvent)}. 9920 */ getKeyDispatcherState()9921 public KeyEvent.DispatcherState getKeyDispatcherState() { 9922 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 9923 } 9924 9925 /** 9926 * Dispatch a key event before it is processed by any input method 9927 * associated with the view hierarchy. This can be used to intercept 9928 * key events in special situations before the IME consumes them; a 9929 * typical example would be handling the BACK key to update the application's 9930 * UI instead of allowing the IME to see it and close itself. 9931 * 9932 * @param event The key event to be dispatched. 9933 * @return True if the event was handled, false otherwise. 9934 */ dispatchKeyEventPreIme(KeyEvent event)9935 public boolean dispatchKeyEventPreIme(KeyEvent event) { 9936 return onKeyPreIme(event.getKeyCode(), event); 9937 } 9938 9939 /** 9940 * Dispatch a key event to the next view on the focus path. This path runs 9941 * from the top of the view tree down to the currently focused view. If this 9942 * view has focus, it will dispatch to itself. Otherwise it will dispatch 9943 * the next node down the focus path. This method also fires any key 9944 * listeners. 9945 * 9946 * @param event The key event to be dispatched. 9947 * @return True if the event was handled, false otherwise. 9948 */ dispatchKeyEvent(KeyEvent event)9949 public boolean dispatchKeyEvent(KeyEvent event) { 9950 if (mInputEventConsistencyVerifier != null) { 9951 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 9952 } 9953 9954 // Give any attached key listener a first crack at the event. 9955 //noinspection SimplifiableIfStatement 9956 ListenerInfo li = mListenerInfo; 9957 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 9958 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 9959 return true; 9960 } 9961 9962 if (event.dispatch(this, mAttachInfo != null 9963 ? mAttachInfo.mKeyDispatchState : null, this)) { 9964 return true; 9965 } 9966 9967 if (mInputEventConsistencyVerifier != null) { 9968 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9969 } 9970 return false; 9971 } 9972 9973 /** 9974 * Dispatches a key shortcut event. 9975 * 9976 * @param event The key event to be dispatched. 9977 * @return True if the event was handled by the view, false otherwise. 9978 */ dispatchKeyShortcutEvent(KeyEvent event)9979 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 9980 return onKeyShortcut(event.getKeyCode(), event); 9981 } 9982 9983 /** 9984 * Pass the touch screen motion event down to the target view, or this 9985 * view if it is the target. 9986 * 9987 * @param event The motion event to be dispatched. 9988 * @return True if the event was handled by the view, false otherwise. 9989 */ dispatchTouchEvent(MotionEvent event)9990 public boolean dispatchTouchEvent(MotionEvent event) { 9991 // If the event should be handled by accessibility focus first. 9992 if (event.isTargetAccessibilityFocus()) { 9993 // We don't have focus or no virtual descendant has it, do not handle the event. 9994 if (!isAccessibilityFocusedViewOrHost()) { 9995 return false; 9996 } 9997 // We have focus and got the event, then use normal event dispatch. 9998 event.setTargetAccessibilityFocus(false); 9999 } 10000 10001 boolean result = false; 10002 10003 if (mInputEventConsistencyVerifier != null) { 10004 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 10005 } 10006 10007 final int actionMasked = event.getActionMasked(); 10008 if (actionMasked == MotionEvent.ACTION_DOWN) { 10009 // Defensive cleanup for new gesture 10010 stopNestedScroll(); 10011 } 10012 10013 if (onFilterTouchEventForSecurity(event)) { 10014 if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { 10015 result = true; 10016 } 10017 //noinspection SimplifiableIfStatement 10018 ListenerInfo li = mListenerInfo; 10019 if (li != null && li.mOnTouchListener != null 10020 && (mViewFlags & ENABLED_MASK) == ENABLED 10021 && li.mOnTouchListener.onTouch(this, event)) { 10022 result = true; 10023 } 10024 10025 if (!result && onTouchEvent(event)) { 10026 result = true; 10027 } 10028 } 10029 10030 if (!result && mInputEventConsistencyVerifier != null) { 10031 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 10032 } 10033 10034 // Clean up after nested scrolls if this is the end of a gesture; 10035 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest 10036 // of the gesture. 10037 if (actionMasked == MotionEvent.ACTION_UP || 10038 actionMasked == MotionEvent.ACTION_CANCEL || 10039 (actionMasked == MotionEvent.ACTION_DOWN && !result)) { 10040 stopNestedScroll(); 10041 } 10042 10043 return result; 10044 } 10045 isAccessibilityFocusedViewOrHost()10046 boolean isAccessibilityFocusedViewOrHost() { 10047 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl() 10048 .getAccessibilityFocusedHost() == this); 10049 } 10050 10051 /** 10052 * Filter the touch event to apply security policies. 10053 * 10054 * @param event The motion event to be filtered. 10055 * @return True if the event should be dispatched, false if the event should be dropped. 10056 * 10057 * @see #getFilterTouchesWhenObscured 10058 */ onFilterTouchEventForSecurity(MotionEvent event)10059 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 10060 //noinspection RedundantIfStatement 10061 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 10062 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 10063 // Window is obscured, drop this touch. 10064 return false; 10065 } 10066 return true; 10067 } 10068 10069 /** 10070 * Pass a trackball motion event down to the focused view. 10071 * 10072 * @param event The motion event to be dispatched. 10073 * @return True if the event was handled by the view, false otherwise. 10074 */ dispatchTrackballEvent(MotionEvent event)10075 public boolean dispatchTrackballEvent(MotionEvent event) { 10076 if (mInputEventConsistencyVerifier != null) { 10077 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 10078 } 10079 10080 return onTrackballEvent(event); 10081 } 10082 10083 /** 10084 * Dispatch a generic motion event. 10085 * <p> 10086 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 10087 * are delivered to the view under the pointer. All other generic motion events are 10088 * delivered to the focused view. Hover events are handled specially and are delivered 10089 * to {@link #onHoverEvent(MotionEvent)}. 10090 * </p> 10091 * 10092 * @param event The motion event to be dispatched. 10093 * @return True if the event was handled by the view, false otherwise. 10094 */ dispatchGenericMotionEvent(MotionEvent event)10095 public boolean dispatchGenericMotionEvent(MotionEvent event) { 10096 if (mInputEventConsistencyVerifier != null) { 10097 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 10098 } 10099 10100 final int source = event.getSource(); 10101 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 10102 final int action = event.getAction(); 10103 if (action == MotionEvent.ACTION_HOVER_ENTER 10104 || action == MotionEvent.ACTION_HOVER_MOVE 10105 || action == MotionEvent.ACTION_HOVER_EXIT) { 10106 if (dispatchHoverEvent(event)) { 10107 return true; 10108 } 10109 } else if (dispatchGenericPointerEvent(event)) { 10110 return true; 10111 } 10112 } else if (dispatchGenericFocusedEvent(event)) { 10113 return true; 10114 } 10115 10116 if (dispatchGenericMotionEventInternal(event)) { 10117 return true; 10118 } 10119 10120 if (mInputEventConsistencyVerifier != null) { 10121 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 10122 } 10123 return false; 10124 } 10125 dispatchGenericMotionEventInternal(MotionEvent event)10126 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 10127 //noinspection SimplifiableIfStatement 10128 ListenerInfo li = mListenerInfo; 10129 if (li != null && li.mOnGenericMotionListener != null 10130 && (mViewFlags & ENABLED_MASK) == ENABLED 10131 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 10132 return true; 10133 } 10134 10135 if (onGenericMotionEvent(event)) { 10136 return true; 10137 } 10138 10139 final int actionButton = event.getActionButton(); 10140 switch (event.getActionMasked()) { 10141 case MotionEvent.ACTION_BUTTON_PRESS: 10142 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress 10143 && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 10144 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 10145 if (performContextClick(event.getX(), event.getY())) { 10146 mInContextButtonPress = true; 10147 setPressed(true, event.getX(), event.getY()); 10148 removeTapCallback(); 10149 removeLongPressCallback(); 10150 return true; 10151 } 10152 } 10153 break; 10154 10155 case MotionEvent.ACTION_BUTTON_RELEASE: 10156 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 10157 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 10158 mInContextButtonPress = false; 10159 mIgnoreNextUpEvent = true; 10160 } 10161 break; 10162 } 10163 10164 if (mInputEventConsistencyVerifier != null) { 10165 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 10166 } 10167 return false; 10168 } 10169 10170 /** 10171 * Dispatch a hover event. 10172 * <p> 10173 * Do not call this method directly. 10174 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10175 * </p> 10176 * 10177 * @param event The motion event to be dispatched. 10178 * @return True if the event was handled by the view, false otherwise. 10179 */ dispatchHoverEvent(MotionEvent event)10180 protected boolean dispatchHoverEvent(MotionEvent event) { 10181 ListenerInfo li = mListenerInfo; 10182 //noinspection SimplifiableIfStatement 10183 if (li != null && li.mOnHoverListener != null 10184 && (mViewFlags & ENABLED_MASK) == ENABLED 10185 && li.mOnHoverListener.onHover(this, event)) { 10186 return true; 10187 } 10188 10189 return onHoverEvent(event); 10190 } 10191 10192 /** 10193 * Returns true if the view has a child to which it has recently sent 10194 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 10195 * it does not have a hovered child, then it must be the innermost hovered view. 10196 * @hide 10197 */ hasHoveredChild()10198 protected boolean hasHoveredChild() { 10199 return false; 10200 } 10201 10202 /** 10203 * Dispatch a generic motion event to the view under the first pointer. 10204 * <p> 10205 * Do not call this method directly. 10206 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10207 * </p> 10208 * 10209 * @param event The motion event to be dispatched. 10210 * @return True if the event was handled by the view, false otherwise. 10211 */ dispatchGenericPointerEvent(MotionEvent event)10212 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 10213 return false; 10214 } 10215 10216 /** 10217 * Dispatch a generic motion event to the currently focused view. 10218 * <p> 10219 * Do not call this method directly. 10220 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 10221 * </p> 10222 * 10223 * @param event The motion event to be dispatched. 10224 * @return True if the event was handled by the view, false otherwise. 10225 */ dispatchGenericFocusedEvent(MotionEvent event)10226 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 10227 return false; 10228 } 10229 10230 /** 10231 * Dispatch a pointer event. 10232 * <p> 10233 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 10234 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 10235 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 10236 * and should not be expected to handle other pointing device features. 10237 * </p> 10238 * 10239 * @param event The motion event to be dispatched. 10240 * @return True if the event was handled by the view, false otherwise. 10241 * @hide 10242 */ dispatchPointerEvent(MotionEvent event)10243 public final boolean dispatchPointerEvent(MotionEvent event) { 10244 if (event.isTouchEvent()) { 10245 return dispatchTouchEvent(event); 10246 } else { 10247 return dispatchGenericMotionEvent(event); 10248 } 10249 } 10250 10251 /** 10252 * Called when the window containing this view gains or loses window focus. 10253 * ViewGroups should override to route to their children. 10254 * 10255 * @param hasFocus True if the window containing this view now has focus, 10256 * false otherwise. 10257 */ dispatchWindowFocusChanged(boolean hasFocus)10258 public void dispatchWindowFocusChanged(boolean hasFocus) { 10259 onWindowFocusChanged(hasFocus); 10260 } 10261 10262 /** 10263 * Called when the window containing this view gains or loses focus. Note 10264 * that this is separate from view focus: to receive key events, both 10265 * your view and its window must have focus. If a window is displayed 10266 * on top of yours that takes input focus, then your own window will lose 10267 * focus but the view focus will remain unchanged. 10268 * 10269 * @param hasWindowFocus True if the window containing this view now has 10270 * focus, false otherwise. 10271 */ onWindowFocusChanged(boolean hasWindowFocus)10272 public void onWindowFocusChanged(boolean hasWindowFocus) { 10273 InputMethodManager imm = InputMethodManager.peekInstance(); 10274 if (!hasWindowFocus) { 10275 if (isPressed()) { 10276 setPressed(false); 10277 } 10278 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 10279 imm.focusOut(this); 10280 } 10281 removeLongPressCallback(); 10282 removeTapCallback(); 10283 onFocusLost(); 10284 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 10285 imm.focusIn(this); 10286 } 10287 refreshDrawableState(); 10288 } 10289 10290 /** 10291 * Returns true if this view is in a window that currently has window focus. 10292 * Note that this is not the same as the view itself having focus. 10293 * 10294 * @return True if this view is in a window that currently has window focus. 10295 */ hasWindowFocus()10296 public boolean hasWindowFocus() { 10297 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 10298 } 10299 10300 /** 10301 * Dispatch a view visibility change down the view hierarchy. 10302 * ViewGroups should override to route to their children. 10303 * @param changedView The view whose visibility changed. Could be 'this' or 10304 * an ancestor view. 10305 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 10306 * {@link #INVISIBLE} or {@link #GONE}. 10307 */ dispatchVisibilityChanged(@onNull View changedView, @Visibility int visibility)10308 protected void dispatchVisibilityChanged(@NonNull View changedView, 10309 @Visibility int visibility) { 10310 onVisibilityChanged(changedView, visibility); 10311 } 10312 10313 /** 10314 * Called when the visibility of the view or an ancestor of the view has 10315 * changed. 10316 * 10317 * @param changedView The view whose visibility changed. May be 10318 * {@code this} or an ancestor view. 10319 * @param visibility The new visibility, one of {@link #VISIBLE}, 10320 * {@link #INVISIBLE} or {@link #GONE}. 10321 */ onVisibilityChanged(@onNull View changedView, @Visibility int visibility)10322 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { 10323 } 10324 10325 /** 10326 * Dispatch a hint about whether this view is displayed. For instance, when 10327 * a View moves out of the screen, it might receives a display hint indicating 10328 * the view is not displayed. Applications should not <em>rely</em> on this hint 10329 * as there is no guarantee that they will receive one. 10330 * 10331 * @param hint A hint about whether or not this view is displayed: 10332 * {@link #VISIBLE} or {@link #INVISIBLE}. 10333 */ dispatchDisplayHint(@isibility int hint)10334 public void dispatchDisplayHint(@Visibility int hint) { 10335 onDisplayHint(hint); 10336 } 10337 10338 /** 10339 * Gives this view a hint about whether is displayed or not. For instance, when 10340 * a View moves out of the screen, it might receives a display hint indicating 10341 * the view is not displayed. Applications should not <em>rely</em> on this hint 10342 * as there is no guarantee that they will receive one. 10343 * 10344 * @param hint A hint about whether or not this view is displayed: 10345 * {@link #VISIBLE} or {@link #INVISIBLE}. 10346 */ onDisplayHint(@isibility int hint)10347 protected void onDisplayHint(@Visibility int hint) { 10348 } 10349 10350 /** 10351 * Dispatch a window visibility change down the view hierarchy. 10352 * ViewGroups should override to route to their children. 10353 * 10354 * @param visibility The new visibility of the window. 10355 * 10356 * @see #onWindowVisibilityChanged(int) 10357 */ dispatchWindowVisibilityChanged(@isibility int visibility)10358 public void dispatchWindowVisibilityChanged(@Visibility int visibility) { 10359 onWindowVisibilityChanged(visibility); 10360 } 10361 10362 /** 10363 * Called when the window containing has change its visibility 10364 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 10365 * that this tells you whether or not your window is being made visible 10366 * to the window manager; this does <em>not</em> tell you whether or not 10367 * your window is obscured by other windows on the screen, even if it 10368 * is itself visible. 10369 * 10370 * @param visibility The new visibility of the window. 10371 */ onWindowVisibilityChanged(@isibility int visibility)10372 protected void onWindowVisibilityChanged(@Visibility int visibility) { 10373 if (visibility == VISIBLE) { 10374 initialAwakenScrollBars(); 10375 } 10376 } 10377 10378 /** 10379 * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by 10380 * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, 10381 * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}. 10382 * 10383 * @param isVisible true if this view's visibility to the user is uninterrupted by its 10384 * ancestors or by window visibility 10385 * @return true if this view is visible to the user, not counting clipping or overlapping 10386 */ dispatchVisibilityAggregated(boolean isVisible)10387 boolean dispatchVisibilityAggregated(boolean isVisible) { 10388 final boolean thisVisible = getVisibility() == VISIBLE; 10389 // If we're not visible but something is telling us we are, ignore it. 10390 if (thisVisible || !isVisible) { 10391 onVisibilityAggregated(isVisible); 10392 } 10393 return thisVisible && isVisible; 10394 } 10395 10396 /** 10397 * Called when the user-visibility of this View is potentially affected by a change 10398 * to this view itself, an ancestor view or the window this view is attached to. 10399 * 10400 * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE} 10401 * and this view's window is also visible 10402 */ 10403 @CallSuper onVisibilityAggregated(boolean isVisible)10404 public void onVisibilityAggregated(boolean isVisible) { 10405 if (isVisible && mAttachInfo != null) { 10406 initialAwakenScrollBars(); 10407 } 10408 10409 final Drawable dr = mBackground; 10410 if (dr != null && isVisible != dr.isVisible()) { 10411 dr.setVisible(isVisible, false); 10412 } 10413 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 10414 if (fg != null && isVisible != fg.isVisible()) { 10415 fg.setVisible(isVisible, false); 10416 } 10417 } 10418 10419 /** 10420 * Returns the current visibility of the window this view is attached to 10421 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 10422 * 10423 * @return Returns the current visibility of the view's window. 10424 */ 10425 @Visibility getWindowVisibility()10426 public int getWindowVisibility() { 10427 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 10428 } 10429 10430 /** 10431 * Retrieve the overall visible display size in which the window this view is 10432 * attached to has been positioned in. This takes into account screen 10433 * decorations above the window, for both cases where the window itself 10434 * is being position inside of them or the window is being placed under 10435 * then and covered insets are used for the window to position its content 10436 * inside. In effect, this tells you the available area where content can 10437 * be placed and remain visible to users. 10438 * 10439 * <p>This function requires an IPC back to the window manager to retrieve 10440 * the requested information, so should not be used in performance critical 10441 * code like drawing. 10442 * 10443 * @param outRect Filled in with the visible display frame. If the view 10444 * is not attached to a window, this is simply the raw display size. 10445 */ getWindowVisibleDisplayFrame(Rect outRect)10446 public void getWindowVisibleDisplayFrame(Rect outRect) { 10447 if (mAttachInfo != null) { 10448 try { 10449 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 10450 } catch (RemoteException e) { 10451 return; 10452 } 10453 // XXX This is really broken, and probably all needs to be done 10454 // in the window manager, and we need to know more about whether 10455 // we want the area behind or in front of the IME. 10456 final Rect insets = mAttachInfo.mVisibleInsets; 10457 outRect.left += insets.left; 10458 outRect.top += insets.top; 10459 outRect.right -= insets.right; 10460 outRect.bottom -= insets.bottom; 10461 return; 10462 } 10463 // The view is not attached to a display so we don't have a context. 10464 // Make a best guess about the display size. 10465 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 10466 d.getRectSize(outRect); 10467 } 10468 10469 /** 10470 * Like {@link #getWindowVisibleDisplayFrame}, but returns the "full" display frame this window 10471 * is currently in without any insets. 10472 * 10473 * @hide 10474 */ getWindowDisplayFrame(Rect outRect)10475 public void getWindowDisplayFrame(Rect outRect) { 10476 if (mAttachInfo != null) { 10477 try { 10478 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 10479 } catch (RemoteException e) { 10480 return; 10481 } 10482 return; 10483 } 10484 // The view is not attached to a display so we don't have a context. 10485 // Make a best guess about the display size. 10486 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 10487 d.getRectSize(outRect); 10488 } 10489 10490 /** 10491 * Dispatch a notification about a resource configuration change down 10492 * the view hierarchy. 10493 * ViewGroups should override to route to their children. 10494 * 10495 * @param newConfig The new resource configuration. 10496 * 10497 * @see #onConfigurationChanged(android.content.res.Configuration) 10498 */ dispatchConfigurationChanged(Configuration newConfig)10499 public void dispatchConfigurationChanged(Configuration newConfig) { 10500 onConfigurationChanged(newConfig); 10501 } 10502 10503 /** 10504 * Called when the current configuration of the resources being used 10505 * by the application have changed. You can use this to decide when 10506 * to reload resources that can changed based on orientation and other 10507 * configuration characteristics. You only need to use this if you are 10508 * not relying on the normal {@link android.app.Activity} mechanism of 10509 * recreating the activity instance upon a configuration change. 10510 * 10511 * @param newConfig The new resource configuration. 10512 */ onConfigurationChanged(Configuration newConfig)10513 protected void onConfigurationChanged(Configuration newConfig) { 10514 } 10515 10516 /** 10517 * Private function to aggregate all per-view attributes in to the view 10518 * root. 10519 */ dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility)10520 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10521 performCollectViewAttributes(attachInfo, visibility); 10522 } 10523 performCollectViewAttributes(AttachInfo attachInfo, int visibility)10524 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10525 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 10526 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 10527 attachInfo.mKeepScreenOn = true; 10528 } 10529 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 10530 ListenerInfo li = mListenerInfo; 10531 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 10532 attachInfo.mHasSystemUiListeners = true; 10533 } 10534 } 10535 } 10536 needGlobalAttributesUpdate(boolean force)10537 void needGlobalAttributesUpdate(boolean force) { 10538 final AttachInfo ai = mAttachInfo; 10539 if (ai != null && !ai.mRecomputeGlobalAttributes) { 10540 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 10541 || ai.mHasSystemUiListeners) { 10542 ai.mRecomputeGlobalAttributes = true; 10543 } 10544 } 10545 } 10546 10547 /** 10548 * Returns whether the device is currently in touch mode. Touch mode is entered 10549 * once the user begins interacting with the device by touch, and affects various 10550 * things like whether focus is always visible to the user. 10551 * 10552 * @return Whether the device is in touch mode. 10553 */ 10554 @ViewDebug.ExportedProperty isInTouchMode()10555 public boolean isInTouchMode() { 10556 if (mAttachInfo != null) { 10557 return mAttachInfo.mInTouchMode; 10558 } else { 10559 return ViewRootImpl.isInTouchMode(); 10560 } 10561 } 10562 10563 /** 10564 * Returns the context the view is running in, through which it can 10565 * access the current theme, resources, etc. 10566 * 10567 * @return The view's Context. 10568 */ 10569 @ViewDebug.CapturedViewProperty getContext()10570 public final Context getContext() { 10571 return mContext; 10572 } 10573 10574 /** 10575 * Handle a key event before it is processed by any input method 10576 * associated with the view hierarchy. This can be used to intercept 10577 * key events in special situations before the IME consumes them; a 10578 * typical example would be handling the BACK key to update the application's 10579 * UI instead of allowing the IME to see it and close itself. 10580 * 10581 * @param keyCode The value in event.getKeyCode(). 10582 * @param event Description of the key event. 10583 * @return If you handled the event, return true. If you want to allow the 10584 * event to be handled by the next receiver, return false. 10585 */ onKeyPreIme(int keyCode, KeyEvent event)10586 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 10587 return false; 10588 } 10589 10590 /** 10591 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 10592 * KeyEvent.Callback.onKeyDown()}: perform press of the view 10593 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 10594 * is released, if the view is enabled and clickable. 10595 * <p> 10596 * Key presses in software keyboards will generally NOT trigger this 10597 * listener, although some may elect to do so in some situations. Do not 10598 * rely on this to catch software key presses. 10599 * 10600 * @param keyCode a key code that represents the button pressed, from 10601 * {@link android.view.KeyEvent} 10602 * @param event the KeyEvent object that defines the button action 10603 */ onKeyDown(int keyCode, KeyEvent event)10604 public boolean onKeyDown(int keyCode, KeyEvent event) { 10605 if (KeyEvent.isConfirmKey(keyCode)) { 10606 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10607 return true; 10608 } 10609 10610 // Long clickable items don't necessarily have to be clickable. 10611 if (((mViewFlags & CLICKABLE) == CLICKABLE 10612 || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 10613 && (event.getRepeatCount() == 0)) { 10614 // For the purposes of menu anchoring and drawable hotspots, 10615 // key events are considered to be at the center of the view. 10616 final float x = getWidth() / 2f; 10617 final float y = getHeight() / 2f; 10618 setPressed(true, x, y); 10619 checkForLongClick(0, x, y); 10620 return true; 10621 } 10622 } 10623 10624 return false; 10625 } 10626 10627 /** 10628 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 10629 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 10630 * the event). 10631 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10632 * although some may elect to do so in some situations. Do not rely on this to 10633 * catch software key presses. 10634 */ onKeyLongPress(int keyCode, KeyEvent event)10635 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 10636 return false; 10637 } 10638 10639 /** 10640 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 10641 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 10642 * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER} 10643 * or {@link KeyEvent#KEYCODE_SPACE} is released. 10644 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10645 * although some may elect to do so in some situations. Do not rely on this to 10646 * catch software key presses. 10647 * 10648 * @param keyCode A key code that represents the button pressed, from 10649 * {@link android.view.KeyEvent}. 10650 * @param event The KeyEvent object that defines the button action. 10651 */ onKeyUp(int keyCode, KeyEvent event)10652 public boolean onKeyUp(int keyCode, KeyEvent event) { 10653 if (KeyEvent.isConfirmKey(keyCode)) { 10654 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10655 return true; 10656 } 10657 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 10658 setPressed(false); 10659 10660 if (!mHasPerformedLongPress) { 10661 // This is a tap, so remove the longpress check 10662 removeLongPressCallback(); 10663 return performClick(); 10664 } 10665 } 10666 } 10667 return false; 10668 } 10669 10670 /** 10671 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 10672 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 10673 * the event). 10674 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10675 * although some may elect to do so in some situations. Do not rely on this to 10676 * catch software key presses. 10677 * 10678 * @param keyCode A key code that represents the button pressed, from 10679 * {@link android.view.KeyEvent}. 10680 * @param repeatCount The number of times the action was made. 10681 * @param event The KeyEvent object that defines the button action. 10682 */ onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)10683 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 10684 return false; 10685 } 10686 10687 /** 10688 * Called on the focused view when a key shortcut event is not handled. 10689 * Override this method to implement local key shortcuts for the View. 10690 * Key shortcuts can also be implemented by setting the 10691 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 10692 * 10693 * @param keyCode The value in event.getKeyCode(). 10694 * @param event Description of the key event. 10695 * @return If you handled the event, return true. If you want to allow the 10696 * event to be handled by the next receiver, return false. 10697 */ onKeyShortcut(int keyCode, KeyEvent event)10698 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 10699 return false; 10700 } 10701 10702 /** 10703 * Check whether the called view is a text editor, in which case it 10704 * would make sense to automatically display a soft input window for 10705 * it. Subclasses should override this if they implement 10706 * {@link #onCreateInputConnection(EditorInfo)} to return true if 10707 * a call on that method would return a non-null InputConnection, and 10708 * they are really a first-class editor that the user would normally 10709 * start typing on when the go into a window containing your view. 10710 * 10711 * <p>The default implementation always returns false. This does 10712 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 10713 * will not be called or the user can not otherwise perform edits on your 10714 * view; it is just a hint to the system that this is not the primary 10715 * purpose of this view. 10716 * 10717 * @return Returns true if this view is a text editor, else false. 10718 */ onCheckIsTextEditor()10719 public boolean onCheckIsTextEditor() { 10720 return false; 10721 } 10722 10723 /** 10724 * Create a new InputConnection for an InputMethod to interact 10725 * with the view. The default implementation returns null, since it doesn't 10726 * support input methods. You can override this to implement such support. 10727 * This is only needed for views that take focus and text input. 10728 * 10729 * <p>When implementing this, you probably also want to implement 10730 * {@link #onCheckIsTextEditor()} to indicate you will return a 10731 * non-null InputConnection.</p> 10732 * 10733 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo} 10734 * object correctly and in its entirety, so that the connected IME can rely 10735 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart} 10736 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members 10737 * must be filled in with the correct cursor position for IMEs to work correctly 10738 * with your application.</p> 10739 * 10740 * @param outAttrs Fill in with attribute information about the connection. 10741 */ onCreateInputConnection(EditorInfo outAttrs)10742 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 10743 return null; 10744 } 10745 10746 /** 10747 * Called by the {@link android.view.inputmethod.InputMethodManager} 10748 * when a view who is not the current 10749 * input connection target is trying to make a call on the manager. The 10750 * default implementation returns false; you can override this to return 10751 * true for certain views if you are performing InputConnection proxying 10752 * to them. 10753 * @param view The View that is making the InputMethodManager call. 10754 * @return Return true to allow the call, false to reject. 10755 */ checkInputConnectionProxy(View view)10756 public boolean checkInputConnectionProxy(View view) { 10757 return false; 10758 } 10759 10760 /** 10761 * Show the context menu for this view. It is not safe to hold on to the 10762 * menu after returning from this method. 10763 * 10764 * You should normally not overload this method. Overload 10765 * {@link #onCreateContextMenu(ContextMenu)} or define an 10766 * {@link OnCreateContextMenuListener} to add items to the context menu. 10767 * 10768 * @param menu The context menu to populate 10769 */ createContextMenu(ContextMenu menu)10770 public void createContextMenu(ContextMenu menu) { 10771 ContextMenuInfo menuInfo = getContextMenuInfo(); 10772 10773 // Sets the current menu info so all items added to menu will have 10774 // my extra info set. 10775 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 10776 10777 onCreateContextMenu(menu); 10778 ListenerInfo li = mListenerInfo; 10779 if (li != null && li.mOnCreateContextMenuListener != null) { 10780 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 10781 } 10782 10783 // Clear the extra information so subsequent items that aren't mine don't 10784 // have my extra info. 10785 ((MenuBuilder)menu).setCurrentMenuInfo(null); 10786 10787 if (mParent != null) { 10788 mParent.createContextMenu(menu); 10789 } 10790 } 10791 10792 /** 10793 * Views should implement this if they have extra information to associate 10794 * with the context menu. The return result is supplied as a parameter to 10795 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 10796 * callback. 10797 * 10798 * @return Extra information about the item for which the context menu 10799 * should be shown. This information will vary across different 10800 * subclasses of View. 10801 */ getContextMenuInfo()10802 protected ContextMenuInfo getContextMenuInfo() { 10803 return null; 10804 } 10805 10806 /** 10807 * Views should implement this if the view itself is going to add items to 10808 * the context menu. 10809 * 10810 * @param menu the context menu to populate 10811 */ onCreateContextMenu(ContextMenu menu)10812 protected void onCreateContextMenu(ContextMenu menu) { 10813 } 10814 10815 /** 10816 * Implement this method to handle trackball motion events. The 10817 * <em>relative</em> movement of the trackball since the last event 10818 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 10819 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 10820 * that a movement of 1 corresponds to the user pressing one DPAD key (so 10821 * they will often be fractional values, representing the more fine-grained 10822 * movement information available from a trackball). 10823 * 10824 * @param event The motion event. 10825 * @return True if the event was handled, false otherwise. 10826 */ onTrackballEvent(MotionEvent event)10827 public boolean onTrackballEvent(MotionEvent event) { 10828 return false; 10829 } 10830 10831 /** 10832 * Implement this method to handle generic motion events. 10833 * <p> 10834 * Generic motion events describe joystick movements, mouse hovers, track pad 10835 * touches, scroll wheel movements and other input events. The 10836 * {@link MotionEvent#getSource() source} of the motion event specifies 10837 * the class of input that was received. Implementations of this method 10838 * must examine the bits in the source before processing the event. 10839 * The following code example shows how this is done. 10840 * </p><p> 10841 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 10842 * are delivered to the view under the pointer. All other generic motion events are 10843 * delivered to the focused view. 10844 * </p> 10845 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 10846 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 10847 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 10848 * // process the joystick movement... 10849 * return true; 10850 * } 10851 * } 10852 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 10853 * switch (event.getAction()) { 10854 * case MotionEvent.ACTION_HOVER_MOVE: 10855 * // process the mouse hover movement... 10856 * return true; 10857 * case MotionEvent.ACTION_SCROLL: 10858 * // process the scroll wheel movement... 10859 * return true; 10860 * } 10861 * } 10862 * return super.onGenericMotionEvent(event); 10863 * }</pre> 10864 * 10865 * @param event The generic motion event being processed. 10866 * @return True if the event was handled, false otherwise. 10867 */ onGenericMotionEvent(MotionEvent event)10868 public boolean onGenericMotionEvent(MotionEvent event) { 10869 return false; 10870 } 10871 10872 /** 10873 * Implement this method to handle hover events. 10874 * <p> 10875 * This method is called whenever a pointer is hovering into, over, or out of the 10876 * bounds of a view and the view is not currently being touched. 10877 * Hover events are represented as pointer events with action 10878 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 10879 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 10880 * </p> 10881 * <ul> 10882 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 10883 * when the pointer enters the bounds of the view.</li> 10884 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 10885 * when the pointer has already entered the bounds of the view and has moved.</li> 10886 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 10887 * when the pointer has exited the bounds of the view or when the pointer is 10888 * about to go down due to a button click, tap, or similar user action that 10889 * causes the view to be touched.</li> 10890 * </ul> 10891 * <p> 10892 * The view should implement this method to return true to indicate that it is 10893 * handling the hover event, such as by changing its drawable state. 10894 * </p><p> 10895 * The default implementation calls {@link #setHovered} to update the hovered state 10896 * of the view when a hover enter or hover exit event is received, if the view 10897 * is enabled and is clickable. The default implementation also sends hover 10898 * accessibility events. 10899 * </p> 10900 * 10901 * @param event The motion event that describes the hover. 10902 * @return True if the view handled the hover event. 10903 * 10904 * @see #isHovered 10905 * @see #setHovered 10906 * @see #onHoverChanged 10907 */ onHoverEvent(MotionEvent event)10908 public boolean onHoverEvent(MotionEvent event) { 10909 // The root view may receive hover (or touch) events that are outside the bounds of 10910 // the window. This code ensures that we only send accessibility events for 10911 // hovers that are actually within the bounds of the root view. 10912 final int action = event.getActionMasked(); 10913 if (!mSendingHoverAccessibilityEvents) { 10914 if ((action == MotionEvent.ACTION_HOVER_ENTER 10915 || action == MotionEvent.ACTION_HOVER_MOVE) 10916 && !hasHoveredChild() 10917 && pointInView(event.getX(), event.getY())) { 10918 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 10919 mSendingHoverAccessibilityEvents = true; 10920 } 10921 } else { 10922 if (action == MotionEvent.ACTION_HOVER_EXIT 10923 || (action == MotionEvent.ACTION_MOVE 10924 && !pointInView(event.getX(), event.getY()))) { 10925 mSendingHoverAccessibilityEvents = false; 10926 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 10927 } 10928 } 10929 10930 if ((action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_MOVE) 10931 && event.isFromSource(InputDevice.SOURCE_MOUSE) 10932 && isOnScrollbar(event.getX(), event.getY())) { 10933 awakenScrollBars(); 10934 } 10935 if (isHoverable()) { 10936 switch (action) { 10937 case MotionEvent.ACTION_HOVER_ENTER: 10938 setHovered(true); 10939 break; 10940 case MotionEvent.ACTION_HOVER_EXIT: 10941 setHovered(false); 10942 break; 10943 } 10944 10945 // Dispatch the event to onGenericMotionEvent before returning true. 10946 // This is to provide compatibility with existing applications that 10947 // handled HOVER_MOVE events in onGenericMotionEvent and that would 10948 // break because of the new default handling for hoverable views 10949 // in onHoverEvent. 10950 // Note that onGenericMotionEvent will be called by default when 10951 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 10952 dispatchGenericMotionEventInternal(event); 10953 // The event was already handled by calling setHovered(), so always 10954 // return true. 10955 return true; 10956 } 10957 10958 return false; 10959 } 10960 10961 /** 10962 * Returns true if the view should handle {@link #onHoverEvent} 10963 * by calling {@link #setHovered} to change its hovered state. 10964 * 10965 * @return True if the view is hoverable. 10966 */ isHoverable()10967 private boolean isHoverable() { 10968 final int viewFlags = mViewFlags; 10969 if ((viewFlags & ENABLED_MASK) == DISABLED) { 10970 return false; 10971 } 10972 10973 return (viewFlags & CLICKABLE) == CLICKABLE 10974 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 10975 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 10976 } 10977 10978 /** 10979 * Returns true if the view is currently hovered. 10980 * 10981 * @return True if the view is currently hovered. 10982 * 10983 * @see #setHovered 10984 * @see #onHoverChanged 10985 */ 10986 @ViewDebug.ExportedProperty isHovered()10987 public boolean isHovered() { 10988 return (mPrivateFlags & PFLAG_HOVERED) != 0; 10989 } 10990 10991 /** 10992 * Sets whether the view is currently hovered. 10993 * <p> 10994 * Calling this method also changes the drawable state of the view. This 10995 * enables the view to react to hover by using different drawable resources 10996 * to change its appearance. 10997 * </p><p> 10998 * The {@link #onHoverChanged} method is called when the hovered state changes. 10999 * </p> 11000 * 11001 * @param hovered True if the view is hovered. 11002 * 11003 * @see #isHovered 11004 * @see #onHoverChanged 11005 */ setHovered(boolean hovered)11006 public void setHovered(boolean hovered) { 11007 if (hovered) { 11008 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 11009 mPrivateFlags |= PFLAG_HOVERED; 11010 refreshDrawableState(); 11011 onHoverChanged(true); 11012 } 11013 } else { 11014 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 11015 mPrivateFlags &= ~PFLAG_HOVERED; 11016 refreshDrawableState(); 11017 onHoverChanged(false); 11018 } 11019 } 11020 } 11021 11022 /** 11023 * Implement this method to handle hover state changes. 11024 * <p> 11025 * This method is called whenever the hover state changes as a result of a 11026 * call to {@link #setHovered}. 11027 * </p> 11028 * 11029 * @param hovered The current hover state, as returned by {@link #isHovered}. 11030 * 11031 * @see #isHovered 11032 * @see #setHovered 11033 */ onHoverChanged(boolean hovered)11034 public void onHoverChanged(boolean hovered) { 11035 } 11036 11037 /** 11038 * Handles scroll bar dragging by mouse input. 11039 * 11040 * @hide 11041 * @param event The motion event. 11042 * 11043 * @return true if the event was handled as a scroll bar dragging, false otherwise. 11044 */ handleScrollBarDragging(MotionEvent event)11045 protected boolean handleScrollBarDragging(MotionEvent event) { 11046 if (mScrollCache == null) { 11047 return false; 11048 } 11049 final float x = event.getX(); 11050 final float y = event.getY(); 11051 final int action = event.getAction(); 11052 if ((mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING 11053 && action != MotionEvent.ACTION_DOWN) 11054 || !event.isFromSource(InputDevice.SOURCE_MOUSE) 11055 || !event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 11056 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 11057 return false; 11058 } 11059 11060 switch (action) { 11061 case MotionEvent.ACTION_MOVE: 11062 if (mScrollCache.mScrollBarDraggingState == ScrollabilityCache.NOT_DRAGGING) { 11063 return false; 11064 } 11065 if (mScrollCache.mScrollBarDraggingState 11066 == ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR) { 11067 final Rect bounds = mScrollCache.mScrollBarBounds; 11068 getVerticalScrollBarBounds(bounds); 11069 final int range = computeVerticalScrollRange(); 11070 final int offset = computeVerticalScrollOffset(); 11071 final int extent = computeVerticalScrollExtent(); 11072 11073 final int thumbLength = ScrollBarUtils.getThumbLength( 11074 bounds.height(), bounds.width(), extent, range); 11075 final int thumbOffset = ScrollBarUtils.getThumbOffset( 11076 bounds.height(), thumbLength, extent, range, offset); 11077 11078 final float diff = y - mScrollCache.mScrollBarDraggingPos; 11079 final float maxThumbOffset = bounds.height() - thumbLength; 11080 final float newThumbOffset = 11081 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 11082 final int height = getHeight(); 11083 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 11084 && height > 0 && extent > 0) { 11085 final int newY = Math.round((range - extent) 11086 / ((float)extent / height) * (newThumbOffset / maxThumbOffset)); 11087 if (newY != getScrollY()) { 11088 mScrollCache.mScrollBarDraggingPos = y; 11089 setScrollY(newY); 11090 } 11091 } 11092 return true; 11093 } 11094 if (mScrollCache.mScrollBarDraggingState 11095 == ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR) { 11096 final Rect bounds = mScrollCache.mScrollBarBounds; 11097 getHorizontalScrollBarBounds(bounds); 11098 final int range = computeHorizontalScrollRange(); 11099 final int offset = computeHorizontalScrollOffset(); 11100 final int extent = computeHorizontalScrollExtent(); 11101 11102 final int thumbLength = ScrollBarUtils.getThumbLength( 11103 bounds.width(), bounds.height(), extent, range); 11104 final int thumbOffset = ScrollBarUtils.getThumbOffset( 11105 bounds.width(), thumbLength, extent, range, offset); 11106 11107 final float diff = x - mScrollCache.mScrollBarDraggingPos; 11108 final float maxThumbOffset = bounds.width() - thumbLength; 11109 final float newThumbOffset = 11110 Math.min(Math.max(thumbOffset + diff, 0.0f), maxThumbOffset); 11111 final int width = getWidth(); 11112 if (Math.round(newThumbOffset) != thumbOffset && maxThumbOffset > 0 11113 && width > 0 && extent > 0) { 11114 final int newX = Math.round((range - extent) 11115 / ((float)extent / width) * (newThumbOffset / maxThumbOffset)); 11116 if (newX != getScrollX()) { 11117 mScrollCache.mScrollBarDraggingPos = x; 11118 setScrollX(newX); 11119 } 11120 } 11121 return true; 11122 } 11123 case MotionEvent.ACTION_DOWN: 11124 if (mScrollCache.state == ScrollabilityCache.OFF) { 11125 return false; 11126 } 11127 if (isOnVerticalScrollbarThumb(x, y)) { 11128 mScrollCache.mScrollBarDraggingState = 11129 ScrollabilityCache.DRAGGING_VERTICAL_SCROLL_BAR; 11130 mScrollCache.mScrollBarDraggingPos = y; 11131 return true; 11132 } 11133 if (isOnHorizontalScrollbarThumb(x, y)) { 11134 mScrollCache.mScrollBarDraggingState = 11135 ScrollabilityCache.DRAGGING_HORIZONTAL_SCROLL_BAR; 11136 mScrollCache.mScrollBarDraggingPos = x; 11137 return true; 11138 } 11139 } 11140 mScrollCache.mScrollBarDraggingState = ScrollabilityCache.NOT_DRAGGING; 11141 return false; 11142 } 11143 11144 /** 11145 * Implement this method to handle touch screen motion events. 11146 * <p> 11147 * If this method is used to detect click actions, it is recommended that 11148 * the actions be performed by implementing and calling 11149 * {@link #performClick()}. This will ensure consistent system behavior, 11150 * including: 11151 * <ul> 11152 * <li>obeying click sound preferences 11153 * <li>dispatching OnClickListener calls 11154 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 11155 * accessibility features are enabled 11156 * </ul> 11157 * 11158 * @param event The motion event. 11159 * @return True if the event was handled, false otherwise. 11160 */ onTouchEvent(MotionEvent event)11161 public boolean onTouchEvent(MotionEvent event) { 11162 final float x = event.getX(); 11163 final float y = event.getY(); 11164 final int viewFlags = mViewFlags; 11165 final int action = event.getAction(); 11166 11167 if ((viewFlags & ENABLED_MASK) == DISABLED) { 11168 if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 11169 setPressed(false); 11170 } 11171 // A disabled view that is clickable still consumes the touch 11172 // events, it just doesn't respond to them. 11173 return (((viewFlags & CLICKABLE) == CLICKABLE 11174 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 11175 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE); 11176 } 11177 if (mTouchDelegate != null) { 11178 if (mTouchDelegate.onTouchEvent(event)) { 11179 return true; 11180 } 11181 } 11182 11183 if (((viewFlags & CLICKABLE) == CLICKABLE || 11184 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || 11185 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) { 11186 switch (action) { 11187 case MotionEvent.ACTION_UP: 11188 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 11189 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 11190 // take focus if we don't have it already and we should in 11191 // touch mode. 11192 boolean focusTaken = false; 11193 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 11194 focusTaken = requestFocus(); 11195 } 11196 11197 if (prepressed) { 11198 // The button is being released before we actually 11199 // showed it as pressed. Make it show the pressed 11200 // state now (before scheduling the click) to ensure 11201 // the user sees it. 11202 setPressed(true, x, y); 11203 } 11204 11205 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { 11206 // This is a tap, so remove the longpress check 11207 removeLongPressCallback(); 11208 11209 // Only perform take click actions if we were in the pressed state 11210 if (!focusTaken) { 11211 // Use a Runnable and post this rather than calling 11212 // performClick directly. This lets other visual state 11213 // of the view update before click actions start. 11214 if (mPerformClick == null) { 11215 mPerformClick = new PerformClick(); 11216 } 11217 if (!post(mPerformClick)) { 11218 performClick(); 11219 } 11220 } 11221 } 11222 11223 if (mUnsetPressedState == null) { 11224 mUnsetPressedState = new UnsetPressedState(); 11225 } 11226 11227 if (prepressed) { 11228 postDelayed(mUnsetPressedState, 11229 ViewConfiguration.getPressedStateDuration()); 11230 } else if (!post(mUnsetPressedState)) { 11231 // If the post failed, unpress right now 11232 mUnsetPressedState.run(); 11233 } 11234 11235 removeTapCallback(); 11236 } 11237 mIgnoreNextUpEvent = false; 11238 break; 11239 11240 case MotionEvent.ACTION_DOWN: 11241 mHasPerformedLongPress = false; 11242 11243 if (performButtonActionOnTouchDown(event)) { 11244 break; 11245 } 11246 11247 // Walk up the hierarchy to determine if we're inside a scrolling container. 11248 boolean isInScrollingContainer = isInScrollingContainer(); 11249 11250 // For views inside a scrolling container, delay the pressed feedback for 11251 // a short period in case this is a scroll. 11252 if (isInScrollingContainer) { 11253 mPrivateFlags |= PFLAG_PREPRESSED; 11254 if (mPendingCheckForTap == null) { 11255 mPendingCheckForTap = new CheckForTap(); 11256 } 11257 mPendingCheckForTap.x = event.getX(); 11258 mPendingCheckForTap.y = event.getY(); 11259 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 11260 } else { 11261 // Not inside a scrolling container, so show the feedback right away 11262 setPressed(true, x, y); 11263 checkForLongClick(0, x, y); 11264 } 11265 break; 11266 11267 case MotionEvent.ACTION_CANCEL: 11268 setPressed(false); 11269 removeTapCallback(); 11270 removeLongPressCallback(); 11271 mInContextButtonPress = false; 11272 mHasPerformedLongPress = false; 11273 mIgnoreNextUpEvent = false; 11274 break; 11275 11276 case MotionEvent.ACTION_MOVE: 11277 drawableHotspotChanged(x, y); 11278 11279 // Be lenient about moving outside of buttons 11280 if (!pointInView(x, y, mTouchSlop)) { 11281 // Outside button 11282 removeTapCallback(); 11283 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 11284 // Remove any future long press/tap checks 11285 removeLongPressCallback(); 11286 11287 setPressed(false); 11288 } 11289 } 11290 break; 11291 } 11292 11293 return true; 11294 } 11295 11296 return false; 11297 } 11298 11299 /** 11300 * @hide 11301 */ isInScrollingContainer()11302 public boolean isInScrollingContainer() { 11303 ViewParent p = getParent(); 11304 while (p != null && p instanceof ViewGroup) { 11305 if (((ViewGroup) p).shouldDelayChildPressedState()) { 11306 return true; 11307 } 11308 p = p.getParent(); 11309 } 11310 return false; 11311 } 11312 11313 /** 11314 * Remove the longpress detection timer. 11315 */ removeLongPressCallback()11316 private void removeLongPressCallback() { 11317 if (mPendingCheckForLongPress != null) { 11318 removeCallbacks(mPendingCheckForLongPress); 11319 } 11320 } 11321 11322 /** 11323 * Remove the pending click action 11324 */ removePerformClickCallback()11325 private void removePerformClickCallback() { 11326 if (mPerformClick != null) { 11327 removeCallbacks(mPerformClick); 11328 } 11329 } 11330 11331 /** 11332 * Remove the prepress detection timer. 11333 */ removeUnsetPressCallback()11334 private void removeUnsetPressCallback() { 11335 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 11336 setPressed(false); 11337 removeCallbacks(mUnsetPressedState); 11338 } 11339 } 11340 11341 /** 11342 * Remove the tap detection timer. 11343 */ removeTapCallback()11344 private void removeTapCallback() { 11345 if (mPendingCheckForTap != null) { 11346 mPrivateFlags &= ~PFLAG_PREPRESSED; 11347 removeCallbacks(mPendingCheckForTap); 11348 } 11349 } 11350 11351 /** 11352 * Cancels a pending long press. Your subclass can use this if you 11353 * want the context menu to come up if the user presses and holds 11354 * at the same place, but you don't want it to come up if they press 11355 * and then move around enough to cause scrolling. 11356 */ cancelLongPress()11357 public void cancelLongPress() { 11358 removeLongPressCallback(); 11359 11360 /* 11361 * The prepressed state handled by the tap callback is a display 11362 * construct, but the tap callback will post a long press callback 11363 * less its own timeout. Remove it here. 11364 */ 11365 removeTapCallback(); 11366 } 11367 11368 /** 11369 * Remove the pending callback for sending a 11370 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 11371 */ removeSendViewScrolledAccessibilityEventCallback()11372 private void removeSendViewScrolledAccessibilityEventCallback() { 11373 if (mSendViewScrolledAccessibilityEvent != null) { 11374 removeCallbacks(mSendViewScrolledAccessibilityEvent); 11375 mSendViewScrolledAccessibilityEvent.mIsPending = false; 11376 } 11377 } 11378 11379 /** 11380 * Sets the TouchDelegate for this View. 11381 */ setTouchDelegate(TouchDelegate delegate)11382 public void setTouchDelegate(TouchDelegate delegate) { 11383 mTouchDelegate = delegate; 11384 } 11385 11386 /** 11387 * Gets the TouchDelegate for this View. 11388 */ getTouchDelegate()11389 public TouchDelegate getTouchDelegate() { 11390 return mTouchDelegate; 11391 } 11392 11393 /** 11394 * Request unbuffered dispatch of the given stream of MotionEvents to this View. 11395 * 11396 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input 11397 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're 11398 * available. This method should only be called for touch events. 11399 * 11400 * <p class="note">This api is not intended for most applications. Buffered dispatch 11401 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent 11402 * streams will not improve your input latency. Side effects include: increased latency, 11403 * jittery scrolls and inability to take advantage of system resampling. Talk to your input 11404 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for 11405 * you.</p> 11406 */ requestUnbufferedDispatch(MotionEvent event)11407 public final void requestUnbufferedDispatch(MotionEvent event) { 11408 final int action = event.getAction(); 11409 if (mAttachInfo == null 11410 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE 11411 || !event.isTouchEvent()) { 11412 return; 11413 } 11414 mAttachInfo.mUnbufferedDispatchRequested = true; 11415 } 11416 11417 /** 11418 * Set flags controlling behavior of this view. 11419 * 11420 * @param flags Constant indicating the value which should be set 11421 * @param mask Constant indicating the bit range that should be changed 11422 */ setFlags(int flags, int mask)11423 void setFlags(int flags, int mask) { 11424 final boolean accessibilityEnabled = 11425 AccessibilityManager.getInstance(mContext).isEnabled(); 11426 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 11427 11428 int old = mViewFlags; 11429 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 11430 11431 int changed = mViewFlags ^ old; 11432 if (changed == 0) { 11433 return; 11434 } 11435 int privateFlags = mPrivateFlags; 11436 11437 /* Check if the FOCUSABLE bit has changed */ 11438 if (((changed & FOCUSABLE_MASK) != 0) && 11439 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { 11440 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 11441 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 11442 /* Give up focus if we are no longer focusable */ 11443 clearFocus(); 11444 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 11445 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 11446 /* 11447 * Tell the view system that we are now available to take focus 11448 * if no one else already has it. 11449 */ 11450 if (mParent != null) mParent.focusableViewAvailable(this); 11451 } 11452 } 11453 11454 final int newVisibility = flags & VISIBILITY_MASK; 11455 if (newVisibility == VISIBLE) { 11456 if ((changed & VISIBILITY_MASK) != 0) { 11457 /* 11458 * If this view is becoming visible, invalidate it in case it changed while 11459 * it was not visible. Marking it drawn ensures that the invalidation will 11460 * go through. 11461 */ 11462 mPrivateFlags |= PFLAG_DRAWN; 11463 invalidate(true); 11464 11465 needGlobalAttributesUpdate(true); 11466 11467 // a view becoming visible is worth notifying the parent 11468 // about in case nothing has focus. even if this specific view 11469 // isn't focusable, it may contain something that is, so let 11470 // the root view try to give this focus if nothing else does. 11471 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 11472 mParent.focusableViewAvailable(this); 11473 } 11474 } 11475 } 11476 11477 /* Check if the GONE bit has changed */ 11478 if ((changed & GONE) != 0) { 11479 needGlobalAttributesUpdate(false); 11480 requestLayout(); 11481 11482 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 11483 if (hasFocus()) clearFocus(); 11484 clearAccessibilityFocus(); 11485 destroyDrawingCache(); 11486 if (mParent instanceof View) { 11487 // GONE views noop invalidation, so invalidate the parent 11488 ((View) mParent).invalidate(true); 11489 } 11490 // Mark the view drawn to ensure that it gets invalidated properly the next 11491 // time it is visible and gets invalidated 11492 mPrivateFlags |= PFLAG_DRAWN; 11493 } 11494 if (mAttachInfo != null) { 11495 mAttachInfo.mViewVisibilityChanged = true; 11496 } 11497 } 11498 11499 /* Check if the VISIBLE bit has changed */ 11500 if ((changed & INVISIBLE) != 0) { 11501 needGlobalAttributesUpdate(false); 11502 /* 11503 * If this view is becoming invisible, set the DRAWN flag so that 11504 * the next invalidate() will not be skipped. 11505 */ 11506 mPrivateFlags |= PFLAG_DRAWN; 11507 11508 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 11509 // root view becoming invisible shouldn't clear focus and accessibility focus 11510 if (getRootView() != this) { 11511 if (hasFocus()) clearFocus(); 11512 clearAccessibilityFocus(); 11513 } 11514 } 11515 if (mAttachInfo != null) { 11516 mAttachInfo.mViewVisibilityChanged = true; 11517 } 11518 } 11519 11520 if ((changed & VISIBILITY_MASK) != 0) { 11521 // If the view is invisible, cleanup its display list to free up resources 11522 if (newVisibility != VISIBLE && mAttachInfo != null) { 11523 cleanupDraw(); 11524 } 11525 11526 if (mParent instanceof ViewGroup) { 11527 ((ViewGroup) mParent).onChildVisibilityChanged(this, 11528 (changed & VISIBILITY_MASK), newVisibility); 11529 ((View) mParent).invalidate(true); 11530 } else if (mParent != null) { 11531 mParent.invalidateChild(this, null); 11532 } 11533 11534 if (mAttachInfo != null) { 11535 dispatchVisibilityChanged(this, newVisibility); 11536 11537 // Aggregated visibility changes are dispatched to attached views 11538 // in visible windows where the parent is currently shown/drawn 11539 // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot), 11540 // discounting clipping or overlapping. This makes it a good place 11541 // to change animation states. 11542 if (mParent != null && getWindowVisibility() == VISIBLE && 11543 ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { 11544 dispatchVisibilityAggregated(newVisibility == VISIBLE); 11545 } 11546 notifySubtreeAccessibilityStateChangedIfNeeded(); 11547 } 11548 } 11549 11550 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 11551 destroyDrawingCache(); 11552 } 11553 11554 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 11555 destroyDrawingCache(); 11556 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 11557 invalidateParentCaches(); 11558 } 11559 11560 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 11561 destroyDrawingCache(); 11562 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 11563 } 11564 11565 if ((changed & DRAW_MASK) != 0) { 11566 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 11567 if (mBackground != null 11568 || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) { 11569 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 11570 } else { 11571 mPrivateFlags |= PFLAG_SKIP_DRAW; 11572 } 11573 } else { 11574 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 11575 } 11576 requestLayout(); 11577 invalidate(true); 11578 } 11579 11580 if ((changed & KEEP_SCREEN_ON) != 0) { 11581 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 11582 mParent.recomputeViewAttributes(this); 11583 } 11584 } 11585 11586 if (accessibilityEnabled) { 11587 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0 11588 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0 11589 || (changed & CONTEXT_CLICKABLE) != 0) { 11590 if (oldIncludeForAccessibility != includeForAccessibility()) { 11591 notifySubtreeAccessibilityStateChangedIfNeeded(); 11592 } else { 11593 notifyViewAccessibilityStateChangedIfNeeded( 11594 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11595 } 11596 } else if ((changed & ENABLED_MASK) != 0) { 11597 notifyViewAccessibilityStateChangedIfNeeded( 11598 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11599 } 11600 } 11601 } 11602 11603 /** 11604 * Change the view's z order in the tree, so it's on top of other sibling 11605 * views. This ordering change may affect layout, if the parent container 11606 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 11607 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 11608 * method should be followed by calls to {@link #requestLayout()} and 11609 * {@link View#invalidate()} on the view's parent to force the parent to redraw 11610 * with the new child ordering. 11611 * 11612 * @see ViewGroup#bringChildToFront(View) 11613 */ bringToFront()11614 public void bringToFront() { 11615 if (mParent != null) { 11616 mParent.bringChildToFront(this); 11617 } 11618 } 11619 11620 /** 11621 * This is called in response to an internal scroll in this view (i.e., the 11622 * view scrolled its own contents). This is typically as a result of 11623 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 11624 * called. 11625 * 11626 * @param l Current horizontal scroll origin. 11627 * @param t Current vertical scroll origin. 11628 * @param oldl Previous horizontal scroll origin. 11629 * @param oldt Previous vertical scroll origin. 11630 */ onScrollChanged(int l, int t, int oldl, int oldt)11631 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 11632 notifySubtreeAccessibilityStateChangedIfNeeded(); 11633 11634 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 11635 postSendViewScrolledAccessibilityEventCallback(); 11636 } 11637 11638 mBackgroundSizeChanged = true; 11639 if (mForegroundInfo != null) { 11640 mForegroundInfo.mBoundsChanged = true; 11641 } 11642 11643 final AttachInfo ai = mAttachInfo; 11644 if (ai != null) { 11645 ai.mViewScrollChanged = true; 11646 } 11647 11648 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) { 11649 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); 11650 } 11651 } 11652 11653 /** 11654 * Interface definition for a callback to be invoked when the scroll 11655 * X or Y positions of a view change. 11656 * <p> 11657 * <b>Note:</b> Some views handle scrolling independently from View and may 11658 * have their own separate listeners for scroll-type events. For example, 11659 * {@link android.widget.ListView ListView} allows clients to register an 11660 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 11661 * to listen for changes in list scroll position. 11662 * 11663 * @see #setOnScrollChangeListener(View.OnScrollChangeListener) 11664 */ 11665 public interface OnScrollChangeListener { 11666 /** 11667 * Called when the scroll position of a view changes. 11668 * 11669 * @param v The view whose scroll position has changed. 11670 * @param scrollX Current horizontal scroll origin. 11671 * @param scrollY Current vertical scroll origin. 11672 * @param oldScrollX Previous horizontal scroll origin. 11673 * @param oldScrollY Previous vertical scroll origin. 11674 */ onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)11675 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); 11676 } 11677 11678 /** 11679 * Interface definition for a callback to be invoked when the layout bounds of a view 11680 * changes due to layout processing. 11681 */ 11682 public interface OnLayoutChangeListener { 11683 /** 11684 * Called when the layout bounds of a view changes due to layout processing. 11685 * 11686 * @param v The view whose bounds have changed. 11687 * @param left The new value of the view's left property. 11688 * @param top The new value of the view's top property. 11689 * @param right The new value of the view's right property. 11690 * @param bottom The new value of the view's bottom property. 11691 * @param oldLeft The previous value of the view's left property. 11692 * @param oldTop The previous value of the view's top property. 11693 * @param oldRight The previous value of the view's right property. 11694 * @param oldBottom The previous value of the view's bottom property. 11695 */ onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom)11696 void onLayoutChange(View v, int left, int top, int right, int bottom, 11697 int oldLeft, int oldTop, int oldRight, int oldBottom); 11698 } 11699 11700 /** 11701 * This is called during layout when the size of this view has changed. If 11702 * you were just added to the view hierarchy, you're called with the old 11703 * values of 0. 11704 * 11705 * @param w Current width of this view. 11706 * @param h Current height of this view. 11707 * @param oldw Old width of this view. 11708 * @param oldh Old height of this view. 11709 */ onSizeChanged(int w, int h, int oldw, int oldh)11710 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 11711 } 11712 11713 /** 11714 * Called by draw to draw the child views. This may be overridden 11715 * by derived classes to gain control just before its children are drawn 11716 * (but after its own view has been drawn). 11717 * @param canvas the canvas on which to draw the view 11718 */ dispatchDraw(Canvas canvas)11719 protected void dispatchDraw(Canvas canvas) { 11720 11721 } 11722 11723 /** 11724 * Gets the parent of this view. Note that the parent is a 11725 * ViewParent and not necessarily a View. 11726 * 11727 * @return Parent of this view. 11728 */ getParent()11729 public final ViewParent getParent() { 11730 return mParent; 11731 } 11732 11733 /** 11734 * Set the horizontal scrolled position of your view. This will cause a call to 11735 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11736 * invalidated. 11737 * @param value the x position to scroll to 11738 */ setScrollX(int value)11739 public void setScrollX(int value) { 11740 scrollTo(value, mScrollY); 11741 } 11742 11743 /** 11744 * Set the vertical scrolled position of your view. This will cause a call to 11745 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11746 * invalidated. 11747 * @param value the y position to scroll to 11748 */ setScrollY(int value)11749 public void setScrollY(int value) { 11750 scrollTo(mScrollX, value); 11751 } 11752 11753 /** 11754 * Return the scrolled left position of this view. This is the left edge of 11755 * the displayed part of your view. You do not need to draw any pixels 11756 * farther left, since those are outside of the frame of your view on 11757 * screen. 11758 * 11759 * @return The left edge of the displayed part of your view, in pixels. 11760 */ getScrollX()11761 public final int getScrollX() { 11762 return mScrollX; 11763 } 11764 11765 /** 11766 * Return the scrolled top position of this view. This is the top edge of 11767 * the displayed part of your view. You do not need to draw any pixels above 11768 * it, since those are outside of the frame of your view on screen. 11769 * 11770 * @return The top edge of the displayed part of your view, in pixels. 11771 */ getScrollY()11772 public final int getScrollY() { 11773 return mScrollY; 11774 } 11775 11776 /** 11777 * Return the width of the your view. 11778 * 11779 * @return The width of your view, in pixels. 11780 */ 11781 @ViewDebug.ExportedProperty(category = "layout") getWidth()11782 public final int getWidth() { 11783 return mRight - mLeft; 11784 } 11785 11786 /** 11787 * Return the height of your view. 11788 * 11789 * @return The height of your view, in pixels. 11790 */ 11791 @ViewDebug.ExportedProperty(category = "layout") getHeight()11792 public final int getHeight() { 11793 return mBottom - mTop; 11794 } 11795 11796 /** 11797 * Return the visible drawing bounds of your view. Fills in the output 11798 * rectangle with the values from getScrollX(), getScrollY(), 11799 * getWidth(), and getHeight(). These bounds do not account for any 11800 * transformation properties currently set on the view, such as 11801 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 11802 * 11803 * @param outRect The (scrolled) drawing bounds of the view. 11804 */ getDrawingRect(Rect outRect)11805 public void getDrawingRect(Rect outRect) { 11806 outRect.left = mScrollX; 11807 outRect.top = mScrollY; 11808 outRect.right = mScrollX + (mRight - mLeft); 11809 outRect.bottom = mScrollY + (mBottom - mTop); 11810 } 11811 11812 /** 11813 * Like {@link #getMeasuredWidthAndState()}, but only returns the 11814 * raw width component (that is the result is masked by 11815 * {@link #MEASURED_SIZE_MASK}). 11816 * 11817 * @return The raw measured width of this view. 11818 */ getMeasuredWidth()11819 public final int getMeasuredWidth() { 11820 return mMeasuredWidth & MEASURED_SIZE_MASK; 11821 } 11822 11823 /** 11824 * Return the full width measurement information for this view as computed 11825 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11826 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11827 * This should be used during measurement and layout calculations only. Use 11828 * {@link #getWidth()} to see how wide a view is after layout. 11829 * 11830 * @return The measured width of this view as a bit mask. 11831 */ 11832 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11833 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11834 name = "MEASURED_STATE_TOO_SMALL"), 11835 }) getMeasuredWidthAndState()11836 public final int getMeasuredWidthAndState() { 11837 return mMeasuredWidth; 11838 } 11839 11840 /** 11841 * Like {@link #getMeasuredHeightAndState()}, but only returns the 11842 * raw width component (that is the result is masked by 11843 * {@link #MEASURED_SIZE_MASK}). 11844 * 11845 * @return The raw measured height of this view. 11846 */ getMeasuredHeight()11847 public final int getMeasuredHeight() { 11848 return mMeasuredHeight & MEASURED_SIZE_MASK; 11849 } 11850 11851 /** 11852 * Return the full height measurement information for this view as computed 11853 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11854 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11855 * This should be used during measurement and layout calculations only. Use 11856 * {@link #getHeight()} to see how wide a view is after layout. 11857 * 11858 * @return The measured width of this view as a bit mask. 11859 */ 11860 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11861 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11862 name = "MEASURED_STATE_TOO_SMALL"), 11863 }) getMeasuredHeightAndState()11864 public final int getMeasuredHeightAndState() { 11865 return mMeasuredHeight; 11866 } 11867 11868 /** 11869 * Return only the state bits of {@link #getMeasuredWidthAndState()} 11870 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 11871 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 11872 * and the height component is at the shifted bits 11873 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 11874 */ getMeasuredState()11875 public final int getMeasuredState() { 11876 return (mMeasuredWidth&MEASURED_STATE_MASK) 11877 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 11878 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 11879 } 11880 11881 /** 11882 * The transform matrix of this view, which is calculated based on the current 11883 * rotation, scale, and pivot properties. 11884 * 11885 * @see #getRotation() 11886 * @see #getScaleX() 11887 * @see #getScaleY() 11888 * @see #getPivotX() 11889 * @see #getPivotY() 11890 * @return The current transform matrix for the view 11891 */ getMatrix()11892 public Matrix getMatrix() { 11893 ensureTransformationInfo(); 11894 final Matrix matrix = mTransformationInfo.mMatrix; 11895 mRenderNode.getMatrix(matrix); 11896 return matrix; 11897 } 11898 11899 /** 11900 * Returns true if the transform matrix is the identity matrix. 11901 * Recomputes the matrix if necessary. 11902 * 11903 * @return True if the transform matrix is the identity matrix, false otherwise. 11904 */ hasIdentityMatrix()11905 final boolean hasIdentityMatrix() { 11906 return mRenderNode.hasIdentityMatrix(); 11907 } 11908 ensureTransformationInfo()11909 void ensureTransformationInfo() { 11910 if (mTransformationInfo == null) { 11911 mTransformationInfo = new TransformationInfo(); 11912 } 11913 } 11914 11915 /** 11916 * Utility method to retrieve the inverse of the current mMatrix property. 11917 * We cache the matrix to avoid recalculating it when transform properties 11918 * have not changed. 11919 * 11920 * @return The inverse of the current matrix of this view. 11921 * @hide 11922 */ getInverseMatrix()11923 public final Matrix getInverseMatrix() { 11924 ensureTransformationInfo(); 11925 if (mTransformationInfo.mInverseMatrix == null) { 11926 mTransformationInfo.mInverseMatrix = new Matrix(); 11927 } 11928 final Matrix matrix = mTransformationInfo.mInverseMatrix; 11929 mRenderNode.getInverseMatrix(matrix); 11930 return matrix; 11931 } 11932 11933 /** 11934 * Gets the distance along the Z axis from the camera to this view. 11935 * 11936 * @see #setCameraDistance(float) 11937 * 11938 * @return The distance along the Z axis. 11939 */ getCameraDistance()11940 public float getCameraDistance() { 11941 final float dpi = mResources.getDisplayMetrics().densityDpi; 11942 return -(mRenderNode.getCameraDistance() * dpi); 11943 } 11944 11945 /** 11946 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 11947 * views are drawn) from the camera to this view. The camera's distance 11948 * affects 3D transformations, for instance rotations around the X and Y 11949 * axis. If the rotationX or rotationY properties are changed and this view is 11950 * large (more than half the size of the screen), it is recommended to always 11951 * use a camera distance that's greater than the height (X axis rotation) or 11952 * the width (Y axis rotation) of this view.</p> 11953 * 11954 * <p>The distance of the camera from the view plane can have an affect on the 11955 * perspective distortion of the view when it is rotated around the x or y axis. 11956 * For example, a large distance will result in a large viewing angle, and there 11957 * will not be much perspective distortion of the view as it rotates. A short 11958 * distance may cause much more perspective distortion upon rotation, and can 11959 * also result in some drawing artifacts if the rotated view ends up partially 11960 * behind the camera (which is why the recommendation is to use a distance at 11961 * least as far as the size of the view, if the view is to be rotated.)</p> 11962 * 11963 * <p>The distance is expressed in "depth pixels." The default distance depends 11964 * on the screen density. For instance, on a medium density display, the 11965 * default distance is 1280. On a high density display, the default distance 11966 * is 1920.</p> 11967 * 11968 * <p>If you want to specify a distance that leads to visually consistent 11969 * results across various densities, use the following formula:</p> 11970 * <pre> 11971 * float scale = context.getResources().getDisplayMetrics().density; 11972 * view.setCameraDistance(distance * scale); 11973 * </pre> 11974 * 11975 * <p>The density scale factor of a high density display is 1.5, 11976 * and 1920 = 1280 * 1.5.</p> 11977 * 11978 * @param distance The distance in "depth pixels", if negative the opposite 11979 * value is used 11980 * 11981 * @see #setRotationX(float) 11982 * @see #setRotationY(float) 11983 */ setCameraDistance(float distance)11984 public void setCameraDistance(float distance) { 11985 final float dpi = mResources.getDisplayMetrics().densityDpi; 11986 11987 invalidateViewProperty(true, false); 11988 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); 11989 invalidateViewProperty(false, false); 11990 11991 invalidateParentIfNeededAndWasQuickRejected(); 11992 } 11993 11994 /** 11995 * The degrees that the view is rotated around the pivot point. 11996 * 11997 * @see #setRotation(float) 11998 * @see #getPivotX() 11999 * @see #getPivotY() 12000 * 12001 * @return The degrees of rotation. 12002 */ 12003 @ViewDebug.ExportedProperty(category = "drawing") getRotation()12004 public float getRotation() { 12005 return mRenderNode.getRotation(); 12006 } 12007 12008 /** 12009 * Sets the degrees that the view is rotated around the pivot point. Increasing values 12010 * result in clockwise rotation. 12011 * 12012 * @param rotation The degrees of rotation. 12013 * 12014 * @see #getRotation() 12015 * @see #getPivotX() 12016 * @see #getPivotY() 12017 * @see #setRotationX(float) 12018 * @see #setRotationY(float) 12019 * 12020 * @attr ref android.R.styleable#View_rotation 12021 */ setRotation(float rotation)12022 public void setRotation(float rotation) { 12023 if (rotation != getRotation()) { 12024 // Double-invalidation is necessary to capture view's old and new areas 12025 invalidateViewProperty(true, false); 12026 mRenderNode.setRotation(rotation); 12027 invalidateViewProperty(false, true); 12028 12029 invalidateParentIfNeededAndWasQuickRejected(); 12030 notifySubtreeAccessibilityStateChangedIfNeeded(); 12031 } 12032 } 12033 12034 /** 12035 * The degrees that the view is rotated around the vertical axis through the pivot point. 12036 * 12037 * @see #getPivotX() 12038 * @see #getPivotY() 12039 * @see #setRotationY(float) 12040 * 12041 * @return The degrees of Y rotation. 12042 */ 12043 @ViewDebug.ExportedProperty(category = "drawing") getRotationY()12044 public float getRotationY() { 12045 return mRenderNode.getRotationY(); 12046 } 12047 12048 /** 12049 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 12050 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 12051 * down the y axis. 12052 * 12053 * When rotating large views, it is recommended to adjust the camera distance 12054 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 12055 * 12056 * @param rotationY The degrees of Y rotation. 12057 * 12058 * @see #getRotationY() 12059 * @see #getPivotX() 12060 * @see #getPivotY() 12061 * @see #setRotation(float) 12062 * @see #setRotationX(float) 12063 * @see #setCameraDistance(float) 12064 * 12065 * @attr ref android.R.styleable#View_rotationY 12066 */ setRotationY(float rotationY)12067 public void setRotationY(float rotationY) { 12068 if (rotationY != getRotationY()) { 12069 invalidateViewProperty(true, false); 12070 mRenderNode.setRotationY(rotationY); 12071 invalidateViewProperty(false, true); 12072 12073 invalidateParentIfNeededAndWasQuickRejected(); 12074 notifySubtreeAccessibilityStateChangedIfNeeded(); 12075 } 12076 } 12077 12078 /** 12079 * The degrees that the view is rotated around the horizontal axis through the pivot point. 12080 * 12081 * @see #getPivotX() 12082 * @see #getPivotY() 12083 * @see #setRotationX(float) 12084 * 12085 * @return The degrees of X rotation. 12086 */ 12087 @ViewDebug.ExportedProperty(category = "drawing") getRotationX()12088 public float getRotationX() { 12089 return mRenderNode.getRotationX(); 12090 } 12091 12092 /** 12093 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 12094 * Increasing values result in clockwise rotation from the viewpoint of looking down the 12095 * x axis. 12096 * 12097 * When rotating large views, it is recommended to adjust the camera distance 12098 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 12099 * 12100 * @param rotationX The degrees of X rotation. 12101 * 12102 * @see #getRotationX() 12103 * @see #getPivotX() 12104 * @see #getPivotY() 12105 * @see #setRotation(float) 12106 * @see #setRotationY(float) 12107 * @see #setCameraDistance(float) 12108 * 12109 * @attr ref android.R.styleable#View_rotationX 12110 */ setRotationX(float rotationX)12111 public void setRotationX(float rotationX) { 12112 if (rotationX != getRotationX()) { 12113 invalidateViewProperty(true, false); 12114 mRenderNode.setRotationX(rotationX); 12115 invalidateViewProperty(false, true); 12116 12117 invalidateParentIfNeededAndWasQuickRejected(); 12118 notifySubtreeAccessibilityStateChangedIfNeeded(); 12119 } 12120 } 12121 12122 /** 12123 * The amount that the view is scaled in x around the pivot point, as a proportion of 12124 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 12125 * 12126 * <p>By default, this is 1.0f. 12127 * 12128 * @see #getPivotX() 12129 * @see #getPivotY() 12130 * @return The scaling factor. 12131 */ 12132 @ViewDebug.ExportedProperty(category = "drawing") getScaleX()12133 public float getScaleX() { 12134 return mRenderNode.getScaleX(); 12135 } 12136 12137 /** 12138 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 12139 * the view's unscaled width. A value of 1 means that no scaling is applied. 12140 * 12141 * @param scaleX The scaling factor. 12142 * @see #getPivotX() 12143 * @see #getPivotY() 12144 * 12145 * @attr ref android.R.styleable#View_scaleX 12146 */ setScaleX(float scaleX)12147 public void setScaleX(float scaleX) { 12148 if (scaleX != getScaleX()) { 12149 invalidateViewProperty(true, false); 12150 mRenderNode.setScaleX(scaleX); 12151 invalidateViewProperty(false, true); 12152 12153 invalidateParentIfNeededAndWasQuickRejected(); 12154 notifySubtreeAccessibilityStateChangedIfNeeded(); 12155 } 12156 } 12157 12158 /** 12159 * The amount that the view is scaled in y around the pivot point, as a proportion of 12160 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 12161 * 12162 * <p>By default, this is 1.0f. 12163 * 12164 * @see #getPivotX() 12165 * @see #getPivotY() 12166 * @return The scaling factor. 12167 */ 12168 @ViewDebug.ExportedProperty(category = "drawing") getScaleY()12169 public float getScaleY() { 12170 return mRenderNode.getScaleY(); 12171 } 12172 12173 /** 12174 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 12175 * the view's unscaled width. A value of 1 means that no scaling is applied. 12176 * 12177 * @param scaleY The scaling factor. 12178 * @see #getPivotX() 12179 * @see #getPivotY() 12180 * 12181 * @attr ref android.R.styleable#View_scaleY 12182 */ setScaleY(float scaleY)12183 public void setScaleY(float scaleY) { 12184 if (scaleY != getScaleY()) { 12185 invalidateViewProperty(true, false); 12186 mRenderNode.setScaleY(scaleY); 12187 invalidateViewProperty(false, true); 12188 12189 invalidateParentIfNeededAndWasQuickRejected(); 12190 notifySubtreeAccessibilityStateChangedIfNeeded(); 12191 } 12192 } 12193 12194 /** 12195 * The x location of the point around which the view is {@link #setRotation(float) rotated} 12196 * and {@link #setScaleX(float) scaled}. 12197 * 12198 * @see #getRotation() 12199 * @see #getScaleX() 12200 * @see #getScaleY() 12201 * @see #getPivotY() 12202 * @return The x location of the pivot point. 12203 * 12204 * @attr ref android.R.styleable#View_transformPivotX 12205 */ 12206 @ViewDebug.ExportedProperty(category = "drawing") getPivotX()12207 public float getPivotX() { 12208 return mRenderNode.getPivotX(); 12209 } 12210 12211 /** 12212 * Sets the x location of the point around which the view is 12213 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 12214 * By default, the pivot point is centered on the object. 12215 * Setting this property disables this behavior and causes the view to use only the 12216 * explicitly set pivotX and pivotY values. 12217 * 12218 * @param pivotX The x location of the pivot point. 12219 * @see #getRotation() 12220 * @see #getScaleX() 12221 * @see #getScaleY() 12222 * @see #getPivotY() 12223 * 12224 * @attr ref android.R.styleable#View_transformPivotX 12225 */ setPivotX(float pivotX)12226 public void setPivotX(float pivotX) { 12227 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { 12228 invalidateViewProperty(true, false); 12229 mRenderNode.setPivotX(pivotX); 12230 invalidateViewProperty(false, true); 12231 12232 invalidateParentIfNeededAndWasQuickRejected(); 12233 } 12234 } 12235 12236 /** 12237 * The y location of the point around which the view is {@link #setRotation(float) rotated} 12238 * and {@link #setScaleY(float) scaled}. 12239 * 12240 * @see #getRotation() 12241 * @see #getScaleX() 12242 * @see #getScaleY() 12243 * @see #getPivotY() 12244 * @return The y location of the pivot point. 12245 * 12246 * @attr ref android.R.styleable#View_transformPivotY 12247 */ 12248 @ViewDebug.ExportedProperty(category = "drawing") getPivotY()12249 public float getPivotY() { 12250 return mRenderNode.getPivotY(); 12251 } 12252 12253 /** 12254 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 12255 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 12256 * Setting this property disables this behavior and causes the view to use only the 12257 * explicitly set pivotX and pivotY values. 12258 * 12259 * @param pivotY The y location of the pivot point. 12260 * @see #getRotation() 12261 * @see #getScaleX() 12262 * @see #getScaleY() 12263 * @see #getPivotY() 12264 * 12265 * @attr ref android.R.styleable#View_transformPivotY 12266 */ setPivotY(float pivotY)12267 public void setPivotY(float pivotY) { 12268 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { 12269 invalidateViewProperty(true, false); 12270 mRenderNode.setPivotY(pivotY); 12271 invalidateViewProperty(false, true); 12272 12273 invalidateParentIfNeededAndWasQuickRejected(); 12274 } 12275 } 12276 12277 /** 12278 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 12279 * completely transparent and 1 means the view is completely opaque. 12280 * 12281 * <p>By default this is 1.0f. 12282 * @return The opacity of the view. 12283 */ 12284 @ViewDebug.ExportedProperty(category = "drawing") getAlpha()12285 public float getAlpha() { 12286 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 12287 } 12288 12289 /** 12290 * Sets the behavior for overlapping rendering for this view (see {@link 12291 * #hasOverlappingRendering()} for more details on this behavior). Calling this method 12292 * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass, 12293 * providing the value which is then used internally. That is, when {@link 12294 * #forceHasOverlappingRendering(boolean)} is called, the value of {@link 12295 * #hasOverlappingRendering()} is ignored and the value passed into this method is used 12296 * instead. 12297 * 12298 * @param hasOverlappingRendering The value for overlapping rendering to be used internally 12299 * instead of that returned by {@link #hasOverlappingRendering()}. 12300 * 12301 * @attr ref android.R.styleable#View_forceHasOverlappingRendering 12302 */ forceHasOverlappingRendering(boolean hasOverlappingRendering)12303 public void forceHasOverlappingRendering(boolean hasOverlappingRendering) { 12304 mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED; 12305 if (hasOverlappingRendering) { 12306 mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 12307 } else { 12308 mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE; 12309 } 12310 } 12311 12312 /** 12313 * Returns the value for overlapping rendering that is used internally. This is either 12314 * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or 12315 * the return value of {@link #hasOverlappingRendering()}, otherwise. 12316 * 12317 * @return The value for overlapping rendering being used internally. 12318 */ getHasOverlappingRendering()12319 public final boolean getHasOverlappingRendering() { 12320 return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ? 12321 (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 : 12322 hasOverlappingRendering(); 12323 } 12324 12325 /** 12326 * Returns whether this View has content which overlaps. 12327 * 12328 * <p>This function, intended to be overridden by specific View types, is an optimization when 12329 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 12330 * an offscreen buffer and then composited into place, which can be expensive. If the view has 12331 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 12332 * directly. An example of overlapping rendering is a TextView with a background image, such as 12333 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 12334 * ImageView with only the foreground image. The default implementation returns true; subclasses 12335 * should override if they have cases which can be optimized.</p> 12336 * 12337 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas} 12338 * necessitates that a View return true if it uses the methods internally without passing the 12339 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p> 12340 * 12341 * <p><strong>Note:</strong> The return value of this method is ignored if {@link 12342 * #forceHasOverlappingRendering(boolean)} has been called on this view.</p> 12343 * 12344 * @return true if the content in this view might overlap, false otherwise. 12345 */ 12346 @ViewDebug.ExportedProperty(category = "drawing") hasOverlappingRendering()12347 public boolean hasOverlappingRendering() { 12348 return true; 12349 } 12350 12351 /** 12352 * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is 12353 * completely transparent and 1 means the view is completely opaque. 12354 * 12355 * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1) 12356 * can have significant performance implications, especially for large views. It is best to use 12357 * the alpha property sparingly and transiently, as in the case of fading animations.</p> 12358 * 12359 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 12360 * strongly recommended for performance reasons to either override 12361 * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a 12362 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration 12363 * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below, 12364 * the default path for rendering an unlayered View with alpha could add multiple milliseconds 12365 * of rendering cost, even for simple or small views. Starting with 12366 * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically 12367 * applied to the view at the rendering level.</p> 12368 * 12369 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 12370 * responsible for applying the opacity itself.</p> 12371 * 12372 * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if 12373 * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is 12374 * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an 12375 * alpha value less than 1.0 will supersede the alpha of the layer paint.</p> 12376 * 12377 * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha 12378 * value will clip a View to its bounds, unless the View returns <code>false</code> from 12379 * {@link #hasOverlappingRendering}.</p> 12380 * 12381 * @param alpha The opacity of the view. 12382 * 12383 * @see #hasOverlappingRendering() 12384 * @see #setLayerType(int, android.graphics.Paint) 12385 * 12386 * @attr ref android.R.styleable#View_alpha 12387 */ setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)12388 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) { 12389 ensureTransformationInfo(); 12390 if (mTransformationInfo.mAlpha != alpha) { 12391 // Report visibility changes, which can affect children, to accessibility 12392 if ((alpha == 0) ^ (mTransformationInfo.mAlpha == 0)) { 12393 notifySubtreeAccessibilityStateChangedIfNeeded(); 12394 } 12395 mTransformationInfo.mAlpha = alpha; 12396 if (onSetAlpha((int) (alpha * 255))) { 12397 mPrivateFlags |= PFLAG_ALPHA_SET; 12398 // subclass is handling alpha - don't optimize rendering cache invalidation 12399 invalidateParentCaches(); 12400 invalidate(true); 12401 } else { 12402 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12403 invalidateViewProperty(true, false); 12404 mRenderNode.setAlpha(getFinalAlpha()); 12405 } 12406 } 12407 } 12408 12409 /** 12410 * Faster version of setAlpha() which performs the same steps except there are 12411 * no calls to invalidate(). The caller of this function should perform proper invalidation 12412 * on the parent and this object. The return value indicates whether the subclass handles 12413 * alpha (the return value for onSetAlpha()). 12414 * 12415 * @param alpha The new value for the alpha property 12416 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 12417 * the new value for the alpha property is different from the old value 12418 */ setAlphaNoInvalidation(float alpha)12419 boolean setAlphaNoInvalidation(float alpha) { 12420 ensureTransformationInfo(); 12421 if (mTransformationInfo.mAlpha != alpha) { 12422 mTransformationInfo.mAlpha = alpha; 12423 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 12424 if (subclassHandlesAlpha) { 12425 mPrivateFlags |= PFLAG_ALPHA_SET; 12426 return true; 12427 } else { 12428 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12429 mRenderNode.setAlpha(getFinalAlpha()); 12430 } 12431 } 12432 return false; 12433 } 12434 12435 /** 12436 * This property is hidden and intended only for use by the Fade transition, which 12437 * animates it to produce a visual translucency that does not side-effect (or get 12438 * affected by) the real alpha property. This value is composited with the other 12439 * alpha value (and the AlphaAnimation value, when that is present) to produce 12440 * a final visual translucency result, which is what is passed into the DisplayList. 12441 * 12442 * @hide 12443 */ setTransitionAlpha(float alpha)12444 public void setTransitionAlpha(float alpha) { 12445 ensureTransformationInfo(); 12446 if (mTransformationInfo.mTransitionAlpha != alpha) { 12447 mTransformationInfo.mTransitionAlpha = alpha; 12448 mPrivateFlags &= ~PFLAG_ALPHA_SET; 12449 invalidateViewProperty(true, false); 12450 mRenderNode.setAlpha(getFinalAlpha()); 12451 } 12452 } 12453 12454 /** 12455 * Calculates the visual alpha of this view, which is a combination of the actual 12456 * alpha value and the transitionAlpha value (if set). 12457 */ getFinalAlpha()12458 private float getFinalAlpha() { 12459 if (mTransformationInfo != null) { 12460 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 12461 } 12462 return 1; 12463 } 12464 12465 /** 12466 * This property is hidden and intended only for use by the Fade transition, which 12467 * animates it to produce a visual translucency that does not side-effect (or get 12468 * affected by) the real alpha property. This value is composited with the other 12469 * alpha value (and the AlphaAnimation value, when that is present) to produce 12470 * a final visual translucency result, which is what is passed into the DisplayList. 12471 * 12472 * @hide 12473 */ 12474 @ViewDebug.ExportedProperty(category = "drawing") getTransitionAlpha()12475 public float getTransitionAlpha() { 12476 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 12477 } 12478 12479 /** 12480 * Top position of this view relative to its parent. 12481 * 12482 * @return The top of this view, in pixels. 12483 */ 12484 @ViewDebug.CapturedViewProperty getTop()12485 public final int getTop() { 12486 return mTop; 12487 } 12488 12489 /** 12490 * Sets the top position of this view relative to its parent. This method is meant to be called 12491 * by the layout system and should not generally be called otherwise, because the property 12492 * may be changed at any time by the layout. 12493 * 12494 * @param top The top of this view, in pixels. 12495 */ setTop(int top)12496 public final void setTop(int top) { 12497 if (top != mTop) { 12498 final boolean matrixIsIdentity = hasIdentityMatrix(); 12499 if (matrixIsIdentity) { 12500 if (mAttachInfo != null) { 12501 int minTop; 12502 int yLoc; 12503 if (top < mTop) { 12504 minTop = top; 12505 yLoc = top - mTop; 12506 } else { 12507 minTop = mTop; 12508 yLoc = 0; 12509 } 12510 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 12511 } 12512 } else { 12513 // Double-invalidation is necessary to capture view's old and new areas 12514 invalidate(true); 12515 } 12516 12517 int width = mRight - mLeft; 12518 int oldHeight = mBottom - mTop; 12519 12520 mTop = top; 12521 mRenderNode.setTop(mTop); 12522 12523 sizeChange(width, mBottom - mTop, width, oldHeight); 12524 12525 if (!matrixIsIdentity) { 12526 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12527 invalidate(true); 12528 } 12529 mBackgroundSizeChanged = true; 12530 if (mForegroundInfo != null) { 12531 mForegroundInfo.mBoundsChanged = true; 12532 } 12533 invalidateParentIfNeeded(); 12534 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12535 // View was rejected last time it was drawn by its parent; this may have changed 12536 invalidateParentIfNeeded(); 12537 } 12538 } 12539 } 12540 12541 /** 12542 * Bottom position of this view relative to its parent. 12543 * 12544 * @return The bottom of this view, in pixels. 12545 */ 12546 @ViewDebug.CapturedViewProperty getBottom()12547 public final int getBottom() { 12548 return mBottom; 12549 } 12550 12551 /** 12552 * True if this view has changed since the last time being drawn. 12553 * 12554 * @return The dirty state of this view. 12555 */ isDirty()12556 public boolean isDirty() { 12557 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 12558 } 12559 12560 /** 12561 * Sets the bottom position of this view relative to its parent. This method is meant to be 12562 * called by the layout system and should not generally be called otherwise, because the 12563 * property may be changed at any time by the layout. 12564 * 12565 * @param bottom The bottom of this view, in pixels. 12566 */ setBottom(int bottom)12567 public final void setBottom(int bottom) { 12568 if (bottom != mBottom) { 12569 final boolean matrixIsIdentity = hasIdentityMatrix(); 12570 if (matrixIsIdentity) { 12571 if (mAttachInfo != null) { 12572 int maxBottom; 12573 if (bottom < mBottom) { 12574 maxBottom = mBottom; 12575 } else { 12576 maxBottom = bottom; 12577 } 12578 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 12579 } 12580 } else { 12581 // Double-invalidation is necessary to capture view's old and new areas 12582 invalidate(true); 12583 } 12584 12585 int width = mRight - mLeft; 12586 int oldHeight = mBottom - mTop; 12587 12588 mBottom = bottom; 12589 mRenderNode.setBottom(mBottom); 12590 12591 sizeChange(width, mBottom - mTop, width, oldHeight); 12592 12593 if (!matrixIsIdentity) { 12594 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12595 invalidate(true); 12596 } 12597 mBackgroundSizeChanged = true; 12598 if (mForegroundInfo != null) { 12599 mForegroundInfo.mBoundsChanged = true; 12600 } 12601 invalidateParentIfNeeded(); 12602 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12603 // View was rejected last time it was drawn by its parent; this may have changed 12604 invalidateParentIfNeeded(); 12605 } 12606 } 12607 } 12608 12609 /** 12610 * Left position of this view relative to its parent. 12611 * 12612 * @return The left edge of this view, in pixels. 12613 */ 12614 @ViewDebug.CapturedViewProperty getLeft()12615 public final int getLeft() { 12616 return mLeft; 12617 } 12618 12619 /** 12620 * Sets the left position of this view relative to its parent. This method is meant to be called 12621 * by the layout system and should not generally be called otherwise, because the property 12622 * may be changed at any time by the layout. 12623 * 12624 * @param left The left of this view, in pixels. 12625 */ setLeft(int left)12626 public final void setLeft(int left) { 12627 if (left != mLeft) { 12628 final boolean matrixIsIdentity = hasIdentityMatrix(); 12629 if (matrixIsIdentity) { 12630 if (mAttachInfo != null) { 12631 int minLeft; 12632 int xLoc; 12633 if (left < mLeft) { 12634 minLeft = left; 12635 xLoc = left - mLeft; 12636 } else { 12637 minLeft = mLeft; 12638 xLoc = 0; 12639 } 12640 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 12641 } 12642 } else { 12643 // Double-invalidation is necessary to capture view's old and new areas 12644 invalidate(true); 12645 } 12646 12647 int oldWidth = mRight - mLeft; 12648 int height = mBottom - mTop; 12649 12650 mLeft = left; 12651 mRenderNode.setLeft(left); 12652 12653 sizeChange(mRight - mLeft, height, oldWidth, height); 12654 12655 if (!matrixIsIdentity) { 12656 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12657 invalidate(true); 12658 } 12659 mBackgroundSizeChanged = true; 12660 if (mForegroundInfo != null) { 12661 mForegroundInfo.mBoundsChanged = true; 12662 } 12663 invalidateParentIfNeeded(); 12664 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12665 // View was rejected last time it was drawn by its parent; this may have changed 12666 invalidateParentIfNeeded(); 12667 } 12668 } 12669 } 12670 12671 /** 12672 * Right position of this view relative to its parent. 12673 * 12674 * @return The right edge of this view, in pixels. 12675 */ 12676 @ViewDebug.CapturedViewProperty getRight()12677 public final int getRight() { 12678 return mRight; 12679 } 12680 12681 /** 12682 * Sets the right position of this view relative to its parent. This method is meant to be called 12683 * by the layout system and should not generally be called otherwise, because the property 12684 * may be changed at any time by the layout. 12685 * 12686 * @param right The right of this view, in pixels. 12687 */ setRight(int right)12688 public final void setRight(int right) { 12689 if (right != mRight) { 12690 final boolean matrixIsIdentity = hasIdentityMatrix(); 12691 if (matrixIsIdentity) { 12692 if (mAttachInfo != null) { 12693 int maxRight; 12694 if (right < mRight) { 12695 maxRight = mRight; 12696 } else { 12697 maxRight = right; 12698 } 12699 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 12700 } 12701 } else { 12702 // Double-invalidation is necessary to capture view's old and new areas 12703 invalidate(true); 12704 } 12705 12706 int oldWidth = mRight - mLeft; 12707 int height = mBottom - mTop; 12708 12709 mRight = right; 12710 mRenderNode.setRight(mRight); 12711 12712 sizeChange(mRight - mLeft, height, oldWidth, height); 12713 12714 if (!matrixIsIdentity) { 12715 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12716 invalidate(true); 12717 } 12718 mBackgroundSizeChanged = true; 12719 if (mForegroundInfo != null) { 12720 mForegroundInfo.mBoundsChanged = true; 12721 } 12722 invalidateParentIfNeeded(); 12723 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12724 // View was rejected last time it was drawn by its parent; this may have changed 12725 invalidateParentIfNeeded(); 12726 } 12727 } 12728 } 12729 12730 /** 12731 * The visual x position of this view, in pixels. This is equivalent to the 12732 * {@link #setTranslationX(float) translationX} property plus the current 12733 * {@link #getLeft() left} property. 12734 * 12735 * @return The visual x position of this view, in pixels. 12736 */ 12737 @ViewDebug.ExportedProperty(category = "drawing") getX()12738 public float getX() { 12739 return mLeft + getTranslationX(); 12740 } 12741 12742 /** 12743 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 12744 * {@link #setTranslationX(float) translationX} property to be the difference between 12745 * the x value passed in and the current {@link #getLeft() left} property. 12746 * 12747 * @param x The visual x position of this view, in pixels. 12748 */ setX(float x)12749 public void setX(float x) { 12750 setTranslationX(x - mLeft); 12751 } 12752 12753 /** 12754 * The visual y position of this view, in pixels. This is equivalent to the 12755 * {@link #setTranslationY(float) translationY} property plus the current 12756 * {@link #getTop() top} property. 12757 * 12758 * @return The visual y position of this view, in pixels. 12759 */ 12760 @ViewDebug.ExportedProperty(category = "drawing") getY()12761 public float getY() { 12762 return mTop + getTranslationY(); 12763 } 12764 12765 /** 12766 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 12767 * {@link #setTranslationY(float) translationY} property to be the difference between 12768 * the y value passed in and the current {@link #getTop() top} property. 12769 * 12770 * @param y The visual y position of this view, in pixels. 12771 */ setY(float y)12772 public void setY(float y) { 12773 setTranslationY(y - mTop); 12774 } 12775 12776 /** 12777 * The visual z position of this view, in pixels. This is equivalent to the 12778 * {@link #setTranslationZ(float) translationZ} property plus the current 12779 * {@link #getElevation() elevation} property. 12780 * 12781 * @return The visual z position of this view, in pixels. 12782 */ 12783 @ViewDebug.ExportedProperty(category = "drawing") getZ()12784 public float getZ() { 12785 return getElevation() + getTranslationZ(); 12786 } 12787 12788 /** 12789 * Sets the visual z position of this view, in pixels. This is equivalent to setting the 12790 * {@link #setTranslationZ(float) translationZ} property to be the difference between 12791 * the x value passed in and the current {@link #getElevation() elevation} property. 12792 * 12793 * @param z The visual z position of this view, in pixels. 12794 */ setZ(float z)12795 public void setZ(float z) { 12796 setTranslationZ(z - getElevation()); 12797 } 12798 12799 /** 12800 * The base elevation of this view relative to its parent, in pixels. 12801 * 12802 * @return The base depth position of the view, in pixels. 12803 */ 12804 @ViewDebug.ExportedProperty(category = "drawing") getElevation()12805 public float getElevation() { 12806 return mRenderNode.getElevation(); 12807 } 12808 12809 /** 12810 * Sets the base elevation of this view, in pixels. 12811 * 12812 * @attr ref android.R.styleable#View_elevation 12813 */ setElevation(float elevation)12814 public void setElevation(float elevation) { 12815 if (elevation != getElevation()) { 12816 invalidateViewProperty(true, false); 12817 mRenderNode.setElevation(elevation); 12818 invalidateViewProperty(false, true); 12819 12820 invalidateParentIfNeededAndWasQuickRejected(); 12821 } 12822 } 12823 12824 /** 12825 * The horizontal location of this view relative to its {@link #getLeft() left} position. 12826 * This position is post-layout, in addition to wherever the object's 12827 * layout placed it. 12828 * 12829 * @return The horizontal position of this view relative to its left position, in pixels. 12830 */ 12831 @ViewDebug.ExportedProperty(category = "drawing") getTranslationX()12832 public float getTranslationX() { 12833 return mRenderNode.getTranslationX(); 12834 } 12835 12836 /** 12837 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 12838 * This effectively positions the object post-layout, in addition to wherever the object's 12839 * layout placed it. 12840 * 12841 * @param translationX The horizontal position of this view relative to its left position, 12842 * in pixels. 12843 * 12844 * @attr ref android.R.styleable#View_translationX 12845 */ setTranslationX(float translationX)12846 public void setTranslationX(float translationX) { 12847 if (translationX != getTranslationX()) { 12848 invalidateViewProperty(true, false); 12849 mRenderNode.setTranslationX(translationX); 12850 invalidateViewProperty(false, true); 12851 12852 invalidateParentIfNeededAndWasQuickRejected(); 12853 notifySubtreeAccessibilityStateChangedIfNeeded(); 12854 } 12855 } 12856 12857 /** 12858 * The vertical location of this view relative to its {@link #getTop() top} position. 12859 * This position is post-layout, in addition to wherever the object's 12860 * layout placed it. 12861 * 12862 * @return The vertical position of this view relative to its top position, 12863 * in pixels. 12864 */ 12865 @ViewDebug.ExportedProperty(category = "drawing") getTranslationY()12866 public float getTranslationY() { 12867 return mRenderNode.getTranslationY(); 12868 } 12869 12870 /** 12871 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 12872 * This effectively positions the object post-layout, in addition to wherever the object's 12873 * layout placed it. 12874 * 12875 * @param translationY The vertical position of this view relative to its top position, 12876 * in pixels. 12877 * 12878 * @attr ref android.R.styleable#View_translationY 12879 */ setTranslationY(float translationY)12880 public void setTranslationY(float translationY) { 12881 if (translationY != getTranslationY()) { 12882 invalidateViewProperty(true, false); 12883 mRenderNode.setTranslationY(translationY); 12884 invalidateViewProperty(false, true); 12885 12886 invalidateParentIfNeededAndWasQuickRejected(); 12887 notifySubtreeAccessibilityStateChangedIfNeeded(); 12888 } 12889 } 12890 12891 /** 12892 * The depth location of this view relative to its {@link #getElevation() elevation}. 12893 * 12894 * @return The depth of this view relative to its elevation. 12895 */ 12896 @ViewDebug.ExportedProperty(category = "drawing") getTranslationZ()12897 public float getTranslationZ() { 12898 return mRenderNode.getTranslationZ(); 12899 } 12900 12901 /** 12902 * Sets the depth location of this view relative to its {@link #getElevation() elevation}. 12903 * 12904 * @attr ref android.R.styleable#View_translationZ 12905 */ setTranslationZ(float translationZ)12906 public void setTranslationZ(float translationZ) { 12907 if (translationZ != getTranslationZ()) { 12908 invalidateViewProperty(true, false); 12909 mRenderNode.setTranslationZ(translationZ); 12910 invalidateViewProperty(false, true); 12911 12912 invalidateParentIfNeededAndWasQuickRejected(); 12913 } 12914 } 12915 12916 /** @hide */ setAnimationMatrix(Matrix matrix)12917 public void setAnimationMatrix(Matrix matrix) { 12918 invalidateViewProperty(true, false); 12919 mRenderNode.setAnimationMatrix(matrix); 12920 invalidateViewProperty(false, true); 12921 12922 invalidateParentIfNeededAndWasQuickRejected(); 12923 } 12924 12925 /** 12926 * Returns the current StateListAnimator if exists. 12927 * 12928 * @return StateListAnimator or null if it does not exists 12929 * @see #setStateListAnimator(android.animation.StateListAnimator) 12930 */ getStateListAnimator()12931 public StateListAnimator getStateListAnimator() { 12932 return mStateListAnimator; 12933 } 12934 12935 /** 12936 * Attaches the provided StateListAnimator to this View. 12937 * <p> 12938 * Any previously attached StateListAnimator will be detached. 12939 * 12940 * @param stateListAnimator The StateListAnimator to update the view 12941 * @see {@link android.animation.StateListAnimator} 12942 */ setStateListAnimator(StateListAnimator stateListAnimator)12943 public void setStateListAnimator(StateListAnimator stateListAnimator) { 12944 if (mStateListAnimator == stateListAnimator) { 12945 return; 12946 } 12947 if (mStateListAnimator != null) { 12948 mStateListAnimator.setTarget(null); 12949 } 12950 mStateListAnimator = stateListAnimator; 12951 if (stateListAnimator != null) { 12952 stateListAnimator.setTarget(this); 12953 if (isAttachedToWindow()) { 12954 stateListAnimator.setState(getDrawableState()); 12955 } 12956 } 12957 } 12958 12959 /** 12960 * Returns whether the Outline should be used to clip the contents of the View. 12961 * <p> 12962 * Note that this flag will only be respected if the View's Outline returns true from 12963 * {@link Outline#canClip()}. 12964 * 12965 * @see #setOutlineProvider(ViewOutlineProvider) 12966 * @see #setClipToOutline(boolean) 12967 */ getClipToOutline()12968 public final boolean getClipToOutline() { 12969 return mRenderNode.getClipToOutline(); 12970 } 12971 12972 /** 12973 * Sets whether the View's Outline should be used to clip the contents of the View. 12974 * <p> 12975 * Only a single non-rectangular clip can be applied on a View at any time. 12976 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float) 12977 * circular reveal} animation take priority over Outline clipping, and 12978 * child Outline clipping takes priority over Outline clipping done by a 12979 * parent. 12980 * <p> 12981 * Note that this flag will only be respected if the View's Outline returns true from 12982 * {@link Outline#canClip()}. 12983 * 12984 * @see #setOutlineProvider(ViewOutlineProvider) 12985 * @see #getClipToOutline() 12986 */ setClipToOutline(boolean clipToOutline)12987 public void setClipToOutline(boolean clipToOutline) { 12988 damageInParent(); 12989 if (getClipToOutline() != clipToOutline) { 12990 mRenderNode.setClipToOutline(clipToOutline); 12991 } 12992 } 12993 12994 // correspond to the enum values of View_outlineProvider 12995 private static final int PROVIDER_BACKGROUND = 0; 12996 private static final int PROVIDER_NONE = 1; 12997 private static final int PROVIDER_BOUNDS = 2; 12998 private static final int PROVIDER_PADDED_BOUNDS = 3; setOutlineProviderFromAttribute(int providerInt)12999 private void setOutlineProviderFromAttribute(int providerInt) { 13000 switch (providerInt) { 13001 case PROVIDER_BACKGROUND: 13002 setOutlineProvider(ViewOutlineProvider.BACKGROUND); 13003 break; 13004 case PROVIDER_NONE: 13005 setOutlineProvider(null); 13006 break; 13007 case PROVIDER_BOUNDS: 13008 setOutlineProvider(ViewOutlineProvider.BOUNDS); 13009 break; 13010 case PROVIDER_PADDED_BOUNDS: 13011 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS); 13012 break; 13013 } 13014 } 13015 13016 /** 13017 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines 13018 * the shape of the shadow it casts, and enables outline clipping. 13019 * <p> 13020 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline 13021 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the 13022 * outline provider with this method allows this behavior to be overridden. 13023 * <p> 13024 * If the ViewOutlineProvider is null, if querying it for an outline returns false, 13025 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast. 13026 * <p> 13027 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping. 13028 * 13029 * @see #setClipToOutline(boolean) 13030 * @see #getClipToOutline() 13031 * @see #getOutlineProvider() 13032 */ setOutlineProvider(ViewOutlineProvider provider)13033 public void setOutlineProvider(ViewOutlineProvider provider) { 13034 mOutlineProvider = provider; 13035 invalidateOutline(); 13036 } 13037 13038 /** 13039 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline 13040 * that defines the shape of the shadow it casts, and enables outline clipping. 13041 * 13042 * @see #setOutlineProvider(ViewOutlineProvider) 13043 */ getOutlineProvider()13044 public ViewOutlineProvider getOutlineProvider() { 13045 return mOutlineProvider; 13046 } 13047 13048 /** 13049 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider} 13050 * 13051 * @see #setOutlineProvider(ViewOutlineProvider) 13052 */ invalidateOutline()13053 public void invalidateOutline() { 13054 rebuildOutline(); 13055 13056 notifySubtreeAccessibilityStateChangedIfNeeded(); 13057 invalidateViewProperty(false, false); 13058 } 13059 13060 /** 13061 * Internal version of {@link #invalidateOutline()} which invalidates the 13062 * outline without invalidating the view itself. This is intended to be called from 13063 * within methods in the View class itself which are the result of the view being 13064 * invalidated already. For example, when we are drawing the background of a View, 13065 * we invalidate the outline in case it changed in the meantime, but we do not 13066 * need to invalidate the view because we're already drawing the background as part 13067 * of drawing the view in response to an earlier invalidation of the view. 13068 */ rebuildOutline()13069 private void rebuildOutline() { 13070 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow() 13071 if (mAttachInfo == null) return; 13072 13073 if (mOutlineProvider == null) { 13074 // no provider, remove outline 13075 mRenderNode.setOutline(null); 13076 } else { 13077 final Outline outline = mAttachInfo.mTmpOutline; 13078 outline.setEmpty(); 13079 outline.setAlpha(1.0f); 13080 13081 mOutlineProvider.getOutline(this, outline); 13082 mRenderNode.setOutline(outline); 13083 } 13084 } 13085 13086 /** 13087 * HierarchyViewer only 13088 * 13089 * @hide 13090 */ 13091 @ViewDebug.ExportedProperty(category = "drawing") hasShadow()13092 public boolean hasShadow() { 13093 return mRenderNode.hasShadow(); 13094 } 13095 13096 13097 /** @hide */ setRevealClip(boolean shouldClip, float x, float y, float radius)13098 public void setRevealClip(boolean shouldClip, float x, float y, float radius) { 13099 mRenderNode.setRevealClip(shouldClip, x, y, radius); 13100 invalidateViewProperty(false, false); 13101 } 13102 13103 /** 13104 * Hit rectangle in parent's coordinates 13105 * 13106 * @param outRect The hit rectangle of the view. 13107 */ getHitRect(Rect outRect)13108 public void getHitRect(Rect outRect) { 13109 if (hasIdentityMatrix() || mAttachInfo == null) { 13110 outRect.set(mLeft, mTop, mRight, mBottom); 13111 } else { 13112 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 13113 tmpRect.set(0, 0, getWidth(), getHeight()); 13114 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) 13115 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 13116 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 13117 } 13118 } 13119 13120 /** 13121 * Determines whether the given point, in local coordinates is inside the view. 13122 */ pointInView(float localX, float localY)13123 /*package*/ final boolean pointInView(float localX, float localY) { 13124 return pointInView(localX, localY, 0); 13125 } 13126 13127 /** 13128 * Utility method to determine whether the given point, in local coordinates, 13129 * is inside the view, where the area of the view is expanded by the slop factor. 13130 * This method is called while processing touch-move events to determine if the event 13131 * is still within the view. 13132 * 13133 * @hide 13134 */ pointInView(float localX, float localY, float slop)13135 public boolean pointInView(float localX, float localY, float slop) { 13136 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 13137 localY < ((mBottom - mTop) + slop); 13138 } 13139 13140 /** 13141 * When a view has focus and the user navigates away from it, the next view is searched for 13142 * starting from the rectangle filled in by this method. 13143 * 13144 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 13145 * of the view. However, if your view maintains some idea of internal selection, 13146 * such as a cursor, or a selected row or column, you should override this method and 13147 * fill in a more specific rectangle. 13148 * 13149 * @param r The rectangle to fill in, in this view's coordinates. 13150 */ getFocusedRect(Rect r)13151 public void getFocusedRect(Rect r) { 13152 getDrawingRect(r); 13153 } 13154 13155 /** 13156 * If some part of this view is not clipped by any of its parents, then 13157 * return that area in r in global (root) coordinates. To convert r to local 13158 * coordinates (without taking possible View rotations into account), offset 13159 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 13160 * If the view is completely clipped or translated out, return false. 13161 * 13162 * @param r If true is returned, r holds the global coordinates of the 13163 * visible portion of this view. 13164 * @param globalOffset If true is returned, globalOffset holds the dx,dy 13165 * between this view and its root. globalOffet may be null. 13166 * @return true if r is non-empty (i.e. part of the view is visible at the 13167 * root level. 13168 */ getGlobalVisibleRect(Rect r, Point globalOffset)13169 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 13170 int width = mRight - mLeft; 13171 int height = mBottom - mTop; 13172 if (width > 0 && height > 0) { 13173 r.set(0, 0, width, height); 13174 if (globalOffset != null) { 13175 globalOffset.set(-mScrollX, -mScrollY); 13176 } 13177 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 13178 } 13179 return false; 13180 } 13181 getGlobalVisibleRect(Rect r)13182 public final boolean getGlobalVisibleRect(Rect r) { 13183 return getGlobalVisibleRect(r, null); 13184 } 13185 getLocalVisibleRect(Rect r)13186 public final boolean getLocalVisibleRect(Rect r) { 13187 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 13188 if (getGlobalVisibleRect(r, offset)) { 13189 r.offset(-offset.x, -offset.y); // make r local 13190 return true; 13191 } 13192 return false; 13193 } 13194 13195 /** 13196 * Offset this view's vertical location by the specified number of pixels. 13197 * 13198 * @param offset the number of pixels to offset the view by 13199 */ offsetTopAndBottom(int offset)13200 public void offsetTopAndBottom(int offset) { 13201 if (offset != 0) { 13202 final boolean matrixIsIdentity = hasIdentityMatrix(); 13203 if (matrixIsIdentity) { 13204 if (isHardwareAccelerated()) { 13205 invalidateViewProperty(false, false); 13206 } else { 13207 final ViewParent p = mParent; 13208 if (p != null && mAttachInfo != null) { 13209 final Rect r = mAttachInfo.mTmpInvalRect; 13210 int minTop; 13211 int maxBottom; 13212 int yLoc; 13213 if (offset < 0) { 13214 minTop = mTop + offset; 13215 maxBottom = mBottom; 13216 yLoc = offset; 13217 } else { 13218 minTop = mTop; 13219 maxBottom = mBottom + offset; 13220 yLoc = 0; 13221 } 13222 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 13223 p.invalidateChild(this, r); 13224 } 13225 } 13226 } else { 13227 invalidateViewProperty(false, false); 13228 } 13229 13230 mTop += offset; 13231 mBottom += offset; 13232 mRenderNode.offsetTopAndBottom(offset); 13233 if (isHardwareAccelerated()) { 13234 invalidateViewProperty(false, false); 13235 invalidateParentIfNeededAndWasQuickRejected(); 13236 } else { 13237 if (!matrixIsIdentity) { 13238 invalidateViewProperty(false, true); 13239 } 13240 invalidateParentIfNeeded(); 13241 } 13242 notifySubtreeAccessibilityStateChangedIfNeeded(); 13243 } 13244 } 13245 13246 /** 13247 * Offset this view's horizontal location by the specified amount of pixels. 13248 * 13249 * @param offset the number of pixels to offset the view by 13250 */ offsetLeftAndRight(int offset)13251 public void offsetLeftAndRight(int offset) { 13252 if (offset != 0) { 13253 final boolean matrixIsIdentity = hasIdentityMatrix(); 13254 if (matrixIsIdentity) { 13255 if (isHardwareAccelerated()) { 13256 invalidateViewProperty(false, false); 13257 } else { 13258 final ViewParent p = mParent; 13259 if (p != null && mAttachInfo != null) { 13260 final Rect r = mAttachInfo.mTmpInvalRect; 13261 int minLeft; 13262 int maxRight; 13263 if (offset < 0) { 13264 minLeft = mLeft + offset; 13265 maxRight = mRight; 13266 } else { 13267 minLeft = mLeft; 13268 maxRight = mRight + offset; 13269 } 13270 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 13271 p.invalidateChild(this, r); 13272 } 13273 } 13274 } else { 13275 invalidateViewProperty(false, false); 13276 } 13277 13278 mLeft += offset; 13279 mRight += offset; 13280 mRenderNode.offsetLeftAndRight(offset); 13281 if (isHardwareAccelerated()) { 13282 invalidateViewProperty(false, false); 13283 invalidateParentIfNeededAndWasQuickRejected(); 13284 } else { 13285 if (!matrixIsIdentity) { 13286 invalidateViewProperty(false, true); 13287 } 13288 invalidateParentIfNeeded(); 13289 } 13290 notifySubtreeAccessibilityStateChangedIfNeeded(); 13291 } 13292 } 13293 13294 /** 13295 * Get the LayoutParams associated with this view. All views should have 13296 * layout parameters. These supply parameters to the <i>parent</i> of this 13297 * view specifying how it should be arranged. There are many subclasses of 13298 * ViewGroup.LayoutParams, and these correspond to the different subclasses 13299 * of ViewGroup that are responsible for arranging their children. 13300 * 13301 * This method may return null if this View is not attached to a parent 13302 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 13303 * was not invoked successfully. When a View is attached to a parent 13304 * ViewGroup, this method must not return null. 13305 * 13306 * @return The LayoutParams associated with this view, or null if no 13307 * parameters have been set yet 13308 */ 13309 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") getLayoutParams()13310 public ViewGroup.LayoutParams getLayoutParams() { 13311 return mLayoutParams; 13312 } 13313 13314 /** 13315 * Set the layout parameters associated with this view. These supply 13316 * parameters to the <i>parent</i> of this view specifying how it should be 13317 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 13318 * correspond to the different subclasses of ViewGroup that are responsible 13319 * for arranging their children. 13320 * 13321 * @param params The layout parameters for this view, cannot be null 13322 */ setLayoutParams(ViewGroup.LayoutParams params)13323 public void setLayoutParams(ViewGroup.LayoutParams params) { 13324 if (params == null) { 13325 throw new NullPointerException("Layout parameters cannot be null"); 13326 } 13327 mLayoutParams = params; 13328 resolveLayoutParams(); 13329 if (mParent instanceof ViewGroup) { 13330 ((ViewGroup) mParent).onSetLayoutParams(this, params); 13331 } 13332 requestLayout(); 13333 } 13334 13335 /** 13336 * Resolve the layout parameters depending on the resolved layout direction 13337 * 13338 * @hide 13339 */ resolveLayoutParams()13340 public void resolveLayoutParams() { 13341 if (mLayoutParams != null) { 13342 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 13343 } 13344 } 13345 13346 /** 13347 * Set the scrolled position of your view. This will cause a call to 13348 * {@link #onScrollChanged(int, int, int, int)} and the view will be 13349 * invalidated. 13350 * @param x the x position to scroll to 13351 * @param y the y position to scroll to 13352 */ scrollTo(int x, int y)13353 public void scrollTo(int x, int y) { 13354 if (mScrollX != x || mScrollY != y) { 13355 int oldX = mScrollX; 13356 int oldY = mScrollY; 13357 mScrollX = x; 13358 mScrollY = y; 13359 invalidateParentCaches(); 13360 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 13361 if (!awakenScrollBars()) { 13362 postInvalidateOnAnimation(); 13363 } 13364 } 13365 } 13366 13367 /** 13368 * Move the scrolled position of your view. This will cause a call to 13369 * {@link #onScrollChanged(int, int, int, int)} and the view will be 13370 * invalidated. 13371 * @param x the amount of pixels to scroll by horizontally 13372 * @param y the amount of pixels to scroll by vertically 13373 */ scrollBy(int x, int y)13374 public void scrollBy(int x, int y) { 13375 scrollTo(mScrollX + x, mScrollY + y); 13376 } 13377 13378 /** 13379 * <p>Trigger the scrollbars to draw. When invoked this method starts an 13380 * animation to fade the scrollbars out after a default delay. If a subclass 13381 * provides animated scrolling, the start delay should equal the duration 13382 * of the scrolling animation.</p> 13383 * 13384 * <p>The animation starts only if at least one of the scrollbars is 13385 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 13386 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13387 * this method returns true, and false otherwise. If the animation is 13388 * started, this method calls {@link #invalidate()}; in that case the 13389 * caller should not call {@link #invalidate()}.</p> 13390 * 13391 * <p>This method should be invoked every time a subclass directly updates 13392 * the scroll parameters.</p> 13393 * 13394 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 13395 * and {@link #scrollTo(int, int)}.</p> 13396 * 13397 * @return true if the animation is played, false otherwise 13398 * 13399 * @see #awakenScrollBars(int) 13400 * @see #scrollBy(int, int) 13401 * @see #scrollTo(int, int) 13402 * @see #isHorizontalScrollBarEnabled() 13403 * @see #isVerticalScrollBarEnabled() 13404 * @see #setHorizontalScrollBarEnabled(boolean) 13405 * @see #setVerticalScrollBarEnabled(boolean) 13406 */ awakenScrollBars()13407 protected boolean awakenScrollBars() { 13408 return mScrollCache != null && 13409 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 13410 } 13411 13412 /** 13413 * Trigger the scrollbars to draw. 13414 * This method differs from awakenScrollBars() only in its default duration. 13415 * initialAwakenScrollBars() will show the scroll bars for longer than 13416 * usual to give the user more of a chance to notice them. 13417 * 13418 * @return true if the animation is played, false otherwise. 13419 */ initialAwakenScrollBars()13420 private boolean initialAwakenScrollBars() { 13421 return mScrollCache != null && 13422 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 13423 } 13424 13425 /** 13426 * <p> 13427 * Trigger the scrollbars to draw. When invoked this method starts an 13428 * animation to fade the scrollbars out after a fixed delay. If a subclass 13429 * provides animated scrolling, the start delay should equal the duration of 13430 * the scrolling animation. 13431 * </p> 13432 * 13433 * <p> 13434 * The animation starts only if at least one of the scrollbars is enabled, 13435 * as specified by {@link #isHorizontalScrollBarEnabled()} and 13436 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13437 * this method returns true, and false otherwise. If the animation is 13438 * started, this method calls {@link #invalidate()}; in that case the caller 13439 * should not call {@link #invalidate()}. 13440 * </p> 13441 * 13442 * <p> 13443 * This method should be invoked every time a subclass directly updates the 13444 * scroll parameters. 13445 * </p> 13446 * 13447 * @param startDelay the delay, in milliseconds, after which the animation 13448 * should start; when the delay is 0, the animation starts 13449 * immediately 13450 * @return true if the animation is played, false otherwise 13451 * 13452 * @see #scrollBy(int, int) 13453 * @see #scrollTo(int, int) 13454 * @see #isHorizontalScrollBarEnabled() 13455 * @see #isVerticalScrollBarEnabled() 13456 * @see #setHorizontalScrollBarEnabled(boolean) 13457 * @see #setVerticalScrollBarEnabled(boolean) 13458 */ awakenScrollBars(int startDelay)13459 protected boolean awakenScrollBars(int startDelay) { 13460 return awakenScrollBars(startDelay, true); 13461 } 13462 13463 /** 13464 * <p> 13465 * Trigger the scrollbars to draw. When invoked this method starts an 13466 * animation to fade the scrollbars out after a fixed delay. If a subclass 13467 * provides animated scrolling, the start delay should equal the duration of 13468 * the scrolling animation. 13469 * </p> 13470 * 13471 * <p> 13472 * The animation starts only if at least one of the scrollbars is enabled, 13473 * as specified by {@link #isHorizontalScrollBarEnabled()} and 13474 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 13475 * this method returns true, and false otherwise. If the animation is 13476 * started, this method calls {@link #invalidate()} if the invalidate parameter 13477 * is set to true; in that case the caller 13478 * should not call {@link #invalidate()}. 13479 * </p> 13480 * 13481 * <p> 13482 * This method should be invoked every time a subclass directly updates the 13483 * scroll parameters. 13484 * </p> 13485 * 13486 * @param startDelay the delay, in milliseconds, after which the animation 13487 * should start; when the delay is 0, the animation starts 13488 * immediately 13489 * 13490 * @param invalidate Whether this method should call invalidate 13491 * 13492 * @return true if the animation is played, false otherwise 13493 * 13494 * @see #scrollBy(int, int) 13495 * @see #scrollTo(int, int) 13496 * @see #isHorizontalScrollBarEnabled() 13497 * @see #isVerticalScrollBarEnabled() 13498 * @see #setHorizontalScrollBarEnabled(boolean) 13499 * @see #setVerticalScrollBarEnabled(boolean) 13500 */ awakenScrollBars(int startDelay, boolean invalidate)13501 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 13502 final ScrollabilityCache scrollCache = mScrollCache; 13503 13504 if (scrollCache == null || !scrollCache.fadeScrollBars) { 13505 return false; 13506 } 13507 13508 if (scrollCache.scrollBar == null) { 13509 scrollCache.scrollBar = new ScrollBarDrawable(); 13510 scrollCache.scrollBar.setState(getDrawableState()); 13511 scrollCache.scrollBar.setCallback(this); 13512 } 13513 13514 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 13515 13516 if (invalidate) { 13517 // Invalidate to show the scrollbars 13518 postInvalidateOnAnimation(); 13519 } 13520 13521 if (scrollCache.state == ScrollabilityCache.OFF) { 13522 // FIXME: this is copied from WindowManagerService. 13523 // We should get this value from the system when it 13524 // is possible to do so. 13525 final int KEY_REPEAT_FIRST_DELAY = 750; 13526 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 13527 } 13528 13529 // Tell mScrollCache when we should start fading. This may 13530 // extend the fade start time if one was already scheduled 13531 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 13532 scrollCache.fadeStartTime = fadeStartTime; 13533 scrollCache.state = ScrollabilityCache.ON; 13534 13535 // Schedule our fader to run, unscheduling any old ones first 13536 if (mAttachInfo != null) { 13537 mAttachInfo.mHandler.removeCallbacks(scrollCache); 13538 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 13539 } 13540 13541 return true; 13542 } 13543 13544 return false; 13545 } 13546 13547 /** 13548 * Do not invalidate views which are not visible and which are not running an animation. They 13549 * will not get drawn and they should not set dirty flags as if they will be drawn 13550 */ skipInvalidate()13551 private boolean skipInvalidate() { 13552 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 13553 (!(mParent instanceof ViewGroup) || 13554 !((ViewGroup) mParent).isViewTransitioning(this)); 13555 } 13556 13557 /** 13558 * Mark the area defined by dirty as needing to be drawn. If the view is 13559 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 13560 * point in the future. 13561 * <p> 13562 * This must be called from a UI thread. To call from a non-UI thread, call 13563 * {@link #postInvalidate()}. 13564 * <p> 13565 * <b>WARNING:</b> In API 19 and below, this method may be destructive to 13566 * {@code dirty}. 13567 * 13568 * @param dirty the rectangle representing the bounds of the dirty region 13569 */ invalidate(Rect dirty)13570 public void invalidate(Rect dirty) { 13571 final int scrollX = mScrollX; 13572 final int scrollY = mScrollY; 13573 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, 13574 dirty.right - scrollX, dirty.bottom - scrollY, true, false); 13575 } 13576 13577 /** 13578 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The 13579 * coordinates of the dirty rect are relative to the view. If the view is 13580 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 13581 * point in the future. 13582 * <p> 13583 * This must be called from a UI thread. To call from a non-UI thread, call 13584 * {@link #postInvalidate()}. 13585 * 13586 * @param l the left position of the dirty region 13587 * @param t the top position of the dirty region 13588 * @param r the right position of the dirty region 13589 * @param b the bottom position of the dirty region 13590 */ invalidate(int l, int t, int r, int b)13591 public void invalidate(int l, int t, int r, int b) { 13592 final int scrollX = mScrollX; 13593 final int scrollY = mScrollY; 13594 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false); 13595 } 13596 13597 /** 13598 * Invalidate the whole view. If the view is visible, 13599 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 13600 * the future. 13601 * <p> 13602 * This must be called from a UI thread. To call from a non-UI thread, call 13603 * {@link #postInvalidate()}. 13604 */ invalidate()13605 public void invalidate() { 13606 invalidate(true); 13607 } 13608 13609 /** 13610 * This is where the invalidate() work actually happens. A full invalidate() 13611 * causes the drawing cache to be invalidated, but this function can be 13612 * called with invalidateCache set to false to skip that invalidation step 13613 * for cases that do not need it (for example, a component that remains at 13614 * the same dimensions with the same content). 13615 * 13616 * @param invalidateCache Whether the drawing cache for this view should be 13617 * invalidated as well. This is usually true for a full 13618 * invalidate, but may be set to false if the View's contents or 13619 * dimensions have not changed. 13620 */ invalidate(boolean invalidateCache)13621 void invalidate(boolean invalidateCache) { 13622 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 13623 } 13624 invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate)13625 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, 13626 boolean fullInvalidate) { 13627 if (mGhostView != null) { 13628 mGhostView.invalidate(true); 13629 return; 13630 } 13631 13632 if (skipInvalidate()) { 13633 return; 13634 } 13635 13636 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) 13637 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) 13638 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED 13639 || (fullInvalidate && isOpaque() != mLastIsOpaque)) { 13640 if (fullInvalidate) { 13641 mLastIsOpaque = isOpaque(); 13642 mPrivateFlags &= ~PFLAG_DRAWN; 13643 } 13644 13645 mPrivateFlags |= PFLAG_DIRTY; 13646 13647 if (invalidateCache) { 13648 mPrivateFlags |= PFLAG_INVALIDATED; 13649 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 13650 } 13651 13652 // Propagate the damage rectangle to the parent view. 13653 final AttachInfo ai = mAttachInfo; 13654 final ViewParent p = mParent; 13655 if (p != null && ai != null && l < r && t < b) { 13656 final Rect damage = ai.mTmpInvalRect; 13657 damage.set(l, t, r, b); 13658 p.invalidateChild(this, damage); 13659 } 13660 13661 // Damage the entire projection receiver, if necessary. 13662 if (mBackground != null && mBackground.isProjected()) { 13663 final View receiver = getProjectionReceiver(); 13664 if (receiver != null) { 13665 receiver.damageInParent(); 13666 } 13667 } 13668 13669 // Damage the entire IsolatedZVolume receiving this view's shadow. 13670 if (isHardwareAccelerated() && getZ() != 0) { 13671 damageShadowReceiver(); 13672 } 13673 } 13674 } 13675 13676 /** 13677 * @return this view's projection receiver, or {@code null} if none exists 13678 */ getProjectionReceiver()13679 private View getProjectionReceiver() { 13680 ViewParent p = getParent(); 13681 while (p != null && p instanceof View) { 13682 final View v = (View) p; 13683 if (v.isProjectionReceiver()) { 13684 return v; 13685 } 13686 p = p.getParent(); 13687 } 13688 13689 return null; 13690 } 13691 13692 /** 13693 * @return whether the view is a projection receiver 13694 */ isProjectionReceiver()13695 private boolean isProjectionReceiver() { 13696 return mBackground != null; 13697 } 13698 13699 /** 13700 * Damage area of the screen that can be covered by this View's shadow. 13701 * 13702 * This method will guarantee that any changes to shadows cast by a View 13703 * are damaged on the screen for future redraw. 13704 */ damageShadowReceiver()13705 private void damageShadowReceiver() { 13706 final AttachInfo ai = mAttachInfo; 13707 if (ai != null) { 13708 ViewParent p = getParent(); 13709 if (p != null && p instanceof ViewGroup) { 13710 final ViewGroup vg = (ViewGroup) p; 13711 vg.damageInParent(); 13712 } 13713 } 13714 } 13715 13716 /** 13717 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 13718 * set any flags or handle all of the cases handled by the default invalidation methods. 13719 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 13720 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 13721 * walk up the hierarchy, transforming the dirty rect as necessary. 13722 * 13723 * The method also handles normal invalidation logic if display list properties are not 13724 * being used in this view. The invalidateParent and forceRedraw flags are used by that 13725 * backup approach, to handle these cases used in the various property-setting methods. 13726 * 13727 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 13728 * are not being used in this view 13729 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 13730 * list properties are not being used in this view 13731 */ invalidateViewProperty(boolean invalidateParent, boolean forceRedraw)13732 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 13733 if (!isHardwareAccelerated() 13734 || !mRenderNode.isValid() 13735 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { 13736 if (invalidateParent) { 13737 invalidateParentCaches(); 13738 } 13739 if (forceRedraw) { 13740 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 13741 } 13742 invalidate(false); 13743 } else { 13744 damageInParent(); 13745 } 13746 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) { 13747 damageShadowReceiver(); 13748 } 13749 } 13750 13751 /** 13752 * Tells the parent view to damage this view's bounds. 13753 * 13754 * @hide 13755 */ damageInParent()13756 protected void damageInParent() { 13757 final AttachInfo ai = mAttachInfo; 13758 final ViewParent p = mParent; 13759 if (p != null && ai != null) { 13760 final Rect r = ai.mTmpInvalRect; 13761 r.set(0, 0, mRight - mLeft, mBottom - mTop); 13762 if (mParent instanceof ViewGroup) { 13763 ((ViewGroup) mParent).damageChild(this, r); 13764 } else { 13765 mParent.invalidateChild(this, r); 13766 } 13767 } 13768 } 13769 13770 /** 13771 * Utility method to transform a given Rect by the current matrix of this view. 13772 */ transformRect(final Rect rect)13773 void transformRect(final Rect rect) { 13774 if (!getMatrix().isIdentity()) { 13775 RectF boundingRect = mAttachInfo.mTmpTransformRect; 13776 boundingRect.set(rect); 13777 getMatrix().mapRect(boundingRect); 13778 rect.set((int) Math.floor(boundingRect.left), 13779 (int) Math.floor(boundingRect.top), 13780 (int) Math.ceil(boundingRect.right), 13781 (int) Math.ceil(boundingRect.bottom)); 13782 } 13783 } 13784 13785 /** 13786 * Used to indicate that the parent of this view should clear its caches. This functionality 13787 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13788 * which is necessary when various parent-managed properties of the view change, such as 13789 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 13790 * clears the parent caches and does not causes an invalidate event. 13791 * 13792 * @hide 13793 */ invalidateParentCaches()13794 protected void invalidateParentCaches() { 13795 if (mParent instanceof View) { 13796 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 13797 } 13798 } 13799 13800 /** 13801 * Used to indicate that the parent of this view should be invalidated. This functionality 13802 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13803 * which is necessary when various parent-managed properties of the view change, such as 13804 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 13805 * an invalidation event to the parent. 13806 * 13807 * @hide 13808 */ invalidateParentIfNeeded()13809 protected void invalidateParentIfNeeded() { 13810 if (isHardwareAccelerated() && mParent instanceof View) { 13811 ((View) mParent).invalidate(true); 13812 } 13813 } 13814 13815 /** 13816 * @hide 13817 */ invalidateParentIfNeededAndWasQuickRejected()13818 protected void invalidateParentIfNeededAndWasQuickRejected() { 13819 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { 13820 // View was rejected last time it was drawn by its parent; this may have changed 13821 invalidateParentIfNeeded(); 13822 } 13823 } 13824 13825 /** 13826 * Indicates whether this View is opaque. An opaque View guarantees that it will 13827 * draw all the pixels overlapping its bounds using a fully opaque color. 13828 * 13829 * Subclasses of View should override this method whenever possible to indicate 13830 * whether an instance is opaque. Opaque Views are treated in a special way by 13831 * the View hierarchy, possibly allowing it to perform optimizations during 13832 * invalidate/draw passes. 13833 * 13834 * @return True if this View is guaranteed to be fully opaque, false otherwise. 13835 */ 13836 @ViewDebug.ExportedProperty(category = "drawing") isOpaque()13837 public boolean isOpaque() { 13838 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 13839 getFinalAlpha() >= 1.0f; 13840 } 13841 13842 /** 13843 * @hide 13844 */ computeOpaqueFlags()13845 protected void computeOpaqueFlags() { 13846 // Opaque if: 13847 // - Has a background 13848 // - Background is opaque 13849 // - Doesn't have scrollbars or scrollbars overlay 13850 13851 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 13852 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 13853 } else { 13854 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 13855 } 13856 13857 final int flags = mViewFlags; 13858 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 13859 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 13860 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 13861 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 13862 } else { 13863 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 13864 } 13865 } 13866 13867 /** 13868 * @hide 13869 */ hasOpaqueScrollbars()13870 protected boolean hasOpaqueScrollbars() { 13871 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 13872 } 13873 13874 /** 13875 * @return A handler associated with the thread running the View. This 13876 * handler can be used to pump events in the UI events queue. 13877 */ getHandler()13878 public Handler getHandler() { 13879 final AttachInfo attachInfo = mAttachInfo; 13880 if (attachInfo != null) { 13881 return attachInfo.mHandler; 13882 } 13883 return null; 13884 } 13885 13886 /** 13887 * Returns the queue of runnable for this view. 13888 * 13889 * @return the queue of runnables for this view 13890 */ getRunQueue()13891 private HandlerActionQueue getRunQueue() { 13892 if (mRunQueue == null) { 13893 mRunQueue = new HandlerActionQueue(); 13894 } 13895 return mRunQueue; 13896 } 13897 13898 /** 13899 * Gets the view root associated with the View. 13900 * @return The view root, or null if none. 13901 * @hide 13902 */ getViewRootImpl()13903 public ViewRootImpl getViewRootImpl() { 13904 if (mAttachInfo != null) { 13905 return mAttachInfo.mViewRootImpl; 13906 } 13907 return null; 13908 } 13909 13910 /** 13911 * @hide 13912 */ getHardwareRenderer()13913 public ThreadedRenderer getHardwareRenderer() { 13914 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null; 13915 } 13916 13917 /** 13918 * <p>Causes the Runnable to be added to the message queue. 13919 * The runnable will be run on the user interface thread.</p> 13920 * 13921 * @param action The Runnable that will be executed. 13922 * 13923 * @return Returns true if the Runnable was successfully placed in to the 13924 * message queue. Returns false on failure, usually because the 13925 * looper processing the message queue is exiting. 13926 * 13927 * @see #postDelayed 13928 * @see #removeCallbacks 13929 */ post(Runnable action)13930 public boolean post(Runnable action) { 13931 final AttachInfo attachInfo = mAttachInfo; 13932 if (attachInfo != null) { 13933 return attachInfo.mHandler.post(action); 13934 } 13935 13936 // Postpone the runnable until we know on which thread it needs to run. 13937 // Assume that the runnable will be successfully placed after attach. 13938 getRunQueue().post(action); 13939 return true; 13940 } 13941 13942 /** 13943 * <p>Causes the Runnable to be added to the message queue, to be run 13944 * after the specified amount of time elapses. 13945 * The runnable will be run on the user interface thread.</p> 13946 * 13947 * @param action The Runnable that will be executed. 13948 * @param delayMillis The delay (in milliseconds) until the Runnable 13949 * will be executed. 13950 * 13951 * @return true if the Runnable was successfully placed in to the 13952 * message queue. Returns false on failure, usually because the 13953 * looper processing the message queue is exiting. Note that a 13954 * result of true does not mean the Runnable will be processed -- 13955 * if the looper is quit before the delivery time of the message 13956 * occurs then the message will be dropped. 13957 * 13958 * @see #post 13959 * @see #removeCallbacks 13960 */ postDelayed(Runnable action, long delayMillis)13961 public boolean postDelayed(Runnable action, long delayMillis) { 13962 final AttachInfo attachInfo = mAttachInfo; 13963 if (attachInfo != null) { 13964 return attachInfo.mHandler.postDelayed(action, delayMillis); 13965 } 13966 13967 // Postpone the runnable until we know on which thread it needs to run. 13968 // Assume that the runnable will be successfully placed after attach. 13969 getRunQueue().postDelayed(action, delayMillis); 13970 return true; 13971 } 13972 13973 /** 13974 * <p>Causes the Runnable to execute on the next animation time step. 13975 * The runnable will be run on the user interface thread.</p> 13976 * 13977 * @param action The Runnable that will be executed. 13978 * 13979 * @see #postOnAnimationDelayed 13980 * @see #removeCallbacks 13981 */ postOnAnimation(Runnable action)13982 public void postOnAnimation(Runnable action) { 13983 final AttachInfo attachInfo = mAttachInfo; 13984 if (attachInfo != null) { 13985 attachInfo.mViewRootImpl.mChoreographer.postCallback( 13986 Choreographer.CALLBACK_ANIMATION, action, null); 13987 } else { 13988 // Postpone the runnable until we know 13989 // on which thread it needs to run. 13990 getRunQueue().post(action); 13991 } 13992 } 13993 13994 /** 13995 * <p>Causes the Runnable to execute on the next animation time step, 13996 * after the specified amount of time elapses. 13997 * The runnable will be run on the user interface thread.</p> 13998 * 13999 * @param action The Runnable that will be executed. 14000 * @param delayMillis The delay (in milliseconds) until the Runnable 14001 * will be executed. 14002 * 14003 * @see #postOnAnimation 14004 * @see #removeCallbacks 14005 */ postOnAnimationDelayed(Runnable action, long delayMillis)14006 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 14007 final AttachInfo attachInfo = mAttachInfo; 14008 if (attachInfo != null) { 14009 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 14010 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 14011 } else { 14012 // Postpone the runnable until we know 14013 // on which thread it needs to run. 14014 getRunQueue().postDelayed(action, delayMillis); 14015 } 14016 } 14017 14018 /** 14019 * <p>Removes the specified Runnable from the message queue.</p> 14020 * 14021 * @param action The Runnable to remove from the message handling queue 14022 * 14023 * @return true if this view could ask the Handler to remove the Runnable, 14024 * false otherwise. When the returned value is true, the Runnable 14025 * may or may not have been actually removed from the message queue 14026 * (for instance, if the Runnable was not in the queue already.) 14027 * 14028 * @see #post 14029 * @see #postDelayed 14030 * @see #postOnAnimation 14031 * @see #postOnAnimationDelayed 14032 */ removeCallbacks(Runnable action)14033 public boolean removeCallbacks(Runnable action) { 14034 if (action != null) { 14035 final AttachInfo attachInfo = mAttachInfo; 14036 if (attachInfo != null) { 14037 attachInfo.mHandler.removeCallbacks(action); 14038 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 14039 Choreographer.CALLBACK_ANIMATION, action, null); 14040 } 14041 getRunQueue().removeCallbacks(action); 14042 } 14043 return true; 14044 } 14045 14046 /** 14047 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 14048 * Use this to invalidate the View from a non-UI thread.</p> 14049 * 14050 * <p>This method can be invoked from outside of the UI thread 14051 * only when this View is attached to a window.</p> 14052 * 14053 * @see #invalidate() 14054 * @see #postInvalidateDelayed(long) 14055 */ postInvalidate()14056 public void postInvalidate() { 14057 postInvalidateDelayed(0); 14058 } 14059 14060 /** 14061 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 14062 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 14063 * 14064 * <p>This method can be invoked from outside of the UI thread 14065 * only when this View is attached to a window.</p> 14066 * 14067 * @param left The left coordinate of the rectangle to invalidate. 14068 * @param top The top coordinate of the rectangle to invalidate. 14069 * @param right The right coordinate of the rectangle to invalidate. 14070 * @param bottom The bottom coordinate of the rectangle to invalidate. 14071 * 14072 * @see #invalidate(int, int, int, int) 14073 * @see #invalidate(Rect) 14074 * @see #postInvalidateDelayed(long, int, int, int, int) 14075 */ postInvalidate(int left, int top, int right, int bottom)14076 public void postInvalidate(int left, int top, int right, int bottom) { 14077 postInvalidateDelayed(0, left, top, right, bottom); 14078 } 14079 14080 /** 14081 * <p>Cause an invalidate to happen on a subsequent cycle through the event 14082 * loop. Waits for the specified amount of time.</p> 14083 * 14084 * <p>This method can be invoked from outside of the UI thread 14085 * only when this View is attached to a window.</p> 14086 * 14087 * @param delayMilliseconds the duration in milliseconds to delay the 14088 * invalidation by 14089 * 14090 * @see #invalidate() 14091 * @see #postInvalidate() 14092 */ postInvalidateDelayed(long delayMilliseconds)14093 public void postInvalidateDelayed(long delayMilliseconds) { 14094 // We try only with the AttachInfo because there's no point in invalidating 14095 // if we are not attached to our window 14096 final AttachInfo attachInfo = mAttachInfo; 14097 if (attachInfo != null) { 14098 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 14099 } 14100 } 14101 14102 /** 14103 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 14104 * through the event loop. Waits for the specified amount of time.</p> 14105 * 14106 * <p>This method can be invoked from outside of the UI thread 14107 * only when this View is attached to a window.</p> 14108 * 14109 * @param delayMilliseconds the duration in milliseconds to delay the 14110 * invalidation by 14111 * @param left The left coordinate of the rectangle to invalidate. 14112 * @param top The top coordinate of the rectangle to invalidate. 14113 * @param right The right coordinate of the rectangle to invalidate. 14114 * @param bottom The bottom coordinate of the rectangle to invalidate. 14115 * 14116 * @see #invalidate(int, int, int, int) 14117 * @see #invalidate(Rect) 14118 * @see #postInvalidate(int, int, int, int) 14119 */ postInvalidateDelayed(long delayMilliseconds, int left, int top, int right, int bottom)14120 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 14121 int right, int bottom) { 14122 14123 // We try only with the AttachInfo because there's no point in invalidating 14124 // if we are not attached to our window 14125 final AttachInfo attachInfo = mAttachInfo; 14126 if (attachInfo != null) { 14127 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 14128 info.target = this; 14129 info.left = left; 14130 info.top = top; 14131 info.right = right; 14132 info.bottom = bottom; 14133 14134 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 14135 } 14136 } 14137 14138 /** 14139 * <p>Cause an invalidate to happen on the next animation time step, typically the 14140 * next display frame.</p> 14141 * 14142 * <p>This method can be invoked from outside of the UI thread 14143 * only when this View is attached to a window.</p> 14144 * 14145 * @see #invalidate() 14146 */ postInvalidateOnAnimation()14147 public void postInvalidateOnAnimation() { 14148 // We try only with the AttachInfo because there's no point in invalidating 14149 // if we are not attached to our window 14150 final AttachInfo attachInfo = mAttachInfo; 14151 if (attachInfo != null) { 14152 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 14153 } 14154 } 14155 14156 /** 14157 * <p>Cause an invalidate of the specified area to happen on the next animation 14158 * time step, typically the next display frame.</p> 14159 * 14160 * <p>This method can be invoked from outside of the UI thread 14161 * only when this View is attached to a window.</p> 14162 * 14163 * @param left The left coordinate of the rectangle to invalidate. 14164 * @param top The top coordinate of the rectangle to invalidate. 14165 * @param right The right coordinate of the rectangle to invalidate. 14166 * @param bottom The bottom coordinate of the rectangle to invalidate. 14167 * 14168 * @see #invalidate(int, int, int, int) 14169 * @see #invalidate(Rect) 14170 */ postInvalidateOnAnimation(int left, int top, int right, int bottom)14171 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 14172 // We try only with the AttachInfo because there's no point in invalidating 14173 // if we are not attached to our window 14174 final AttachInfo attachInfo = mAttachInfo; 14175 if (attachInfo != null) { 14176 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 14177 info.target = this; 14178 info.left = left; 14179 info.top = top; 14180 info.right = right; 14181 info.bottom = bottom; 14182 14183 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 14184 } 14185 } 14186 14187 /** 14188 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 14189 * This event is sent at most once every 14190 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 14191 */ postSendViewScrolledAccessibilityEventCallback()14192 private void postSendViewScrolledAccessibilityEventCallback() { 14193 if (mSendViewScrolledAccessibilityEvent == null) { 14194 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 14195 } 14196 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 14197 mSendViewScrolledAccessibilityEvent.mIsPending = true; 14198 postDelayed(mSendViewScrolledAccessibilityEvent, 14199 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 14200 } 14201 } 14202 14203 /** 14204 * Called by a parent to request that a child update its values for mScrollX 14205 * and mScrollY if necessary. This will typically be done if the child is 14206 * animating a scroll using a {@link android.widget.Scroller Scroller} 14207 * object. 14208 */ computeScroll()14209 public void computeScroll() { 14210 } 14211 14212 /** 14213 * <p>Indicate whether the horizontal edges are faded when the view is 14214 * scrolled horizontally.</p> 14215 * 14216 * @return true if the horizontal edges should are faded on scroll, false 14217 * otherwise 14218 * 14219 * @see #setHorizontalFadingEdgeEnabled(boolean) 14220 * 14221 * @attr ref android.R.styleable#View_requiresFadingEdge 14222 */ isHorizontalFadingEdgeEnabled()14223 public boolean isHorizontalFadingEdgeEnabled() { 14224 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 14225 } 14226 14227 /** 14228 * <p>Define whether the horizontal edges should be faded when this view 14229 * is scrolled horizontally.</p> 14230 * 14231 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 14232 * be faded when the view is scrolled 14233 * horizontally 14234 * 14235 * @see #isHorizontalFadingEdgeEnabled() 14236 * 14237 * @attr ref android.R.styleable#View_requiresFadingEdge 14238 */ setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled)14239 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 14240 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 14241 if (horizontalFadingEdgeEnabled) { 14242 initScrollCache(); 14243 } 14244 14245 mViewFlags ^= FADING_EDGE_HORIZONTAL; 14246 } 14247 } 14248 14249 /** 14250 * <p>Indicate whether the vertical edges are faded when the view is 14251 * scrolled horizontally.</p> 14252 * 14253 * @return true if the vertical edges should are faded on scroll, false 14254 * otherwise 14255 * 14256 * @see #setVerticalFadingEdgeEnabled(boolean) 14257 * 14258 * @attr ref android.R.styleable#View_requiresFadingEdge 14259 */ isVerticalFadingEdgeEnabled()14260 public boolean isVerticalFadingEdgeEnabled() { 14261 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 14262 } 14263 14264 /** 14265 * <p>Define whether the vertical edges should be faded when this view 14266 * is scrolled vertically.</p> 14267 * 14268 * @param verticalFadingEdgeEnabled true if the vertical edges should 14269 * be faded when the view is scrolled 14270 * vertically 14271 * 14272 * @see #isVerticalFadingEdgeEnabled() 14273 * 14274 * @attr ref android.R.styleable#View_requiresFadingEdge 14275 */ setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled)14276 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 14277 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 14278 if (verticalFadingEdgeEnabled) { 14279 initScrollCache(); 14280 } 14281 14282 mViewFlags ^= FADING_EDGE_VERTICAL; 14283 } 14284 } 14285 14286 /** 14287 * Returns the strength, or intensity, of the top faded edge. The strength is 14288 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14289 * returns 0.0 or 1.0 but no value in between. 14290 * 14291 * Subclasses should override this method to provide a smoother fade transition 14292 * when scrolling occurs. 14293 * 14294 * @return the intensity of the top fade as a float between 0.0f and 1.0f 14295 */ getTopFadingEdgeStrength()14296 protected float getTopFadingEdgeStrength() { 14297 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 14298 } 14299 14300 /** 14301 * Returns the strength, or intensity, of the bottom faded edge. The strength is 14302 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14303 * returns 0.0 or 1.0 but no value in between. 14304 * 14305 * Subclasses should override this method to provide a smoother fade transition 14306 * when scrolling occurs. 14307 * 14308 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 14309 */ getBottomFadingEdgeStrength()14310 protected float getBottomFadingEdgeStrength() { 14311 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 14312 computeVerticalScrollRange() ? 1.0f : 0.0f; 14313 } 14314 14315 /** 14316 * Returns the strength, or intensity, of the left faded edge. The strength is 14317 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14318 * returns 0.0 or 1.0 but no value in between. 14319 * 14320 * Subclasses should override this method to provide a smoother fade transition 14321 * when scrolling occurs. 14322 * 14323 * @return the intensity of the left fade as a float between 0.0f and 1.0f 14324 */ getLeftFadingEdgeStrength()14325 protected float getLeftFadingEdgeStrength() { 14326 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 14327 } 14328 14329 /** 14330 * Returns the strength, or intensity, of the right faded edge. The strength is 14331 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 14332 * returns 0.0 or 1.0 but no value in between. 14333 * 14334 * Subclasses should override this method to provide a smoother fade transition 14335 * when scrolling occurs. 14336 * 14337 * @return the intensity of the right fade as a float between 0.0f and 1.0f 14338 */ getRightFadingEdgeStrength()14339 protected float getRightFadingEdgeStrength() { 14340 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 14341 computeHorizontalScrollRange() ? 1.0f : 0.0f; 14342 } 14343 14344 /** 14345 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 14346 * scrollbar is not drawn by default.</p> 14347 * 14348 * @return true if the horizontal scrollbar should be painted, false 14349 * otherwise 14350 * 14351 * @see #setHorizontalScrollBarEnabled(boolean) 14352 */ isHorizontalScrollBarEnabled()14353 public boolean isHorizontalScrollBarEnabled() { 14354 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 14355 } 14356 14357 /** 14358 * <p>Define whether the horizontal scrollbar should be drawn or not. The 14359 * scrollbar is not drawn by default.</p> 14360 * 14361 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 14362 * be painted 14363 * 14364 * @see #isHorizontalScrollBarEnabled() 14365 */ setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled)14366 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 14367 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 14368 mViewFlags ^= SCROLLBARS_HORIZONTAL; 14369 computeOpaqueFlags(); 14370 resolvePadding(); 14371 } 14372 } 14373 14374 /** 14375 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 14376 * scrollbar is not drawn by default.</p> 14377 * 14378 * @return true if the vertical scrollbar should be painted, false 14379 * otherwise 14380 * 14381 * @see #setVerticalScrollBarEnabled(boolean) 14382 */ isVerticalScrollBarEnabled()14383 public boolean isVerticalScrollBarEnabled() { 14384 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 14385 } 14386 14387 /** 14388 * <p>Define whether the vertical scrollbar should be drawn or not. The 14389 * scrollbar is not drawn by default.</p> 14390 * 14391 * @param verticalScrollBarEnabled true if the vertical scrollbar should 14392 * be painted 14393 * 14394 * @see #isVerticalScrollBarEnabled() 14395 */ setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled)14396 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 14397 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 14398 mViewFlags ^= SCROLLBARS_VERTICAL; 14399 computeOpaqueFlags(); 14400 resolvePadding(); 14401 } 14402 } 14403 14404 /** 14405 * @hide 14406 */ recomputePadding()14407 protected void recomputePadding() { 14408 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 14409 } 14410 14411 /** 14412 * Define whether scrollbars will fade when the view is not scrolling. 14413 * 14414 * @param fadeScrollbars whether to enable fading 14415 * 14416 * @attr ref android.R.styleable#View_fadeScrollbars 14417 */ setScrollbarFadingEnabled(boolean fadeScrollbars)14418 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 14419 initScrollCache(); 14420 final ScrollabilityCache scrollabilityCache = mScrollCache; 14421 scrollabilityCache.fadeScrollBars = fadeScrollbars; 14422 if (fadeScrollbars) { 14423 scrollabilityCache.state = ScrollabilityCache.OFF; 14424 } else { 14425 scrollabilityCache.state = ScrollabilityCache.ON; 14426 } 14427 } 14428 14429 /** 14430 * 14431 * Returns true if scrollbars will fade when this view is not scrolling 14432 * 14433 * @return true if scrollbar fading is enabled 14434 * 14435 * @attr ref android.R.styleable#View_fadeScrollbars 14436 */ isScrollbarFadingEnabled()14437 public boolean isScrollbarFadingEnabled() { 14438 return mScrollCache != null && mScrollCache.fadeScrollBars; 14439 } 14440 14441 /** 14442 * 14443 * Returns the delay before scrollbars fade. 14444 * 14445 * @return the delay before scrollbars fade 14446 * 14447 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 14448 */ getScrollBarDefaultDelayBeforeFade()14449 public int getScrollBarDefaultDelayBeforeFade() { 14450 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 14451 mScrollCache.scrollBarDefaultDelayBeforeFade; 14452 } 14453 14454 /** 14455 * Define the delay before scrollbars fade. 14456 * 14457 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 14458 * 14459 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 14460 */ setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade)14461 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 14462 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 14463 } 14464 14465 /** 14466 * 14467 * Returns the scrollbar fade duration. 14468 * 14469 * @return the scrollbar fade duration 14470 * 14471 * @attr ref android.R.styleable#View_scrollbarFadeDuration 14472 */ getScrollBarFadeDuration()14473 public int getScrollBarFadeDuration() { 14474 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 14475 mScrollCache.scrollBarFadeDuration; 14476 } 14477 14478 /** 14479 * Define the scrollbar fade duration. 14480 * 14481 * @param scrollBarFadeDuration - the scrollbar fade duration 14482 * 14483 * @attr ref android.R.styleable#View_scrollbarFadeDuration 14484 */ setScrollBarFadeDuration(int scrollBarFadeDuration)14485 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 14486 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 14487 } 14488 14489 /** 14490 * 14491 * Returns the scrollbar size. 14492 * 14493 * @return the scrollbar size 14494 * 14495 * @attr ref android.R.styleable#View_scrollbarSize 14496 */ getScrollBarSize()14497 public int getScrollBarSize() { 14498 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 14499 mScrollCache.scrollBarSize; 14500 } 14501 14502 /** 14503 * Define the scrollbar size. 14504 * 14505 * @param scrollBarSize - the scrollbar size 14506 * 14507 * @attr ref android.R.styleable#View_scrollbarSize 14508 */ setScrollBarSize(int scrollBarSize)14509 public void setScrollBarSize(int scrollBarSize) { 14510 getScrollCache().scrollBarSize = scrollBarSize; 14511 } 14512 14513 /** 14514 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 14515 * inset. When inset, they add to the padding of the view. And the scrollbars 14516 * can be drawn inside the padding area or on the edge of the view. For example, 14517 * if a view has a background drawable and you want to draw the scrollbars 14518 * inside the padding specified by the drawable, you can use 14519 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 14520 * appear at the edge of the view, ignoring the padding, then you can use 14521 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 14522 * @param style the style of the scrollbars. Should be one of 14523 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 14524 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 14525 * @see #SCROLLBARS_INSIDE_OVERLAY 14526 * @see #SCROLLBARS_INSIDE_INSET 14527 * @see #SCROLLBARS_OUTSIDE_OVERLAY 14528 * @see #SCROLLBARS_OUTSIDE_INSET 14529 * 14530 * @attr ref android.R.styleable#View_scrollbarStyle 14531 */ setScrollBarStyle(@crollBarStyle int style)14532 public void setScrollBarStyle(@ScrollBarStyle int style) { 14533 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 14534 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 14535 computeOpaqueFlags(); 14536 resolvePadding(); 14537 } 14538 } 14539 14540 /** 14541 * <p>Returns the current scrollbar style.</p> 14542 * @return the current scrollbar style 14543 * @see #SCROLLBARS_INSIDE_OVERLAY 14544 * @see #SCROLLBARS_INSIDE_INSET 14545 * @see #SCROLLBARS_OUTSIDE_OVERLAY 14546 * @see #SCROLLBARS_OUTSIDE_INSET 14547 * 14548 * @attr ref android.R.styleable#View_scrollbarStyle 14549 */ 14550 @ViewDebug.ExportedProperty(mapping = { 14551 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 14552 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 14553 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 14554 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 14555 }) 14556 @ScrollBarStyle getScrollBarStyle()14557 public int getScrollBarStyle() { 14558 return mViewFlags & SCROLLBARS_STYLE_MASK; 14559 } 14560 14561 /** 14562 * <p>Compute the horizontal range that the horizontal scrollbar 14563 * represents.</p> 14564 * 14565 * <p>The range is expressed in arbitrary units that must be the same as the 14566 * units used by {@link #computeHorizontalScrollExtent()} and 14567 * {@link #computeHorizontalScrollOffset()}.</p> 14568 * 14569 * <p>The default range is the drawing width of this view.</p> 14570 * 14571 * @return the total horizontal range represented by the horizontal 14572 * scrollbar 14573 * 14574 * @see #computeHorizontalScrollExtent() 14575 * @see #computeHorizontalScrollOffset() 14576 * @see android.widget.ScrollBarDrawable 14577 */ computeHorizontalScrollRange()14578 protected int computeHorizontalScrollRange() { 14579 return getWidth(); 14580 } 14581 14582 /** 14583 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 14584 * within the horizontal range. This value is used to compute the position 14585 * of the thumb within the scrollbar's track.</p> 14586 * 14587 * <p>The range is expressed in arbitrary units that must be the same as the 14588 * units used by {@link #computeHorizontalScrollRange()} and 14589 * {@link #computeHorizontalScrollExtent()}.</p> 14590 * 14591 * <p>The default offset is the scroll offset of this view.</p> 14592 * 14593 * @return the horizontal offset of the scrollbar's thumb 14594 * 14595 * @see #computeHorizontalScrollRange() 14596 * @see #computeHorizontalScrollExtent() 14597 * @see android.widget.ScrollBarDrawable 14598 */ computeHorizontalScrollOffset()14599 protected int computeHorizontalScrollOffset() { 14600 return mScrollX; 14601 } 14602 14603 /** 14604 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 14605 * within the horizontal range. This value is used to compute the length 14606 * of the thumb within the scrollbar's track.</p> 14607 * 14608 * <p>The range is expressed in arbitrary units that must be the same as the 14609 * units used by {@link #computeHorizontalScrollRange()} and 14610 * {@link #computeHorizontalScrollOffset()}.</p> 14611 * 14612 * <p>The default extent is the drawing width of this view.</p> 14613 * 14614 * @return the horizontal extent of the scrollbar's thumb 14615 * 14616 * @see #computeHorizontalScrollRange() 14617 * @see #computeHorizontalScrollOffset() 14618 * @see android.widget.ScrollBarDrawable 14619 */ computeHorizontalScrollExtent()14620 protected int computeHorizontalScrollExtent() { 14621 return getWidth(); 14622 } 14623 14624 /** 14625 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 14626 * 14627 * <p>The range is expressed in arbitrary units that must be the same as the 14628 * units used by {@link #computeVerticalScrollExtent()} and 14629 * {@link #computeVerticalScrollOffset()}.</p> 14630 * 14631 * @return the total vertical range represented by the vertical scrollbar 14632 * 14633 * <p>The default range is the drawing height of this view.</p> 14634 * 14635 * @see #computeVerticalScrollExtent() 14636 * @see #computeVerticalScrollOffset() 14637 * @see android.widget.ScrollBarDrawable 14638 */ computeVerticalScrollRange()14639 protected int computeVerticalScrollRange() { 14640 return getHeight(); 14641 } 14642 14643 /** 14644 * <p>Compute the vertical offset of the vertical scrollbar's thumb 14645 * within the horizontal range. This value is used to compute the position 14646 * of the thumb within the scrollbar's track.</p> 14647 * 14648 * <p>The range is expressed in arbitrary units that must be the same as the 14649 * units used by {@link #computeVerticalScrollRange()} and 14650 * {@link #computeVerticalScrollExtent()}.</p> 14651 * 14652 * <p>The default offset is the scroll offset of this view.</p> 14653 * 14654 * @return the vertical offset of the scrollbar's thumb 14655 * 14656 * @see #computeVerticalScrollRange() 14657 * @see #computeVerticalScrollExtent() 14658 * @see android.widget.ScrollBarDrawable 14659 */ computeVerticalScrollOffset()14660 protected int computeVerticalScrollOffset() { 14661 return mScrollY; 14662 } 14663 14664 /** 14665 * <p>Compute the vertical extent of the vertical scrollbar's thumb 14666 * within the vertical range. This value is used to compute the length 14667 * of the thumb within the scrollbar's track.</p> 14668 * 14669 * <p>The range is expressed in arbitrary units that must be the same as the 14670 * units used by {@link #computeVerticalScrollRange()} and 14671 * {@link #computeVerticalScrollOffset()}.</p> 14672 * 14673 * <p>The default extent is the drawing height of this view.</p> 14674 * 14675 * @return the vertical extent of the scrollbar's thumb 14676 * 14677 * @see #computeVerticalScrollRange() 14678 * @see #computeVerticalScrollOffset() 14679 * @see android.widget.ScrollBarDrawable 14680 */ computeVerticalScrollExtent()14681 protected int computeVerticalScrollExtent() { 14682 return getHeight(); 14683 } 14684 14685 /** 14686 * Check if this view can be scrolled horizontally in a certain direction. 14687 * 14688 * @param direction Negative to check scrolling left, positive to check scrolling right. 14689 * @return true if this view can be scrolled in the specified direction, false otherwise. 14690 */ canScrollHorizontally(int direction)14691 public boolean canScrollHorizontally(int direction) { 14692 final int offset = computeHorizontalScrollOffset(); 14693 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 14694 if (range == 0) return false; 14695 if (direction < 0) { 14696 return offset > 0; 14697 } else { 14698 return offset < range - 1; 14699 } 14700 } 14701 14702 /** 14703 * Check if this view can be scrolled vertically in a certain direction. 14704 * 14705 * @param direction Negative to check scrolling up, positive to check scrolling down. 14706 * @return true if this view can be scrolled in the specified direction, false otherwise. 14707 */ canScrollVertically(int direction)14708 public boolean canScrollVertically(int direction) { 14709 final int offset = computeVerticalScrollOffset(); 14710 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 14711 if (range == 0) return false; 14712 if (direction < 0) { 14713 return offset > 0; 14714 } else { 14715 return offset < range - 1; 14716 } 14717 } 14718 getScrollIndicatorBounds(@onNull Rect out)14719 void getScrollIndicatorBounds(@NonNull Rect out) { 14720 out.left = mScrollX; 14721 out.right = mScrollX + mRight - mLeft; 14722 out.top = mScrollY; 14723 out.bottom = mScrollY + mBottom - mTop; 14724 } 14725 onDrawScrollIndicators(Canvas c)14726 private void onDrawScrollIndicators(Canvas c) { 14727 if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { 14728 // No scroll indicators enabled. 14729 return; 14730 } 14731 14732 final Drawable dr = mScrollIndicatorDrawable; 14733 if (dr == null) { 14734 // Scroll indicators aren't supported here. 14735 return; 14736 } 14737 14738 final int h = dr.getIntrinsicHeight(); 14739 final int w = dr.getIntrinsicWidth(); 14740 final Rect rect = mAttachInfo.mTmpInvalRect; 14741 getScrollIndicatorBounds(rect); 14742 14743 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { 14744 final boolean canScrollUp = canScrollVertically(-1); 14745 if (canScrollUp) { 14746 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); 14747 dr.draw(c); 14748 } 14749 } 14750 14751 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { 14752 final boolean canScrollDown = canScrollVertically(1); 14753 if (canScrollDown) { 14754 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); 14755 dr.draw(c); 14756 } 14757 } 14758 14759 final int leftRtl; 14760 final int rightRtl; 14761 if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 14762 leftRtl = PFLAG3_SCROLL_INDICATOR_END; 14763 rightRtl = PFLAG3_SCROLL_INDICATOR_START; 14764 } else { 14765 leftRtl = PFLAG3_SCROLL_INDICATOR_START; 14766 rightRtl = PFLAG3_SCROLL_INDICATOR_END; 14767 } 14768 14769 final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; 14770 if ((mPrivateFlags3 & leftMask) != 0) { 14771 final boolean canScrollLeft = canScrollHorizontally(-1); 14772 if (canScrollLeft) { 14773 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); 14774 dr.draw(c); 14775 } 14776 } 14777 14778 final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; 14779 if ((mPrivateFlags3 & rightMask) != 0) { 14780 final boolean canScrollRight = canScrollHorizontally(1); 14781 if (canScrollRight) { 14782 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); 14783 dr.draw(c); 14784 } 14785 } 14786 } 14787 getHorizontalScrollBarBounds(Rect bounds)14788 private void getHorizontalScrollBarBounds(Rect bounds) { 14789 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 14790 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 14791 && !isVerticalScrollBarHidden(); 14792 final int size = getHorizontalScrollbarHeight(); 14793 final int verticalScrollBarGap = drawVerticalScrollBar ? 14794 getVerticalScrollbarWidth() : 0; 14795 final int width = mRight - mLeft; 14796 final int height = mBottom - mTop; 14797 bounds.top = mScrollY + height - size - (mUserPaddingBottom & inside); 14798 bounds.left = mScrollX + (mPaddingLeft & inside); 14799 bounds.right = mScrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 14800 bounds.bottom = bounds.top + size; 14801 } 14802 getVerticalScrollBarBounds(Rect bounds)14803 private void getVerticalScrollBarBounds(Rect bounds) { 14804 if (mRoundScrollbarRenderer == null) { 14805 getStraightVerticalScrollBarBounds(bounds); 14806 } else { 14807 getRoundVerticalScrollBarBounds(bounds); 14808 } 14809 } 14810 getRoundVerticalScrollBarBounds(Rect bounds)14811 private void getRoundVerticalScrollBarBounds(Rect bounds) { 14812 final int width = mRight - mLeft; 14813 final int height = mBottom - mTop; 14814 // Do not take padding into account as we always want the scrollbars 14815 // to hug the screen for round wearable devices. 14816 bounds.left = mScrollX; 14817 bounds.top = mScrollY; 14818 bounds.right = bounds.left + width; 14819 bounds.bottom = mScrollY + height; 14820 } 14821 getStraightVerticalScrollBarBounds(Rect bounds)14822 private void getStraightVerticalScrollBarBounds(Rect bounds) { 14823 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 14824 final int size = getVerticalScrollbarWidth(); 14825 int verticalScrollbarPosition = mVerticalScrollbarPosition; 14826 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 14827 verticalScrollbarPosition = isLayoutRtl() ? 14828 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 14829 } 14830 final int width = mRight - mLeft; 14831 final int height = mBottom - mTop; 14832 switch (verticalScrollbarPosition) { 14833 default: 14834 case SCROLLBAR_POSITION_RIGHT: 14835 bounds.left = mScrollX + width - size - (mUserPaddingRight & inside); 14836 break; 14837 case SCROLLBAR_POSITION_LEFT: 14838 bounds.left = mScrollX + (mUserPaddingLeft & inside); 14839 break; 14840 } 14841 bounds.top = mScrollY + (mPaddingTop & inside); 14842 bounds.right = bounds.left + size; 14843 bounds.bottom = mScrollY + height - (mUserPaddingBottom & inside); 14844 } 14845 14846 /** 14847 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 14848 * scrollbars are painted only if they have been awakened first.</p> 14849 * 14850 * @param canvas the canvas on which to draw the scrollbars 14851 * 14852 * @see #awakenScrollBars(int) 14853 */ onDrawScrollBars(Canvas canvas)14854 protected final void onDrawScrollBars(Canvas canvas) { 14855 // scrollbars are drawn only when the animation is running 14856 final ScrollabilityCache cache = mScrollCache; 14857 14858 if (cache != null) { 14859 14860 int state = cache.state; 14861 14862 if (state == ScrollabilityCache.OFF) { 14863 return; 14864 } 14865 14866 boolean invalidate = false; 14867 14868 if (state == ScrollabilityCache.FADING) { 14869 // We're fading -- get our fade interpolation 14870 if (cache.interpolatorValues == null) { 14871 cache.interpolatorValues = new float[1]; 14872 } 14873 14874 float[] values = cache.interpolatorValues; 14875 14876 // Stops the animation if we're done 14877 if (cache.scrollBarInterpolator.timeToValues(values) == 14878 Interpolator.Result.FREEZE_END) { 14879 cache.state = ScrollabilityCache.OFF; 14880 } else { 14881 cache.scrollBar.mutate().setAlpha(Math.round(values[0])); 14882 } 14883 14884 // This will make the scroll bars inval themselves after 14885 // drawing. We only want this when we're fading so that 14886 // we prevent excessive redraws 14887 invalidate = true; 14888 } else { 14889 // We're just on -- but we may have been fading before so 14890 // reset alpha 14891 cache.scrollBar.mutate().setAlpha(255); 14892 } 14893 14894 final boolean drawHorizontalScrollBar = isHorizontalScrollBarEnabled(); 14895 final boolean drawVerticalScrollBar = isVerticalScrollBarEnabled() 14896 && !isVerticalScrollBarHidden(); 14897 14898 // Fork out the scroll bar drawing for round wearable devices. 14899 if (mRoundScrollbarRenderer != null) { 14900 if (drawVerticalScrollBar) { 14901 final Rect bounds = cache.mScrollBarBounds; 14902 getVerticalScrollBarBounds(bounds); 14903 mRoundScrollbarRenderer.drawRoundScrollbars( 14904 canvas, (float) cache.scrollBar.getAlpha() / 255f, bounds); 14905 if (invalidate) { 14906 invalidate(); 14907 } 14908 } 14909 // Do not draw horizontal scroll bars for round wearable devices. 14910 } else if (drawVerticalScrollBar || drawHorizontalScrollBar) { 14911 final ScrollBarDrawable scrollBar = cache.scrollBar; 14912 14913 if (drawHorizontalScrollBar) { 14914 scrollBar.setParameters(computeHorizontalScrollRange(), 14915 computeHorizontalScrollOffset(), 14916 computeHorizontalScrollExtent(), false); 14917 final Rect bounds = cache.mScrollBarBounds; 14918 getHorizontalScrollBarBounds(bounds); 14919 onDrawHorizontalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 14920 bounds.right, bounds.bottom); 14921 if (invalidate) { 14922 invalidate(bounds); 14923 } 14924 } 14925 14926 if (drawVerticalScrollBar) { 14927 scrollBar.setParameters(computeVerticalScrollRange(), 14928 computeVerticalScrollOffset(), 14929 computeVerticalScrollExtent(), true); 14930 final Rect bounds = cache.mScrollBarBounds; 14931 getVerticalScrollBarBounds(bounds); 14932 onDrawVerticalScrollBar(canvas, scrollBar, bounds.left, bounds.top, 14933 bounds.right, bounds.bottom); 14934 if (invalidate) { 14935 invalidate(bounds); 14936 } 14937 } 14938 } 14939 } 14940 } 14941 14942 /** 14943 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 14944 * FastScroller is visible. 14945 * @return whether to temporarily hide the vertical scrollbar 14946 * @hide 14947 */ isVerticalScrollBarHidden()14948 protected boolean isVerticalScrollBarHidden() { 14949 return false; 14950 } 14951 14952 /** 14953 * <p>Draw the horizontal scrollbar if 14954 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 14955 * 14956 * @param canvas the canvas on which to draw the scrollbar 14957 * @param scrollBar the scrollbar's drawable 14958 * 14959 * @see #isHorizontalScrollBarEnabled() 14960 * @see #computeHorizontalScrollRange() 14961 * @see #computeHorizontalScrollExtent() 14962 * @see #computeHorizontalScrollOffset() 14963 * @see android.widget.ScrollBarDrawable 14964 * @hide 14965 */ onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14966 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 14967 int l, int t, int r, int b) { 14968 scrollBar.setBounds(l, t, r, b); 14969 scrollBar.draw(canvas); 14970 } 14971 14972 /** 14973 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 14974 * returns true.</p> 14975 * 14976 * @param canvas the canvas on which to draw the scrollbar 14977 * @param scrollBar the scrollbar's drawable 14978 * 14979 * @see #isVerticalScrollBarEnabled() 14980 * @see #computeVerticalScrollRange() 14981 * @see #computeVerticalScrollExtent() 14982 * @see #computeVerticalScrollOffset() 14983 * @see android.widget.ScrollBarDrawable 14984 * @hide 14985 */ onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b)14986 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 14987 int l, int t, int r, int b) { 14988 scrollBar.setBounds(l, t, r, b); 14989 scrollBar.draw(canvas); 14990 } 14991 14992 /** 14993 * Implement this to do your drawing. 14994 * 14995 * @param canvas the canvas on which the background will be drawn 14996 */ onDraw(Canvas canvas)14997 protected void onDraw(Canvas canvas) { 14998 } 14999 15000 /* 15001 * Caller is responsible for calling requestLayout if necessary. 15002 * (This allows addViewInLayout to not request a new layout.) 15003 */ assignParent(ViewParent parent)15004 void assignParent(ViewParent parent) { 15005 if (mParent == null) { 15006 mParent = parent; 15007 } else if (parent == null) { 15008 mParent = null; 15009 } else { 15010 throw new RuntimeException("view " + this + " being added, but" 15011 + " it already has a parent"); 15012 } 15013 } 15014 15015 /** 15016 * This is called when the view is attached to a window. At this point it 15017 * has a Surface and will start drawing. Note that this function is 15018 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 15019 * however it may be called any time before the first onDraw -- including 15020 * before or after {@link #onMeasure(int, int)}. 15021 * 15022 * @see #onDetachedFromWindow() 15023 */ 15024 @CallSuper onAttachedToWindow()15025 protected void onAttachedToWindow() { 15026 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 15027 mParent.requestTransparentRegion(this); 15028 } 15029 15030 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 15031 15032 jumpDrawablesToCurrentState(); 15033 15034 resetSubtreeAccessibilityStateChanged(); 15035 15036 // rebuild, since Outline not maintained while View is detached 15037 rebuildOutline(); 15038 15039 if (isFocused()) { 15040 InputMethodManager imm = InputMethodManager.peekInstance(); 15041 if (imm != null) { 15042 imm.focusIn(this); 15043 } 15044 } 15045 } 15046 15047 /** 15048 * Resolve all RTL related properties. 15049 * 15050 * @return true if resolution of RTL properties has been done 15051 * 15052 * @hide 15053 */ resolveRtlPropertiesIfNeeded()15054 public boolean resolveRtlPropertiesIfNeeded() { 15055 if (!needRtlPropertiesResolution()) return false; 15056 15057 // Order is important here: LayoutDirection MUST be resolved first 15058 if (!isLayoutDirectionResolved()) { 15059 resolveLayoutDirection(); 15060 resolveLayoutParams(); 15061 } 15062 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 15063 if (!isTextDirectionResolved()) { 15064 resolveTextDirection(); 15065 } 15066 if (!isTextAlignmentResolved()) { 15067 resolveTextAlignment(); 15068 } 15069 // Should resolve Drawables before Padding because we need the layout direction of the 15070 // Drawable to correctly resolve Padding. 15071 if (!areDrawablesResolved()) { 15072 resolveDrawables(); 15073 } 15074 if (!isPaddingResolved()) { 15075 resolvePadding(); 15076 } 15077 onRtlPropertiesChanged(getLayoutDirection()); 15078 return true; 15079 } 15080 15081 /** 15082 * Reset resolution of all RTL related properties. 15083 * 15084 * @hide 15085 */ resetRtlProperties()15086 public void resetRtlProperties() { 15087 resetResolvedLayoutDirection(); 15088 resetResolvedTextDirection(); 15089 resetResolvedTextAlignment(); 15090 resetResolvedPadding(); 15091 resetResolvedDrawables(); 15092 } 15093 15094 /** 15095 * @see #onScreenStateChanged(int) 15096 */ dispatchScreenStateChanged(int screenState)15097 void dispatchScreenStateChanged(int screenState) { 15098 onScreenStateChanged(screenState); 15099 } 15100 15101 /** 15102 * This method is called whenever the state of the screen this view is 15103 * attached to changes. A state change will usually occurs when the screen 15104 * turns on or off (whether it happens automatically or the user does it 15105 * manually.) 15106 * 15107 * @param screenState The new state of the screen. Can be either 15108 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 15109 */ onScreenStateChanged(int screenState)15110 public void onScreenStateChanged(int screenState) { 15111 } 15112 15113 /** 15114 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 15115 */ hasRtlSupport()15116 private boolean hasRtlSupport() { 15117 return mContext.getApplicationInfo().hasRtlSupport(); 15118 } 15119 15120 /** 15121 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 15122 * RTL not supported) 15123 */ isRtlCompatibilityMode()15124 private boolean isRtlCompatibilityMode() { 15125 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 15126 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 15127 } 15128 15129 /** 15130 * @return true if RTL properties need resolution. 15131 * 15132 */ needRtlPropertiesResolution()15133 private boolean needRtlPropertiesResolution() { 15134 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 15135 } 15136 15137 /** 15138 * Called when any RTL property (layout direction or text direction or text alignment) has 15139 * been changed. 15140 * 15141 * Subclasses need to override this method to take care of cached information that depends on the 15142 * resolved layout direction, or to inform child views that inherit their layout direction. 15143 * 15144 * The default implementation does nothing. 15145 * 15146 * @param layoutDirection the direction of the layout 15147 * 15148 * @see #LAYOUT_DIRECTION_LTR 15149 * @see #LAYOUT_DIRECTION_RTL 15150 */ onRtlPropertiesChanged(@esolvedLayoutDir int layoutDirection)15151 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { 15152 } 15153 15154 /** 15155 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 15156 * that the parent directionality can and will be resolved before its children. 15157 * 15158 * @return true if resolution has been done, false otherwise. 15159 * 15160 * @hide 15161 */ resolveLayoutDirection()15162 public boolean resolveLayoutDirection() { 15163 // Clear any previous layout direction resolution 15164 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 15165 15166 if (hasRtlSupport()) { 15167 // Set resolved depending on layout direction 15168 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 15169 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 15170 case LAYOUT_DIRECTION_INHERIT: 15171 // We cannot resolve yet. LTR is by default and let the resolution happen again 15172 // later to get the correct resolved value 15173 if (!canResolveLayoutDirection()) return false; 15174 15175 // Parent has not yet resolved, LTR is still the default 15176 try { 15177 if (!mParent.isLayoutDirectionResolved()) return false; 15178 15179 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 15180 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15181 } 15182 } catch (AbstractMethodError e) { 15183 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 15184 " does not fully implement ViewParent", e); 15185 } 15186 break; 15187 case LAYOUT_DIRECTION_RTL: 15188 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15189 break; 15190 case LAYOUT_DIRECTION_LOCALE: 15191 if((LAYOUT_DIRECTION_RTL == 15192 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 15193 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 15194 } 15195 break; 15196 default: 15197 // Nothing to do, LTR by default 15198 } 15199 } 15200 15201 // Set to resolved 15202 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 15203 return true; 15204 } 15205 15206 /** 15207 * Check if layout direction resolution can be done. 15208 * 15209 * @return true if layout direction resolution can be done otherwise return false. 15210 */ canResolveLayoutDirection()15211 public boolean canResolveLayoutDirection() { 15212 switch (getRawLayoutDirection()) { 15213 case LAYOUT_DIRECTION_INHERIT: 15214 if (mParent != null) { 15215 try { 15216 return mParent.canResolveLayoutDirection(); 15217 } catch (AbstractMethodError e) { 15218 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 15219 " does not fully implement ViewParent", e); 15220 } 15221 } 15222 return false; 15223 15224 default: 15225 return true; 15226 } 15227 } 15228 15229 /** 15230 * Reset the resolved layout direction. Layout direction will be resolved during a call to 15231 * {@link #onMeasure(int, int)}. 15232 * 15233 * @hide 15234 */ resetResolvedLayoutDirection()15235 public void resetResolvedLayoutDirection() { 15236 // Reset the current resolved bits 15237 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 15238 } 15239 15240 /** 15241 * @return true if the layout direction is inherited. 15242 * 15243 * @hide 15244 */ isLayoutDirectionInherited()15245 public boolean isLayoutDirectionInherited() { 15246 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 15247 } 15248 15249 /** 15250 * @return true if layout direction has been resolved. 15251 */ isLayoutDirectionResolved()15252 public boolean isLayoutDirectionResolved() { 15253 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 15254 } 15255 15256 /** 15257 * Return if padding has been resolved 15258 * 15259 * @hide 15260 */ isPaddingResolved()15261 boolean isPaddingResolved() { 15262 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 15263 } 15264 15265 /** 15266 * Resolves padding depending on layout direction, if applicable, and 15267 * recomputes internal padding values to adjust for scroll bars. 15268 * 15269 * @hide 15270 */ resolvePadding()15271 public void resolvePadding() { 15272 final int resolvedLayoutDirection = getLayoutDirection(); 15273 15274 if (!isRtlCompatibilityMode()) { 15275 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 15276 // If start / end padding are defined, they will be resolved (hence overriding) to 15277 // left / right or right / left depending on the resolved layout direction. 15278 // If start / end padding are not defined, use the left / right ones. 15279 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 15280 Rect padding = sThreadLocal.get(); 15281 if (padding == null) { 15282 padding = new Rect(); 15283 sThreadLocal.set(padding); 15284 } 15285 mBackground.getPadding(padding); 15286 if (!mLeftPaddingDefined) { 15287 mUserPaddingLeftInitial = padding.left; 15288 } 15289 if (!mRightPaddingDefined) { 15290 mUserPaddingRightInitial = padding.right; 15291 } 15292 } 15293 switch (resolvedLayoutDirection) { 15294 case LAYOUT_DIRECTION_RTL: 15295 if (mUserPaddingStart != UNDEFINED_PADDING) { 15296 mUserPaddingRight = mUserPaddingStart; 15297 } else { 15298 mUserPaddingRight = mUserPaddingRightInitial; 15299 } 15300 if (mUserPaddingEnd != UNDEFINED_PADDING) { 15301 mUserPaddingLeft = mUserPaddingEnd; 15302 } else { 15303 mUserPaddingLeft = mUserPaddingLeftInitial; 15304 } 15305 break; 15306 case LAYOUT_DIRECTION_LTR: 15307 default: 15308 if (mUserPaddingStart != UNDEFINED_PADDING) { 15309 mUserPaddingLeft = mUserPaddingStart; 15310 } else { 15311 mUserPaddingLeft = mUserPaddingLeftInitial; 15312 } 15313 if (mUserPaddingEnd != UNDEFINED_PADDING) { 15314 mUserPaddingRight = mUserPaddingEnd; 15315 } else { 15316 mUserPaddingRight = mUserPaddingRightInitial; 15317 } 15318 } 15319 15320 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 15321 } 15322 15323 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 15324 onRtlPropertiesChanged(resolvedLayoutDirection); 15325 15326 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 15327 } 15328 15329 /** 15330 * Reset the resolved layout direction. 15331 * 15332 * @hide 15333 */ resetResolvedPadding()15334 public void resetResolvedPadding() { 15335 resetResolvedPaddingInternal(); 15336 } 15337 15338 /** 15339 * Used when we only want to reset *this* view's padding and not trigger overrides 15340 * in ViewGroup that reset children too. 15341 */ resetResolvedPaddingInternal()15342 void resetResolvedPaddingInternal() { 15343 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 15344 } 15345 15346 /** 15347 * This is called when the view is detached from a window. At this point it 15348 * no longer has a surface for drawing. 15349 * 15350 * @see #onAttachedToWindow() 15351 */ 15352 @CallSuper onDetachedFromWindow()15353 protected void onDetachedFromWindow() { 15354 } 15355 15356 /** 15357 * This is a framework-internal mirror of onDetachedFromWindow() that's called 15358 * after onDetachedFromWindow(). 15359 * 15360 * If you override this you *MUST* call super.onDetachedFromWindowInternal()! 15361 * The super method should be called at the end of the overridden method to ensure 15362 * subclasses are destroyed first 15363 * 15364 * @hide 15365 */ 15366 @CallSuper onDetachedFromWindowInternal()15367 protected void onDetachedFromWindowInternal() { 15368 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 15369 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 15370 mPrivateFlags3 &= ~PFLAG3_TEMPORARY_DETACH; 15371 15372 removeUnsetPressCallback(); 15373 removeLongPressCallback(); 15374 removePerformClickCallback(); 15375 removeSendViewScrolledAccessibilityEventCallback(); 15376 stopNestedScroll(); 15377 15378 // Anything that started animating right before detach should already 15379 // be in its final state when re-attached. 15380 jumpDrawablesToCurrentState(); 15381 15382 destroyDrawingCache(); 15383 15384 cleanupDraw(); 15385 mCurrentAnimation = null; 15386 } 15387 cleanupDraw()15388 private void cleanupDraw() { 15389 resetDisplayList(); 15390 if (mAttachInfo != null) { 15391 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 15392 } 15393 } 15394 invalidateInheritedLayoutMode(int layoutModeOfRoot)15395 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 15396 } 15397 15398 /** 15399 * @return The number of times this view has been attached to a window 15400 */ getWindowAttachCount()15401 protected int getWindowAttachCount() { 15402 return mWindowAttachCount; 15403 } 15404 15405 /** 15406 * Retrieve a unique token identifying the window this view is attached to. 15407 * @return Return the window's token for use in 15408 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 15409 */ getWindowToken()15410 public IBinder getWindowToken() { 15411 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 15412 } 15413 15414 /** 15415 * Retrieve the {@link WindowId} for the window this view is 15416 * currently attached to. 15417 */ getWindowId()15418 public WindowId getWindowId() { 15419 if (mAttachInfo == null) { 15420 return null; 15421 } 15422 if (mAttachInfo.mWindowId == null) { 15423 try { 15424 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId( 15425 mAttachInfo.mWindowToken); 15426 mAttachInfo.mWindowId = new WindowId( 15427 mAttachInfo.mIWindowId); 15428 } catch (RemoteException e) { 15429 } 15430 } 15431 return mAttachInfo.mWindowId; 15432 } 15433 15434 /** 15435 * Retrieve a unique token identifying the top-level "real" window of 15436 * the window that this view is attached to. That is, this is like 15437 * {@link #getWindowToken}, except if the window this view in is a panel 15438 * window (attached to another containing window), then the token of 15439 * the containing window is returned instead. 15440 * 15441 * @return Returns the associated window token, either 15442 * {@link #getWindowToken()} or the containing window's token. 15443 */ getApplicationWindowToken()15444 public IBinder getApplicationWindowToken() { 15445 AttachInfo ai = mAttachInfo; 15446 if (ai != null) { 15447 IBinder appWindowToken = ai.mPanelParentWindowToken; 15448 if (appWindowToken == null) { 15449 appWindowToken = ai.mWindowToken; 15450 } 15451 return appWindowToken; 15452 } 15453 return null; 15454 } 15455 15456 /** 15457 * Gets the logical display to which the view's window has been attached. 15458 * 15459 * @return The logical display, or null if the view is not currently attached to a window. 15460 */ getDisplay()15461 public Display getDisplay() { 15462 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 15463 } 15464 15465 /** 15466 * Retrieve private session object this view hierarchy is using to 15467 * communicate with the window manager. 15468 * @return the session object to communicate with the window manager 15469 */ getWindowSession()15470 /*package*/ IWindowSession getWindowSession() { 15471 return mAttachInfo != null ? mAttachInfo.mSession : null; 15472 } 15473 15474 /** 15475 * Return the visibility value of the least visible component passed. 15476 */ combineVisibility(int vis1, int vis2)15477 int combineVisibility(int vis1, int vis2) { 15478 // This works because VISIBLE < INVISIBLE < GONE. 15479 return Math.max(vis1, vis2); 15480 } 15481 15482 /** 15483 * @param info the {@link android.view.View.AttachInfo} to associated with 15484 * this view 15485 */ dispatchAttachedToWindow(AttachInfo info, int visibility)15486 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 15487 mAttachInfo = info; 15488 if (mOverlay != null) { 15489 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 15490 } 15491 mWindowAttachCount++; 15492 // We will need to evaluate the drawable state at least once. 15493 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 15494 if (mFloatingTreeObserver != null) { 15495 info.mTreeObserver.merge(mFloatingTreeObserver); 15496 mFloatingTreeObserver = null; 15497 } 15498 15499 registerPendingFrameMetricsObservers(); 15500 15501 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 15502 mAttachInfo.mScrollContainers.add(this); 15503 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 15504 } 15505 // Transfer all pending runnables. 15506 if (mRunQueue != null) { 15507 mRunQueue.executeActions(info.mHandler); 15508 mRunQueue = null; 15509 } 15510 performCollectViewAttributes(mAttachInfo, visibility); 15511 onAttachedToWindow(); 15512 15513 ListenerInfo li = mListenerInfo; 15514 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 15515 li != null ? li.mOnAttachStateChangeListeners : null; 15516 if (listeners != null && listeners.size() > 0) { 15517 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 15518 // perform the dispatching. The iterator is a safe guard against listeners that 15519 // could mutate the list by calling the various add/remove methods. This prevents 15520 // the array from being modified while we iterate it. 15521 for (OnAttachStateChangeListener listener : listeners) { 15522 listener.onViewAttachedToWindow(this); 15523 } 15524 } 15525 15526 int vis = info.mWindowVisibility; 15527 if (vis != GONE) { 15528 onWindowVisibilityChanged(vis); 15529 if (isShown()) { 15530 // Calling onVisibilityAggregated directly here since the subtree will also 15531 // receive dispatchAttachedToWindow and this same call 15532 onVisibilityAggregated(vis == VISIBLE); 15533 } 15534 } 15535 15536 // Send onVisibilityChanged directly instead of dispatchVisibilityChanged. 15537 // As all views in the subtree will already receive dispatchAttachedToWindow 15538 // traversing the subtree again here is not desired. 15539 onVisibilityChanged(this, visibility); 15540 15541 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 15542 // If nobody has evaluated the drawable state yet, then do it now. 15543 refreshDrawableState(); 15544 } 15545 needGlobalAttributesUpdate(false); 15546 } 15547 dispatchDetachedFromWindow()15548 void dispatchDetachedFromWindow() { 15549 AttachInfo info = mAttachInfo; 15550 if (info != null) { 15551 int vis = info.mWindowVisibility; 15552 if (vis != GONE) { 15553 onWindowVisibilityChanged(GONE); 15554 if (isShown()) { 15555 // Invoking onVisibilityAggregated directly here since the subtree 15556 // will also receive detached from window 15557 onVisibilityAggregated(false); 15558 } 15559 } 15560 } 15561 15562 onDetachedFromWindow(); 15563 onDetachedFromWindowInternal(); 15564 15565 InputMethodManager imm = InputMethodManager.peekInstance(); 15566 if (imm != null) { 15567 imm.onViewDetachedFromWindow(this); 15568 } 15569 15570 ListenerInfo li = mListenerInfo; 15571 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 15572 li != null ? li.mOnAttachStateChangeListeners : null; 15573 if (listeners != null && listeners.size() > 0) { 15574 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 15575 // perform the dispatching. The iterator is a safe guard against listeners that 15576 // could mutate the list by calling the various add/remove methods. This prevents 15577 // the array from being modified while we iterate it. 15578 for (OnAttachStateChangeListener listener : listeners) { 15579 listener.onViewDetachedFromWindow(this); 15580 } 15581 } 15582 15583 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 15584 mAttachInfo.mScrollContainers.remove(this); 15585 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 15586 } 15587 15588 mAttachInfo = null; 15589 if (mOverlay != null) { 15590 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 15591 } 15592 } 15593 15594 /** 15595 * Cancel any deferred high-level input events that were previously posted to the event queue. 15596 * 15597 * <p>Many views post high-level events such as click handlers to the event queue 15598 * to run deferred in order to preserve a desired user experience - clearing visible 15599 * pressed states before executing, etc. This method will abort any events of this nature 15600 * that are currently in flight.</p> 15601 * 15602 * <p>Custom views that generate their own high-level deferred input events should override 15603 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 15604 * 15605 * <p>This will also cancel pending input events for any child views.</p> 15606 * 15607 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 15608 * This will not impact newer events posted after this call that may occur as a result of 15609 * lower-level input events still waiting in the queue. If you are trying to prevent 15610 * double-submitted events for the duration of some sort of asynchronous transaction 15611 * you should also take other steps to protect against unexpected double inputs e.g. calling 15612 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 15613 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 15614 */ cancelPendingInputEvents()15615 public final void cancelPendingInputEvents() { 15616 dispatchCancelPendingInputEvents(); 15617 } 15618 15619 /** 15620 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 15621 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 15622 */ dispatchCancelPendingInputEvents()15623 void dispatchCancelPendingInputEvents() { 15624 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 15625 onCancelPendingInputEvents(); 15626 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 15627 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 15628 " did not call through to super.onCancelPendingInputEvents()"); 15629 } 15630 } 15631 15632 /** 15633 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 15634 * a parent view. 15635 * 15636 * <p>This method is responsible for removing any pending high-level input events that were 15637 * posted to the event queue to run later. Custom view classes that post their own deferred 15638 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 15639 * {@link android.os.Handler} should override this method, call 15640 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 15641 * </p> 15642 */ onCancelPendingInputEvents()15643 public void onCancelPendingInputEvents() { 15644 removePerformClickCallback(); 15645 cancelLongPress(); 15646 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 15647 } 15648 15649 /** 15650 * Store this view hierarchy's frozen state into the given container. 15651 * 15652 * @param container The SparseArray in which to save the view's state. 15653 * 15654 * @see #restoreHierarchyState(android.util.SparseArray) 15655 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15656 * @see #onSaveInstanceState() 15657 */ saveHierarchyState(SparseArray<Parcelable> container)15658 public void saveHierarchyState(SparseArray<Parcelable> container) { 15659 dispatchSaveInstanceState(container); 15660 } 15661 15662 /** 15663 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 15664 * this view and its children. May be overridden to modify how freezing happens to a 15665 * view's children; for example, some views may want to not store state for their children. 15666 * 15667 * @param container The SparseArray in which to save the view's state. 15668 * 15669 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15670 * @see #saveHierarchyState(android.util.SparseArray) 15671 * @see #onSaveInstanceState() 15672 */ dispatchSaveInstanceState(SparseArray<Parcelable> container)15673 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 15674 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 15675 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15676 Parcelable state = onSaveInstanceState(); 15677 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15678 throw new IllegalStateException( 15679 "Derived class did not call super.onSaveInstanceState()"); 15680 } 15681 if (state != null) { 15682 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 15683 // + ": " + state); 15684 container.put(mID, state); 15685 } 15686 } 15687 } 15688 15689 /** 15690 * Hook allowing a view to generate a representation of its internal state 15691 * that can later be used to create a new instance with that same state. 15692 * This state should only contain information that is not persistent or can 15693 * not be reconstructed later. For example, you will never store your 15694 * current position on screen because that will be computed again when a 15695 * new instance of the view is placed in its view hierarchy. 15696 * <p> 15697 * Some examples of things you may store here: the current cursor position 15698 * in a text view (but usually not the text itself since that is stored in a 15699 * content provider or other persistent storage), the currently selected 15700 * item in a list view. 15701 * 15702 * @return Returns a Parcelable object containing the view's current dynamic 15703 * state, or null if there is nothing interesting to save. The 15704 * default implementation returns null. 15705 * @see #onRestoreInstanceState(android.os.Parcelable) 15706 * @see #saveHierarchyState(android.util.SparseArray) 15707 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15708 * @see #setSaveEnabled(boolean) 15709 */ 15710 @CallSuper onSaveInstanceState()15711 protected Parcelable onSaveInstanceState() { 15712 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15713 if (mStartActivityRequestWho != null) { 15714 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE); 15715 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; 15716 return state; 15717 } 15718 return BaseSavedState.EMPTY_STATE; 15719 } 15720 15721 /** 15722 * Restore this view hierarchy's frozen state from the given container. 15723 * 15724 * @param container The SparseArray which holds previously frozen states. 15725 * 15726 * @see #saveHierarchyState(android.util.SparseArray) 15727 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15728 * @see #onRestoreInstanceState(android.os.Parcelable) 15729 */ restoreHierarchyState(SparseArray<Parcelable> container)15730 public void restoreHierarchyState(SparseArray<Parcelable> container) { 15731 dispatchRestoreInstanceState(container); 15732 } 15733 15734 /** 15735 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 15736 * state for this view and its children. May be overridden to modify how restoring 15737 * happens to a view's children; for example, some views may want to not store state 15738 * for their children. 15739 * 15740 * @param container The SparseArray which holds previously saved state. 15741 * 15742 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15743 * @see #restoreHierarchyState(android.util.SparseArray) 15744 * @see #onRestoreInstanceState(android.os.Parcelable) 15745 */ dispatchRestoreInstanceState(SparseArray<Parcelable> container)15746 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 15747 if (mID != NO_ID) { 15748 Parcelable state = container.get(mID); 15749 if (state != null) { 15750 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 15751 // + ": " + state); 15752 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15753 onRestoreInstanceState(state); 15754 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15755 throw new IllegalStateException( 15756 "Derived class did not call super.onRestoreInstanceState()"); 15757 } 15758 } 15759 } 15760 } 15761 15762 /** 15763 * Hook allowing a view to re-apply a representation of its internal state that had previously 15764 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 15765 * null state. 15766 * 15767 * @param state The frozen state that had previously been returned by 15768 * {@link #onSaveInstanceState}. 15769 * 15770 * @see #onSaveInstanceState() 15771 * @see #restoreHierarchyState(android.util.SparseArray) 15772 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15773 */ 15774 @CallSuper onRestoreInstanceState(Parcelable state)15775 protected void onRestoreInstanceState(Parcelable state) { 15776 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15777 if (state != null && !(state instanceof AbsSavedState)) { 15778 throw new IllegalArgumentException("Wrong state class, expecting View State but " 15779 + "received " + state.getClass().toString() + " instead. This usually happens " 15780 + "when two views of different type have the same id in the same hierarchy. " 15781 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 15782 + "other views do not use the same id."); 15783 } 15784 if (state != null && state instanceof BaseSavedState) { 15785 mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved; 15786 } 15787 } 15788 15789 /** 15790 * <p>Return the time at which the drawing of the view hierarchy started.</p> 15791 * 15792 * @return the drawing start time in milliseconds 15793 */ getDrawingTime()15794 public long getDrawingTime() { 15795 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 15796 } 15797 15798 /** 15799 * <p>Enables or disables the duplication of the parent's state into this view. When 15800 * duplication is enabled, this view gets its drawable state from its parent rather 15801 * than from its own internal properties.</p> 15802 * 15803 * <p>Note: in the current implementation, setting this property to true after the 15804 * view was added to a ViewGroup might have no effect at all. This property should 15805 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 15806 * 15807 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 15808 * property is enabled, an exception will be thrown.</p> 15809 * 15810 * <p>Note: if the child view uses and updates additional states which are unknown to the 15811 * parent, these states should not be affected by this method.</p> 15812 * 15813 * @param enabled True to enable duplication of the parent's drawable state, false 15814 * to disable it. 15815 * 15816 * @see #getDrawableState() 15817 * @see #isDuplicateParentStateEnabled() 15818 */ setDuplicateParentStateEnabled(boolean enabled)15819 public void setDuplicateParentStateEnabled(boolean enabled) { 15820 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 15821 } 15822 15823 /** 15824 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 15825 * 15826 * @return True if this view's drawable state is duplicated from the parent, 15827 * false otherwise 15828 * 15829 * @see #getDrawableState() 15830 * @see #setDuplicateParentStateEnabled(boolean) 15831 */ isDuplicateParentStateEnabled()15832 public boolean isDuplicateParentStateEnabled() { 15833 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 15834 } 15835 15836 /** 15837 * <p>Specifies the type of layer backing this view. The layer can be 15838 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15839 * {@link #LAYER_TYPE_HARDWARE}.</p> 15840 * 15841 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15842 * instance that controls how the layer is composed on screen. The following 15843 * properties of the paint are taken into account when composing the layer:</p> 15844 * <ul> 15845 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15846 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15847 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15848 * </ul> 15849 * 15850 * <p>If this view has an alpha value set to < 1.0 by calling 15851 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded 15852 * by this view's alpha value.</p> 15853 * 15854 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 15855 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 15856 * for more information on when and how to use layers.</p> 15857 * 15858 * @param layerType The type of layer to use with this view, must be one of 15859 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15860 * {@link #LAYER_TYPE_HARDWARE} 15861 * @param paint The paint used to compose the layer. This argument is optional 15862 * and can be null. It is ignored when the layer type is 15863 * {@link #LAYER_TYPE_NONE} 15864 * 15865 * @see #getLayerType() 15866 * @see #LAYER_TYPE_NONE 15867 * @see #LAYER_TYPE_SOFTWARE 15868 * @see #LAYER_TYPE_HARDWARE 15869 * @see #setAlpha(float) 15870 * 15871 * @attr ref android.R.styleable#View_layerType 15872 */ setLayerType(int layerType, @Nullable Paint paint)15873 public void setLayerType(int layerType, @Nullable Paint paint) { 15874 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 15875 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 15876 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 15877 } 15878 15879 boolean typeChanged = mRenderNode.setLayerType(layerType); 15880 15881 if (!typeChanged) { 15882 setLayerPaint(paint); 15883 return; 15884 } 15885 15886 if (layerType != LAYER_TYPE_SOFTWARE) { 15887 // Destroy any previous software drawing cache if present 15888 // NOTE: even if previous layer type is HW, we do this to ensure we've cleaned up 15889 // drawing cache created in View#draw when drawing to a SW canvas. 15890 destroyDrawingCache(); 15891 } 15892 15893 mLayerType = layerType; 15894 mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint; 15895 mRenderNode.setLayerPaint(mLayerPaint); 15896 15897 // draw() behaves differently if we are on a layer, so we need to 15898 // invalidate() here 15899 invalidateParentCaches(); 15900 invalidate(true); 15901 } 15902 15903 /** 15904 * Updates the {@link Paint} object used with the current layer (used only if the current 15905 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 15906 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 15907 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 15908 * ensure that the view gets redrawn immediately. 15909 * 15910 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15911 * instance that controls how the layer is composed on screen. The following 15912 * properties of the paint are taken into account when composing the layer:</p> 15913 * <ul> 15914 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15915 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15916 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15917 * </ul> 15918 * 15919 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 15920 * alpha value of the layer's paint is superseded by this view's alpha value.</p> 15921 * 15922 * @param paint The paint used to compose the layer. This argument is optional 15923 * and can be null. It is ignored when the layer type is 15924 * {@link #LAYER_TYPE_NONE} 15925 * 15926 * @see #setLayerType(int, android.graphics.Paint) 15927 */ setLayerPaint(@ullable Paint paint)15928 public void setLayerPaint(@Nullable Paint paint) { 15929 int layerType = getLayerType(); 15930 if (layerType != LAYER_TYPE_NONE) { 15931 mLayerPaint = paint; 15932 if (layerType == LAYER_TYPE_HARDWARE) { 15933 if (mRenderNode.setLayerPaint(paint)) { 15934 invalidateViewProperty(false, false); 15935 } 15936 } else { 15937 invalidate(); 15938 } 15939 } 15940 } 15941 15942 /** 15943 * Indicates what type of layer is currently associated with this view. By default 15944 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 15945 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 15946 * for more information on the different types of layers. 15947 * 15948 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15949 * {@link #LAYER_TYPE_HARDWARE} 15950 * 15951 * @see #setLayerType(int, android.graphics.Paint) 15952 * @see #buildLayer() 15953 * @see #LAYER_TYPE_NONE 15954 * @see #LAYER_TYPE_SOFTWARE 15955 * @see #LAYER_TYPE_HARDWARE 15956 */ getLayerType()15957 public int getLayerType() { 15958 return mLayerType; 15959 } 15960 15961 /** 15962 * Forces this view's layer to be created and this view to be rendered 15963 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 15964 * invoking this method will have no effect. 15965 * 15966 * This method can for instance be used to render a view into its layer before 15967 * starting an animation. If this view is complex, rendering into the layer 15968 * before starting the animation will avoid skipping frames. 15969 * 15970 * @throws IllegalStateException If this view is not attached to a window 15971 * 15972 * @see #setLayerType(int, android.graphics.Paint) 15973 */ buildLayer()15974 public void buildLayer() { 15975 if (mLayerType == LAYER_TYPE_NONE) return; 15976 15977 final AttachInfo attachInfo = mAttachInfo; 15978 if (attachInfo == null) { 15979 throw new IllegalStateException("This view must be attached to a window first"); 15980 } 15981 15982 if (getWidth() == 0 || getHeight() == 0) { 15983 return; 15984 } 15985 15986 switch (mLayerType) { 15987 case LAYER_TYPE_HARDWARE: 15988 updateDisplayListIfDirty(); 15989 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) { 15990 attachInfo.mHardwareRenderer.buildLayer(mRenderNode); 15991 } 15992 break; 15993 case LAYER_TYPE_SOFTWARE: 15994 buildDrawingCache(true); 15995 break; 15996 } 15997 } 15998 15999 /** 16000 * Destroys all hardware rendering resources. This method is invoked 16001 * when the system needs to reclaim resources. Upon execution of this 16002 * method, you should free any OpenGL resources created by the view. 16003 * 16004 * Note: you <strong>must</strong> call 16005 * <code>super.destroyHardwareResources()</code> when overriding 16006 * this method. 16007 * 16008 * @hide 16009 */ 16010 @CallSuper destroyHardwareResources()16011 protected void destroyHardwareResources() { 16012 // Although the Layer will be destroyed by RenderNode, we want to release 16013 // the staging display list, which is also a signal to RenderNode that it's 16014 // safe to free its copy of the display list as it knows that we will 16015 // push an updated DisplayList if we try to draw again 16016 resetDisplayList(); 16017 } 16018 16019 /** 16020 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 16021 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 16022 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 16023 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 16024 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 16025 * null.</p> 16026 * 16027 * <p>Enabling the drawing cache is similar to 16028 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 16029 * acceleration is turned off. When hardware acceleration is turned on, enabling the 16030 * drawing cache has no effect on rendering because the system uses a different mechanism 16031 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 16032 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 16033 * for information on how to enable software and hardware layers.</p> 16034 * 16035 * <p>This API can be used to manually generate 16036 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 16037 * {@link #getDrawingCache()}.</p> 16038 * 16039 * @param enabled true to enable the drawing cache, false otherwise 16040 * 16041 * @see #isDrawingCacheEnabled() 16042 * @see #getDrawingCache() 16043 * @see #buildDrawingCache() 16044 * @see #setLayerType(int, android.graphics.Paint) 16045 */ setDrawingCacheEnabled(boolean enabled)16046 public void setDrawingCacheEnabled(boolean enabled) { 16047 mCachingFailed = false; 16048 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 16049 } 16050 16051 /** 16052 * <p>Indicates whether the drawing cache is enabled for this view.</p> 16053 * 16054 * @return true if the drawing cache is enabled 16055 * 16056 * @see #setDrawingCacheEnabled(boolean) 16057 * @see #getDrawingCache() 16058 */ 16059 @ViewDebug.ExportedProperty(category = "drawing") isDrawingCacheEnabled()16060 public boolean isDrawingCacheEnabled() { 16061 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 16062 } 16063 16064 /** 16065 * Debugging utility which recursively outputs the dirty state of a view and its 16066 * descendants. 16067 * 16068 * @hide 16069 */ 16070 @SuppressWarnings({"UnusedDeclaration"}) outputDirtyFlags(String indent, boolean clear, int clearMask)16071 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 16072 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) + 16073 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" + 16074 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) + 16075 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 16076 if (clear) { 16077 mPrivateFlags &= clearMask; 16078 } 16079 if (this instanceof ViewGroup) { 16080 ViewGroup parent = (ViewGroup) this; 16081 final int count = parent.getChildCount(); 16082 for (int i = 0; i < count; i++) { 16083 final View child = parent.getChildAt(i); 16084 child.outputDirtyFlags(indent + " ", clear, clearMask); 16085 } 16086 } 16087 } 16088 16089 /** 16090 * This method is used by ViewGroup to cause its children to restore or recreate their 16091 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 16092 * to recreate its own display list, which would happen if it went through the normal 16093 * draw/dispatchDraw mechanisms. 16094 * 16095 * @hide 16096 */ dispatchGetDisplayList()16097 protected void dispatchGetDisplayList() {} 16098 16099 /** 16100 * A view that is not attached or hardware accelerated cannot create a display list. 16101 * This method checks these conditions and returns the appropriate result. 16102 * 16103 * @return true if view has the ability to create a display list, false otherwise. 16104 * 16105 * @hide 16106 */ canHaveDisplayList()16107 public boolean canHaveDisplayList() { 16108 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 16109 } 16110 16111 /** 16112 * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported) 16113 * @hide 16114 */ 16115 @NonNull updateDisplayListIfDirty()16116 public RenderNode updateDisplayListIfDirty() { 16117 final RenderNode renderNode = mRenderNode; 16118 if (!canHaveDisplayList()) { 16119 // can't populate RenderNode, don't try 16120 return renderNode; 16121 } 16122 16123 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 16124 || !renderNode.isValid() 16125 || (mRecreateDisplayList)) { 16126 // Don't need to recreate the display list, just need to tell our 16127 // children to restore/recreate theirs 16128 if (renderNode.isValid() 16129 && !mRecreateDisplayList) { 16130 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16131 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16132 dispatchGetDisplayList(); 16133 16134 return renderNode; // no work needed 16135 } 16136 16137 // If we got here, we're recreating it. Mark it as such to ensure that 16138 // we copy in child display lists into ours in drawChild() 16139 mRecreateDisplayList = true; 16140 16141 int width = mRight - mLeft; 16142 int height = mBottom - mTop; 16143 int layerType = getLayerType(); 16144 16145 final DisplayListCanvas canvas = renderNode.start(width, height); 16146 canvas.setHighContrastText(mAttachInfo.mHighContrastText); 16147 16148 try { 16149 if (layerType == LAYER_TYPE_SOFTWARE) { 16150 buildDrawingCache(true); 16151 Bitmap cache = getDrawingCache(true); 16152 if (cache != null) { 16153 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 16154 } 16155 } else { 16156 computeScroll(); 16157 16158 canvas.translate(-mScrollX, -mScrollY); 16159 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16160 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16161 16162 // Fast path for layouts with no backgrounds 16163 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16164 dispatchDraw(canvas); 16165 if (mOverlay != null && !mOverlay.isEmpty()) { 16166 mOverlay.getOverlayView().draw(canvas); 16167 } 16168 } else { 16169 draw(canvas); 16170 } 16171 } 16172 } finally { 16173 renderNode.end(canvas); 16174 setDisplayListProperties(renderNode); 16175 } 16176 } else { 16177 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 16178 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16179 } 16180 return renderNode; 16181 } 16182 resetDisplayList()16183 private void resetDisplayList() { 16184 if (mRenderNode.isValid()) { 16185 mRenderNode.discardDisplayList(); 16186 } 16187 16188 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { 16189 mBackgroundRenderNode.discardDisplayList(); 16190 } 16191 } 16192 16193 /** 16194 * Called when the passed RenderNode is removed from the draw tree 16195 * @hide 16196 */ onRenderNodeDetached(RenderNode renderNode)16197 public void onRenderNodeDetached(RenderNode renderNode) { 16198 } 16199 16200 /** 16201 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 16202 * 16203 * @return A non-scaled bitmap representing this view or null if cache is disabled. 16204 * 16205 * @see #getDrawingCache(boolean) 16206 */ getDrawingCache()16207 public Bitmap getDrawingCache() { 16208 return getDrawingCache(false); 16209 } 16210 16211 /** 16212 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 16213 * is null when caching is disabled. If caching is enabled and the cache is not ready, 16214 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 16215 * draw from the cache when the cache is enabled. To benefit from the cache, you must 16216 * request the drawing cache by calling this method and draw it on screen if the 16217 * returned bitmap is not null.</p> 16218 * 16219 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 16220 * this method will create a bitmap of the same size as this view. Because this bitmap 16221 * will be drawn scaled by the parent ViewGroup, the result on screen might show 16222 * scaling artifacts. To avoid such artifacts, you should call this method by setting 16223 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 16224 * size than the view. This implies that your application must be able to handle this 16225 * size.</p> 16226 * 16227 * @param autoScale Indicates whether the generated bitmap should be scaled based on 16228 * the current density of the screen when the application is in compatibility 16229 * mode. 16230 * 16231 * @return A bitmap representing this view or null if cache is disabled. 16232 * 16233 * @see #setDrawingCacheEnabled(boolean) 16234 * @see #isDrawingCacheEnabled() 16235 * @see #buildDrawingCache(boolean) 16236 * @see #destroyDrawingCache() 16237 */ getDrawingCache(boolean autoScale)16238 public Bitmap getDrawingCache(boolean autoScale) { 16239 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 16240 return null; 16241 } 16242 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 16243 buildDrawingCache(autoScale); 16244 } 16245 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 16246 } 16247 16248 /** 16249 * <p>Frees the resources used by the drawing cache. If you call 16250 * {@link #buildDrawingCache()} manually without calling 16251 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 16252 * should cleanup the cache with this method afterwards.</p> 16253 * 16254 * @see #setDrawingCacheEnabled(boolean) 16255 * @see #buildDrawingCache() 16256 * @see #getDrawingCache() 16257 */ destroyDrawingCache()16258 public void destroyDrawingCache() { 16259 if (mDrawingCache != null) { 16260 mDrawingCache.recycle(); 16261 mDrawingCache = null; 16262 } 16263 if (mUnscaledDrawingCache != null) { 16264 mUnscaledDrawingCache.recycle(); 16265 mUnscaledDrawingCache = null; 16266 } 16267 } 16268 16269 /** 16270 * Setting a solid background color for the drawing cache's bitmaps will improve 16271 * performance and memory usage. Note, though that this should only be used if this 16272 * view will always be drawn on top of a solid color. 16273 * 16274 * @param color The background color to use for the drawing cache's bitmap 16275 * 16276 * @see #setDrawingCacheEnabled(boolean) 16277 * @see #buildDrawingCache() 16278 * @see #getDrawingCache() 16279 */ setDrawingCacheBackgroundColor(@olorInt int color)16280 public void setDrawingCacheBackgroundColor(@ColorInt int color) { 16281 if (color != mDrawingCacheBackgroundColor) { 16282 mDrawingCacheBackgroundColor = color; 16283 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 16284 } 16285 } 16286 16287 /** 16288 * @see #setDrawingCacheBackgroundColor(int) 16289 * 16290 * @return The background color to used for the drawing cache's bitmap 16291 */ 16292 @ColorInt getDrawingCacheBackgroundColor()16293 public int getDrawingCacheBackgroundColor() { 16294 return mDrawingCacheBackgroundColor; 16295 } 16296 16297 /** 16298 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 16299 * 16300 * @see #buildDrawingCache(boolean) 16301 */ buildDrawingCache()16302 public void buildDrawingCache() { 16303 buildDrawingCache(false); 16304 } 16305 16306 /** 16307 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 16308 * 16309 * <p>If you call {@link #buildDrawingCache()} manually without calling 16310 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 16311 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 16312 * 16313 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 16314 * this method will create a bitmap of the same size as this view. Because this bitmap 16315 * will be drawn scaled by the parent ViewGroup, the result on screen might show 16316 * scaling artifacts. To avoid such artifacts, you should call this method by setting 16317 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 16318 * size than the view. This implies that your application must be able to handle this 16319 * size.</p> 16320 * 16321 * <p>You should avoid calling this method when hardware acceleration is enabled. If 16322 * you do not need the drawing cache bitmap, calling this method will increase memory 16323 * usage and cause the view to be rendered in software once, thus negatively impacting 16324 * performance.</p> 16325 * 16326 * @see #getDrawingCache() 16327 * @see #destroyDrawingCache() 16328 */ buildDrawingCache(boolean autoScale)16329 public void buildDrawingCache(boolean autoScale) { 16330 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 16331 mDrawingCache == null : mUnscaledDrawingCache == null)) { 16332 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 16333 Trace.traceBegin(Trace.TRACE_TAG_VIEW, 16334 "buildDrawingCache/SW Layer for " + getClass().getSimpleName()); 16335 } 16336 try { 16337 buildDrawingCacheImpl(autoScale); 16338 } finally { 16339 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 16340 } 16341 } 16342 } 16343 16344 /** 16345 * private, internal implementation of buildDrawingCache, used to enable tracing 16346 */ buildDrawingCacheImpl(boolean autoScale)16347 private void buildDrawingCacheImpl(boolean autoScale) { 16348 mCachingFailed = false; 16349 16350 int width = mRight - mLeft; 16351 int height = mBottom - mTop; 16352 16353 final AttachInfo attachInfo = mAttachInfo; 16354 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 16355 16356 if (autoScale && scalingRequired) { 16357 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 16358 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 16359 } 16360 16361 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 16362 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 16363 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 16364 16365 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 16366 final long drawingCacheSize = 16367 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 16368 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 16369 if (width > 0 && height > 0) { 16370 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is" 16371 + " too large to fit into a software layer (or drawing cache), needs " 16372 + projectedBitmapSize + " bytes, only " 16373 + drawingCacheSize + " available"); 16374 } 16375 destroyDrawingCache(); 16376 mCachingFailed = true; 16377 return; 16378 } 16379 16380 boolean clear = true; 16381 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 16382 16383 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 16384 Bitmap.Config quality; 16385 if (!opaque) { 16386 // Never pick ARGB_4444 because it looks awful 16387 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 16388 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 16389 case DRAWING_CACHE_QUALITY_AUTO: 16390 case DRAWING_CACHE_QUALITY_LOW: 16391 case DRAWING_CACHE_QUALITY_HIGH: 16392 default: 16393 quality = Bitmap.Config.ARGB_8888; 16394 break; 16395 } 16396 } else { 16397 // Optimization for translucent windows 16398 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 16399 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 16400 } 16401 16402 // Try to cleanup memory 16403 if (bitmap != null) bitmap.recycle(); 16404 16405 try { 16406 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 16407 width, height, quality); 16408 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 16409 if (autoScale) { 16410 mDrawingCache = bitmap; 16411 } else { 16412 mUnscaledDrawingCache = bitmap; 16413 } 16414 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 16415 } catch (OutOfMemoryError e) { 16416 // If there is not enough memory to create the bitmap cache, just 16417 // ignore the issue as bitmap caches are not required to draw the 16418 // view hierarchy 16419 if (autoScale) { 16420 mDrawingCache = null; 16421 } else { 16422 mUnscaledDrawingCache = null; 16423 } 16424 mCachingFailed = true; 16425 return; 16426 } 16427 16428 clear = drawingCacheBackgroundColor != 0; 16429 } 16430 16431 Canvas canvas; 16432 if (attachInfo != null) { 16433 canvas = attachInfo.mCanvas; 16434 if (canvas == null) { 16435 canvas = new Canvas(); 16436 } 16437 canvas.setBitmap(bitmap); 16438 // Temporarily clobber the cached Canvas in case one of our children 16439 // is also using a drawing cache. Without this, the children would 16440 // steal the canvas by attaching their own bitmap to it and bad, bad 16441 // thing would happen (invisible views, corrupted drawings, etc.) 16442 attachInfo.mCanvas = null; 16443 } else { 16444 // This case should hopefully never or seldom happen 16445 canvas = new Canvas(bitmap); 16446 } 16447 16448 if (clear) { 16449 bitmap.eraseColor(drawingCacheBackgroundColor); 16450 } 16451 16452 computeScroll(); 16453 final int restoreCount = canvas.save(); 16454 16455 if (autoScale && scalingRequired) { 16456 final float scale = attachInfo.mApplicationScale; 16457 canvas.scale(scale, scale); 16458 } 16459 16460 canvas.translate(-mScrollX, -mScrollY); 16461 16462 mPrivateFlags |= PFLAG_DRAWN; 16463 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 16464 mLayerType != LAYER_TYPE_NONE) { 16465 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 16466 } 16467 16468 // Fast path for layouts with no backgrounds 16469 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16470 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16471 dispatchDraw(canvas); 16472 if (mOverlay != null && !mOverlay.isEmpty()) { 16473 mOverlay.getOverlayView().draw(canvas); 16474 } 16475 } else { 16476 draw(canvas); 16477 } 16478 16479 canvas.restoreToCount(restoreCount); 16480 canvas.setBitmap(null); 16481 16482 if (attachInfo != null) { 16483 // Restore the cached Canvas for our siblings 16484 attachInfo.mCanvas = canvas; 16485 } 16486 } 16487 16488 /** 16489 * Create a snapshot of the view into a bitmap. We should probably make 16490 * some form of this public, but should think about the API. 16491 * 16492 * @hide 16493 */ createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren)16494 public Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 16495 int width = mRight - mLeft; 16496 int height = mBottom - mTop; 16497 16498 final AttachInfo attachInfo = mAttachInfo; 16499 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 16500 width = (int) ((width * scale) + 0.5f); 16501 height = (int) ((height * scale) + 0.5f); 16502 16503 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 16504 width > 0 ? width : 1, height > 0 ? height : 1, quality); 16505 if (bitmap == null) { 16506 throw new OutOfMemoryError(); 16507 } 16508 16509 Resources resources = getResources(); 16510 if (resources != null) { 16511 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 16512 } 16513 16514 Canvas canvas; 16515 if (attachInfo != null) { 16516 canvas = attachInfo.mCanvas; 16517 if (canvas == null) { 16518 canvas = new Canvas(); 16519 } 16520 canvas.setBitmap(bitmap); 16521 // Temporarily clobber the cached Canvas in case one of our children 16522 // is also using a drawing cache. Without this, the children would 16523 // steal the canvas by attaching their own bitmap to it and bad, bad 16524 // things would happen (invisible views, corrupted drawings, etc.) 16525 attachInfo.mCanvas = null; 16526 } else { 16527 // This case should hopefully never or seldom happen 16528 canvas = new Canvas(bitmap); 16529 } 16530 16531 if ((backgroundColor & 0xff000000) != 0) { 16532 bitmap.eraseColor(backgroundColor); 16533 } 16534 16535 computeScroll(); 16536 final int restoreCount = canvas.save(); 16537 canvas.scale(scale, scale); 16538 canvas.translate(-mScrollX, -mScrollY); 16539 16540 // Temporarily remove the dirty mask 16541 int flags = mPrivateFlags; 16542 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16543 16544 // Fast path for layouts with no backgrounds 16545 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16546 dispatchDraw(canvas); 16547 if (mOverlay != null && !mOverlay.isEmpty()) { 16548 mOverlay.getOverlayView().draw(canvas); 16549 } 16550 } else { 16551 draw(canvas); 16552 } 16553 16554 mPrivateFlags = flags; 16555 16556 canvas.restoreToCount(restoreCount); 16557 canvas.setBitmap(null); 16558 16559 if (attachInfo != null) { 16560 // Restore the cached Canvas for our siblings 16561 attachInfo.mCanvas = canvas; 16562 } 16563 16564 return bitmap; 16565 } 16566 16567 /** 16568 * Indicates whether this View is currently in edit mode. A View is usually 16569 * in edit mode when displayed within a developer tool. For instance, if 16570 * this View is being drawn by a visual user interface builder, this method 16571 * should return true. 16572 * 16573 * Subclasses should check the return value of this method to provide 16574 * different behaviors if their normal behavior might interfere with the 16575 * host environment. For instance: the class spawns a thread in its 16576 * constructor, the drawing code relies on device-specific features, etc. 16577 * 16578 * This method is usually checked in the drawing code of custom widgets. 16579 * 16580 * @return True if this View is in edit mode, false otherwise. 16581 */ isInEditMode()16582 public boolean isInEditMode() { 16583 return false; 16584 } 16585 16586 /** 16587 * If the View draws content inside its padding and enables fading edges, 16588 * it needs to support padding offsets. Padding offsets are added to the 16589 * fading edges to extend the length of the fade so that it covers pixels 16590 * drawn inside the padding. 16591 * 16592 * Subclasses of this class should override this method if they need 16593 * to draw content inside the padding. 16594 * 16595 * @return True if padding offset must be applied, false otherwise. 16596 * 16597 * @see #getLeftPaddingOffset() 16598 * @see #getRightPaddingOffset() 16599 * @see #getTopPaddingOffset() 16600 * @see #getBottomPaddingOffset() 16601 * 16602 * @since CURRENT 16603 */ isPaddingOffsetRequired()16604 protected boolean isPaddingOffsetRequired() { 16605 return false; 16606 } 16607 16608 /** 16609 * Amount by which to extend the left fading region. Called only when 16610 * {@link #isPaddingOffsetRequired()} returns true. 16611 * 16612 * @return The left padding offset in pixels. 16613 * 16614 * @see #isPaddingOffsetRequired() 16615 * 16616 * @since CURRENT 16617 */ getLeftPaddingOffset()16618 protected int getLeftPaddingOffset() { 16619 return 0; 16620 } 16621 16622 /** 16623 * Amount by which to extend the right fading region. Called only when 16624 * {@link #isPaddingOffsetRequired()} returns true. 16625 * 16626 * @return The right padding offset in pixels. 16627 * 16628 * @see #isPaddingOffsetRequired() 16629 * 16630 * @since CURRENT 16631 */ getRightPaddingOffset()16632 protected int getRightPaddingOffset() { 16633 return 0; 16634 } 16635 16636 /** 16637 * Amount by which to extend the top fading region. Called only when 16638 * {@link #isPaddingOffsetRequired()} returns true. 16639 * 16640 * @return The top padding offset in pixels. 16641 * 16642 * @see #isPaddingOffsetRequired() 16643 * 16644 * @since CURRENT 16645 */ getTopPaddingOffset()16646 protected int getTopPaddingOffset() { 16647 return 0; 16648 } 16649 16650 /** 16651 * Amount by which to extend the bottom fading region. Called only when 16652 * {@link #isPaddingOffsetRequired()} returns true. 16653 * 16654 * @return The bottom padding offset in pixels. 16655 * 16656 * @see #isPaddingOffsetRequired() 16657 * 16658 * @since CURRENT 16659 */ getBottomPaddingOffset()16660 protected int getBottomPaddingOffset() { 16661 return 0; 16662 } 16663 16664 /** 16665 * @hide 16666 * @param offsetRequired 16667 */ getFadeTop(boolean offsetRequired)16668 protected int getFadeTop(boolean offsetRequired) { 16669 int top = mPaddingTop; 16670 if (offsetRequired) top += getTopPaddingOffset(); 16671 return top; 16672 } 16673 16674 /** 16675 * @hide 16676 * @param offsetRequired 16677 */ getFadeHeight(boolean offsetRequired)16678 protected int getFadeHeight(boolean offsetRequired) { 16679 int padding = mPaddingTop; 16680 if (offsetRequired) padding += getTopPaddingOffset(); 16681 return mBottom - mTop - mPaddingBottom - padding; 16682 } 16683 16684 /** 16685 * <p>Indicates whether this view is attached to a hardware accelerated 16686 * window or not.</p> 16687 * 16688 * <p>Even if this method returns true, it does not mean that every call 16689 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 16690 * accelerated {@link android.graphics.Canvas}. For instance, if this view 16691 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 16692 * window is hardware accelerated, 16693 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 16694 * return false, and this method will return true.</p> 16695 * 16696 * @return True if the view is attached to a window and the window is 16697 * hardware accelerated; false in any other case. 16698 */ 16699 @ViewDebug.ExportedProperty(category = "drawing") isHardwareAccelerated()16700 public boolean isHardwareAccelerated() { 16701 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 16702 } 16703 16704 /** 16705 * Sets a rectangular area on this view to which the view will be clipped 16706 * when it is drawn. Setting the value to null will remove the clip bounds 16707 * and the view will draw normally, using its full bounds. 16708 * 16709 * @param clipBounds The rectangular area, in the local coordinates of 16710 * this view, to which future drawing operations will be clipped. 16711 */ setClipBounds(Rect clipBounds)16712 public void setClipBounds(Rect clipBounds) { 16713 if (clipBounds == mClipBounds 16714 || (clipBounds != null && clipBounds.equals(mClipBounds))) { 16715 return; 16716 } 16717 if (clipBounds != null) { 16718 if (mClipBounds == null) { 16719 mClipBounds = new Rect(clipBounds); 16720 } else { 16721 mClipBounds.set(clipBounds); 16722 } 16723 } else { 16724 mClipBounds = null; 16725 } 16726 mRenderNode.setClipBounds(mClipBounds); 16727 invalidateViewProperty(false, false); 16728 } 16729 16730 /** 16731 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 16732 * 16733 * @return A copy of the current clip bounds if clip bounds are set, 16734 * otherwise null. 16735 */ getClipBounds()16736 public Rect getClipBounds() { 16737 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 16738 } 16739 16740 16741 /** 16742 * Populates an output rectangle with the clip bounds of the view, 16743 * returning {@code true} if successful or {@code false} if the view's 16744 * clip bounds are {@code null}. 16745 * 16746 * @param outRect rectangle in which to place the clip bounds of the view 16747 * @return {@code true} if successful or {@code false} if the view's 16748 * clip bounds are {@code null} 16749 */ getClipBounds(Rect outRect)16750 public boolean getClipBounds(Rect outRect) { 16751 if (mClipBounds != null) { 16752 outRect.set(mClipBounds); 16753 return true; 16754 } 16755 return false; 16756 } 16757 16758 /** 16759 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 16760 * case of an active Animation being run on the view. 16761 */ applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired)16762 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, 16763 Animation a, boolean scalingRequired) { 16764 Transformation invalidationTransform; 16765 final int flags = parent.mGroupFlags; 16766 final boolean initialized = a.isInitialized(); 16767 if (!initialized) { 16768 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 16769 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 16770 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 16771 onAnimationStart(); 16772 } 16773 16774 final Transformation t = parent.getChildTransformation(); 16775 boolean more = a.getTransformation(drawingTime, t, 1f); 16776 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 16777 if (parent.mInvalidationTransformation == null) { 16778 parent.mInvalidationTransformation = new Transformation(); 16779 } 16780 invalidationTransform = parent.mInvalidationTransformation; 16781 a.getTransformation(drawingTime, invalidationTransform, 1f); 16782 } else { 16783 invalidationTransform = t; 16784 } 16785 16786 if (more) { 16787 if (!a.willChangeBounds()) { 16788 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 16789 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 16790 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 16791 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 16792 // The child need to draw an animation, potentially offscreen, so 16793 // make sure we do not cancel invalidate requests 16794 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16795 parent.invalidate(mLeft, mTop, mRight, mBottom); 16796 } 16797 } else { 16798 if (parent.mInvalidateRegion == null) { 16799 parent.mInvalidateRegion = new RectF(); 16800 } 16801 final RectF region = parent.mInvalidateRegion; 16802 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 16803 invalidationTransform); 16804 16805 // The child need to draw an animation, potentially offscreen, so 16806 // make sure we do not cancel invalidate requests 16807 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16808 16809 final int left = mLeft + (int) region.left; 16810 final int top = mTop + (int) region.top; 16811 parent.invalidate(left, top, left + (int) (region.width() + .5f), 16812 top + (int) (region.height() + .5f)); 16813 } 16814 } 16815 return more; 16816 } 16817 16818 /** 16819 * This method is called by getDisplayList() when a display list is recorded for a View. 16820 * It pushes any properties to the RenderNode that aren't managed by the RenderNode. 16821 */ setDisplayListProperties(RenderNode renderNode)16822 void setDisplayListProperties(RenderNode renderNode) { 16823 if (renderNode != null) { 16824 renderNode.setHasOverlappingRendering(getHasOverlappingRendering()); 16825 renderNode.setClipToBounds(mParent instanceof ViewGroup 16826 && ((ViewGroup) mParent).getClipChildren()); 16827 16828 float alpha = 1; 16829 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 16830 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16831 ViewGroup parentVG = (ViewGroup) mParent; 16832 final Transformation t = parentVG.getChildTransformation(); 16833 if (parentVG.getChildStaticTransformation(this, t)) { 16834 final int transformType = t.getTransformationType(); 16835 if (transformType != Transformation.TYPE_IDENTITY) { 16836 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 16837 alpha = t.getAlpha(); 16838 } 16839 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 16840 renderNode.setStaticMatrix(t.getMatrix()); 16841 } 16842 } 16843 } 16844 } 16845 if (mTransformationInfo != null) { 16846 alpha *= getFinalAlpha(); 16847 if (alpha < 1) { 16848 final int multipliedAlpha = (int) (255 * alpha); 16849 if (onSetAlpha(multipliedAlpha)) { 16850 alpha = 1; 16851 } 16852 } 16853 renderNode.setAlpha(alpha); 16854 } else if (alpha < 1) { 16855 renderNode.setAlpha(alpha); 16856 } 16857 } 16858 } 16859 16860 /** 16861 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 16862 * 16863 * This is where the View specializes rendering behavior based on layer type, 16864 * and hardware acceleration. 16865 */ draw(Canvas canvas, ViewGroup parent, long drawingTime)16866 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 16867 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated(); 16868 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList. 16869 * 16870 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't 16871 * HW accelerated, it can't handle drawing RenderNodes. 16872 */ 16873 boolean drawingWithRenderNode = mAttachInfo != null 16874 && mAttachInfo.mHardwareAccelerated 16875 && hardwareAcceleratedCanvas; 16876 16877 boolean more = false; 16878 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 16879 final int parentFlags = parent.mGroupFlags; 16880 16881 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) { 16882 parent.getChildTransformation().clear(); 16883 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16884 } 16885 16886 Transformation transformToApply = null; 16887 boolean concatMatrix = false; 16888 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired; 16889 final Animation a = getAnimation(); 16890 if (a != null) { 16891 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); 16892 concatMatrix = a.willChangeTransformationMatrix(); 16893 if (concatMatrix) { 16894 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16895 } 16896 transformToApply = parent.getChildTransformation(); 16897 } else { 16898 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { 16899 // No longer animating: clear out old animation matrix 16900 mRenderNode.setAnimationMatrix(null); 16901 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16902 } 16903 if (!drawingWithRenderNode 16904 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16905 final Transformation t = parent.getChildTransformation(); 16906 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 16907 if (hasTransform) { 16908 final int transformType = t.getTransformationType(); 16909 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 16910 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 16911 } 16912 } 16913 } 16914 16915 concatMatrix |= !childHasIdentityMatrix; 16916 16917 // Sets the flag as early as possible to allow draw() implementations 16918 // to call invalidate() successfully when doing animations 16919 mPrivateFlags |= PFLAG_DRAWN; 16920 16921 if (!concatMatrix && 16922 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 16923 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 16924 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 16925 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 16926 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 16927 return more; 16928 } 16929 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 16930 16931 if (hardwareAcceleratedCanvas) { 16932 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 16933 // retain the flag's value temporarily in the mRecreateDisplayList flag 16934 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0; 16935 mPrivateFlags &= ~PFLAG_INVALIDATED; 16936 } 16937 16938 RenderNode renderNode = null; 16939 Bitmap cache = null; 16940 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local 16941 if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) { 16942 if (layerType != LAYER_TYPE_NONE) { 16943 // If not drawing with RenderNode, treat HW layers as SW 16944 layerType = LAYER_TYPE_SOFTWARE; 16945 buildDrawingCache(true); 16946 } 16947 cache = getDrawingCache(true); 16948 } 16949 16950 if (drawingWithRenderNode) { 16951 // Delay getting the display list until animation-driven alpha values are 16952 // set up and possibly passed on to the view 16953 renderNode = updateDisplayListIfDirty(); 16954 if (!renderNode.isValid()) { 16955 // Uncommon, but possible. If a view is removed from the hierarchy during the call 16956 // to getDisplayList(), the display list will be marked invalid and we should not 16957 // try to use it again. 16958 renderNode = null; 16959 drawingWithRenderNode = false; 16960 } 16961 } 16962 16963 int sx = 0; 16964 int sy = 0; 16965 if (!drawingWithRenderNode) { 16966 computeScroll(); 16967 sx = mScrollX; 16968 sy = mScrollY; 16969 } 16970 16971 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode; 16972 final boolean offsetForScroll = cache == null && !drawingWithRenderNode; 16973 16974 int restoreTo = -1; 16975 if (!drawingWithRenderNode || transformToApply != null) { 16976 restoreTo = canvas.save(); 16977 } 16978 if (offsetForScroll) { 16979 canvas.translate(mLeft - sx, mTop - sy); 16980 } else { 16981 if (!drawingWithRenderNode) { 16982 canvas.translate(mLeft, mTop); 16983 } 16984 if (scalingRequired) { 16985 if (drawingWithRenderNode) { 16986 // TODO: Might not need this if we put everything inside the DL 16987 restoreTo = canvas.save(); 16988 } 16989 // mAttachInfo cannot be null, otherwise scalingRequired == false 16990 final float scale = 1.0f / mAttachInfo.mApplicationScale; 16991 canvas.scale(scale, scale); 16992 } 16993 } 16994 16995 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha()); 16996 if (transformToApply != null 16997 || alpha < 1 16998 || !hasIdentityMatrix() 16999 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 17000 if (transformToApply != null || !childHasIdentityMatrix) { 17001 int transX = 0; 17002 int transY = 0; 17003 17004 if (offsetForScroll) { 17005 transX = -sx; 17006 transY = -sy; 17007 } 17008 17009 if (transformToApply != null) { 17010 if (concatMatrix) { 17011 if (drawingWithRenderNode) { 17012 renderNode.setAnimationMatrix(transformToApply.getMatrix()); 17013 } else { 17014 // Undo the scroll translation, apply the transformation matrix, 17015 // then redo the scroll translate to get the correct result. 17016 canvas.translate(-transX, -transY); 17017 canvas.concat(transformToApply.getMatrix()); 17018 canvas.translate(transX, transY); 17019 } 17020 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 17021 } 17022 17023 float transformAlpha = transformToApply.getAlpha(); 17024 if (transformAlpha < 1) { 17025 alpha *= transformAlpha; 17026 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 17027 } 17028 } 17029 17030 if (!childHasIdentityMatrix && !drawingWithRenderNode) { 17031 canvas.translate(-transX, -transY); 17032 canvas.concat(getMatrix()); 17033 canvas.translate(transX, transY); 17034 } 17035 } 17036 17037 // Deal with alpha if it is or used to be <1 17038 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 17039 if (alpha < 1) { 17040 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 17041 } else { 17042 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 17043 } 17044 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 17045 if (!drawingWithDrawingCache) { 17046 final int multipliedAlpha = (int) (255 * alpha); 17047 if (!onSetAlpha(multipliedAlpha)) { 17048 if (drawingWithRenderNode) { 17049 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 17050 } else if (layerType == LAYER_TYPE_NONE) { 17051 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), 17052 multipliedAlpha); 17053 } 17054 } else { 17055 // Alpha is handled by the child directly, clobber the layer's alpha 17056 mPrivateFlags |= PFLAG_ALPHA_SET; 17057 } 17058 } 17059 } 17060 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 17061 onSetAlpha(255); 17062 mPrivateFlags &= ~PFLAG_ALPHA_SET; 17063 } 17064 17065 if (!drawingWithRenderNode) { 17066 // apply clips directly, since RenderNode won't do it for this draw 17067 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) { 17068 if (offsetForScroll) { 17069 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight()); 17070 } else { 17071 if (!scalingRequired || cache == null) { 17072 canvas.clipRect(0, 0, getWidth(), getHeight()); 17073 } else { 17074 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 17075 } 17076 } 17077 } 17078 17079 if (mClipBounds != null) { 17080 // clip bounds ignore scroll 17081 canvas.clipRect(mClipBounds); 17082 } 17083 } 17084 17085 if (!drawingWithDrawingCache) { 17086 if (drawingWithRenderNode) { 17087 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 17088 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 17089 } else { 17090 // Fast path for layouts with no backgrounds 17091 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 17092 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 17093 dispatchDraw(canvas); 17094 } else { 17095 draw(canvas); 17096 } 17097 } 17098 } else if (cache != null) { 17099 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 17100 if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) { 17101 // no layer paint, use temporary paint to draw bitmap 17102 Paint cachePaint = parent.mCachePaint; 17103 if (cachePaint == null) { 17104 cachePaint = new Paint(); 17105 cachePaint.setDither(false); 17106 parent.mCachePaint = cachePaint; 17107 } 17108 cachePaint.setAlpha((int) (alpha * 255)); 17109 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 17110 } else { 17111 // use layer paint to draw the bitmap, merging the two alphas, but also restore 17112 int layerPaintAlpha = mLayerPaint.getAlpha(); 17113 if (alpha < 1) { 17114 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha)); 17115 } 17116 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint); 17117 if (alpha < 1) { 17118 mLayerPaint.setAlpha(layerPaintAlpha); 17119 } 17120 } 17121 } 17122 17123 if (restoreTo >= 0) { 17124 canvas.restoreToCount(restoreTo); 17125 } 17126 17127 if (a != null && !more) { 17128 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) { 17129 onSetAlpha(255); 17130 } 17131 parent.finishAnimatingView(this, a); 17132 } 17133 17134 if (more && hardwareAcceleratedCanvas) { 17135 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 17136 // alpha animations should cause the child to recreate its display list 17137 invalidate(true); 17138 } 17139 } 17140 17141 mRecreateDisplayList = false; 17142 17143 return more; 17144 } 17145 17146 /** 17147 * Manually render this view (and all of its children) to the given Canvas. 17148 * The view must have already done a full layout before this function is 17149 * called. When implementing a view, implement 17150 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 17151 * If you do need to override this method, call the superclass version. 17152 * 17153 * @param canvas The Canvas to which the View is rendered. 17154 */ 17155 @CallSuper draw(Canvas canvas)17156 public void draw(Canvas canvas) { 17157 final int privateFlags = mPrivateFlags; 17158 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 17159 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 17160 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 17161 17162 /* 17163 * Draw traversal performs several drawing steps which must be executed 17164 * in the appropriate order: 17165 * 17166 * 1. Draw the background 17167 * 2. If necessary, save the canvas' layers to prepare for fading 17168 * 3. Draw view's content 17169 * 4. Draw children 17170 * 5. If necessary, draw the fading edges and restore layers 17171 * 6. Draw decorations (scrollbars for instance) 17172 */ 17173 17174 // Step 1, draw the background, if needed 17175 int saveCount; 17176 17177 if (!dirtyOpaque) { 17178 drawBackground(canvas); 17179 } 17180 17181 // skip step 2 & 5 if possible (common case) 17182 final int viewFlags = mViewFlags; 17183 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 17184 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 17185 if (!verticalEdges && !horizontalEdges) { 17186 // Step 3, draw the content 17187 if (!dirtyOpaque) onDraw(canvas); 17188 17189 // Step 4, draw the children 17190 dispatchDraw(canvas); 17191 17192 // Overlay is part of the content and draws beneath Foreground 17193 if (mOverlay != null && !mOverlay.isEmpty()) { 17194 mOverlay.getOverlayView().dispatchDraw(canvas); 17195 } 17196 17197 // Step 6, draw decorations (foreground, scrollbars) 17198 onDrawForeground(canvas); 17199 17200 // we're done... 17201 return; 17202 } 17203 17204 /* 17205 * Here we do the full fledged routine... 17206 * (this is an uncommon case where speed matters less, 17207 * this is why we repeat some of the tests that have been 17208 * done above) 17209 */ 17210 17211 boolean drawTop = false; 17212 boolean drawBottom = false; 17213 boolean drawLeft = false; 17214 boolean drawRight = false; 17215 17216 float topFadeStrength = 0.0f; 17217 float bottomFadeStrength = 0.0f; 17218 float leftFadeStrength = 0.0f; 17219 float rightFadeStrength = 0.0f; 17220 17221 // Step 2, save the canvas' layers 17222 int paddingLeft = mPaddingLeft; 17223 17224 final boolean offsetRequired = isPaddingOffsetRequired(); 17225 if (offsetRequired) { 17226 paddingLeft += getLeftPaddingOffset(); 17227 } 17228 17229 int left = mScrollX + paddingLeft; 17230 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 17231 int top = mScrollY + getFadeTop(offsetRequired); 17232 int bottom = top + getFadeHeight(offsetRequired); 17233 17234 if (offsetRequired) { 17235 right += getRightPaddingOffset(); 17236 bottom += getBottomPaddingOffset(); 17237 } 17238 17239 final ScrollabilityCache scrollabilityCache = mScrollCache; 17240 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 17241 int length = (int) fadeHeight; 17242 17243 // clip the fade length if top and bottom fades overlap 17244 // overlapping fades produce odd-looking artifacts 17245 if (verticalEdges && (top + length > bottom - length)) { 17246 length = (bottom - top) / 2; 17247 } 17248 17249 // also clip horizontal fades if necessary 17250 if (horizontalEdges && (left + length > right - length)) { 17251 length = (right - left) / 2; 17252 } 17253 17254 if (verticalEdges) { 17255 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 17256 drawTop = topFadeStrength * fadeHeight > 1.0f; 17257 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 17258 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 17259 } 17260 17261 if (horizontalEdges) { 17262 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 17263 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 17264 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 17265 drawRight = rightFadeStrength * fadeHeight > 1.0f; 17266 } 17267 17268 saveCount = canvas.getSaveCount(); 17269 17270 int solidColor = getSolidColor(); 17271 if (solidColor == 0) { 17272 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 17273 17274 if (drawTop) { 17275 canvas.saveLayer(left, top, right, top + length, null, flags); 17276 } 17277 17278 if (drawBottom) { 17279 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 17280 } 17281 17282 if (drawLeft) { 17283 canvas.saveLayer(left, top, left + length, bottom, null, flags); 17284 } 17285 17286 if (drawRight) { 17287 canvas.saveLayer(right - length, top, right, bottom, null, flags); 17288 } 17289 } else { 17290 scrollabilityCache.setFadeColor(solidColor); 17291 } 17292 17293 // Step 3, draw the content 17294 if (!dirtyOpaque) onDraw(canvas); 17295 17296 // Step 4, draw the children 17297 dispatchDraw(canvas); 17298 17299 // Step 5, draw the fade effect and restore layers 17300 final Paint p = scrollabilityCache.paint; 17301 final Matrix matrix = scrollabilityCache.matrix; 17302 final Shader fade = scrollabilityCache.shader; 17303 17304 if (drawTop) { 17305 matrix.setScale(1, fadeHeight * topFadeStrength); 17306 matrix.postTranslate(left, top); 17307 fade.setLocalMatrix(matrix); 17308 p.setShader(fade); 17309 canvas.drawRect(left, top, right, top + length, p); 17310 } 17311 17312 if (drawBottom) { 17313 matrix.setScale(1, fadeHeight * bottomFadeStrength); 17314 matrix.postRotate(180); 17315 matrix.postTranslate(left, bottom); 17316 fade.setLocalMatrix(matrix); 17317 p.setShader(fade); 17318 canvas.drawRect(left, bottom - length, right, bottom, p); 17319 } 17320 17321 if (drawLeft) { 17322 matrix.setScale(1, fadeHeight * leftFadeStrength); 17323 matrix.postRotate(-90); 17324 matrix.postTranslate(left, top); 17325 fade.setLocalMatrix(matrix); 17326 p.setShader(fade); 17327 canvas.drawRect(left, top, left + length, bottom, p); 17328 } 17329 17330 if (drawRight) { 17331 matrix.setScale(1, fadeHeight * rightFadeStrength); 17332 matrix.postRotate(90); 17333 matrix.postTranslate(right, top); 17334 fade.setLocalMatrix(matrix); 17335 p.setShader(fade); 17336 canvas.drawRect(right - length, top, right, bottom, p); 17337 } 17338 17339 canvas.restoreToCount(saveCount); 17340 17341 // Overlay is part of the content and draws beneath Foreground 17342 if (mOverlay != null && !mOverlay.isEmpty()) { 17343 mOverlay.getOverlayView().dispatchDraw(canvas); 17344 } 17345 17346 // Step 6, draw decorations (foreground, scrollbars) 17347 onDrawForeground(canvas); 17348 } 17349 17350 /** 17351 * Draws the background onto the specified canvas. 17352 * 17353 * @param canvas Canvas on which to draw the background 17354 */ drawBackground(Canvas canvas)17355 private void drawBackground(Canvas canvas) { 17356 final Drawable background = mBackground; 17357 if (background == null) { 17358 return; 17359 } 17360 17361 setBackgroundBounds(); 17362 17363 // Attempt to use a display list if requested. 17364 if (canvas.isHardwareAccelerated() && mAttachInfo != null 17365 && mAttachInfo.mHardwareRenderer != null) { 17366 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); 17367 17368 final RenderNode renderNode = mBackgroundRenderNode; 17369 if (renderNode != null && renderNode.isValid()) { 17370 setBackgroundRenderNodeProperties(renderNode); 17371 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 17372 return; 17373 } 17374 } 17375 17376 final int scrollX = mScrollX; 17377 final int scrollY = mScrollY; 17378 if ((scrollX | scrollY) == 0) { 17379 background.draw(canvas); 17380 } else { 17381 canvas.translate(scrollX, scrollY); 17382 background.draw(canvas); 17383 canvas.translate(-scrollX, -scrollY); 17384 } 17385 } 17386 17387 /** 17388 * Sets the correct background bounds and rebuilds the outline, if needed. 17389 * <p/> 17390 * This is called by LayoutLib. 17391 */ setBackgroundBounds()17392 void setBackgroundBounds() { 17393 if (mBackgroundSizeChanged && mBackground != null) { 17394 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 17395 mBackgroundSizeChanged = false; 17396 rebuildOutline(); 17397 } 17398 } 17399 setBackgroundRenderNodeProperties(RenderNode renderNode)17400 private void setBackgroundRenderNodeProperties(RenderNode renderNode) { 17401 renderNode.setTranslationX(mScrollX); 17402 renderNode.setTranslationY(mScrollY); 17403 } 17404 17405 /** 17406 * Creates a new display list or updates the existing display list for the 17407 * specified Drawable. 17408 * 17409 * @param drawable Drawable for which to create a display list 17410 * @param renderNode Existing RenderNode, or {@code null} 17411 * @return A valid display list for the specified drawable 17412 */ getDrawableRenderNode(Drawable drawable, RenderNode renderNode)17413 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { 17414 if (renderNode == null) { 17415 renderNode = RenderNode.create(drawable.getClass().getName(), this); 17416 } 17417 17418 final Rect bounds = drawable.getBounds(); 17419 final int width = bounds.width(); 17420 final int height = bounds.height(); 17421 final DisplayListCanvas canvas = renderNode.start(width, height); 17422 17423 // Reverse left/top translation done by drawable canvas, which will 17424 // instead be applied by rendernode's LTRB bounds below. This way, the 17425 // drawable's bounds match with its rendernode bounds and its content 17426 // will lie within those bounds in the rendernode tree. 17427 canvas.translate(-bounds.left, -bounds.top); 17428 17429 try { 17430 drawable.draw(canvas); 17431 } finally { 17432 renderNode.end(canvas); 17433 } 17434 17435 // Set up drawable properties that are view-independent. 17436 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); 17437 renderNode.setProjectBackwards(drawable.isProjected()); 17438 renderNode.setProjectionReceiver(true); 17439 renderNode.setClipToBounds(false); 17440 return renderNode; 17441 } 17442 17443 /** 17444 * Returns the overlay for this view, creating it if it does not yet exist. 17445 * Adding drawables to the overlay will cause them to be displayed whenever 17446 * the view itself is redrawn. Objects in the overlay should be actively 17447 * managed: remove them when they should not be displayed anymore. The 17448 * overlay will always have the same size as its host view. 17449 * 17450 * <p>Note: Overlays do not currently work correctly with {@link 17451 * SurfaceView} or {@link TextureView}; contents in overlays for these 17452 * types of views may not display correctly.</p> 17453 * 17454 * @return The ViewOverlay object for this view. 17455 * @see ViewOverlay 17456 */ getOverlay()17457 public ViewOverlay getOverlay() { 17458 if (mOverlay == null) { 17459 mOverlay = new ViewOverlay(mContext, this); 17460 } 17461 return mOverlay; 17462 } 17463 17464 /** 17465 * Override this if your view is known to always be drawn on top of a solid color background, 17466 * and needs to draw fading edges. Returning a non-zero color enables the view system to 17467 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 17468 * should be set to 0xFF. 17469 * 17470 * @see #setVerticalFadingEdgeEnabled(boolean) 17471 * @see #setHorizontalFadingEdgeEnabled(boolean) 17472 * 17473 * @return The known solid color background for this view, or 0 if the color may vary 17474 */ 17475 @ViewDebug.ExportedProperty(category = "drawing") 17476 @ColorInt getSolidColor()17477 public int getSolidColor() { 17478 return 0; 17479 } 17480 17481 /** 17482 * Build a human readable string representation of the specified view flags. 17483 * 17484 * @param flags the view flags to convert to a string 17485 * @return a String representing the supplied flags 17486 */ printFlags(int flags)17487 private static String printFlags(int flags) { 17488 String output = ""; 17489 int numFlags = 0; 17490 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 17491 output += "TAKES_FOCUS"; 17492 numFlags++; 17493 } 17494 17495 switch (flags & VISIBILITY_MASK) { 17496 case INVISIBLE: 17497 if (numFlags > 0) { 17498 output += " "; 17499 } 17500 output += "INVISIBLE"; 17501 // USELESS HERE numFlags++; 17502 break; 17503 case GONE: 17504 if (numFlags > 0) { 17505 output += " "; 17506 } 17507 output += "GONE"; 17508 // USELESS HERE numFlags++; 17509 break; 17510 default: 17511 break; 17512 } 17513 return output; 17514 } 17515 17516 /** 17517 * Build a human readable string representation of the specified private 17518 * view flags. 17519 * 17520 * @param privateFlags the private view flags to convert to a string 17521 * @return a String representing the supplied flags 17522 */ printPrivateFlags(int privateFlags)17523 private static String printPrivateFlags(int privateFlags) { 17524 String output = ""; 17525 int numFlags = 0; 17526 17527 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 17528 output += "WANTS_FOCUS"; 17529 numFlags++; 17530 } 17531 17532 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 17533 if (numFlags > 0) { 17534 output += " "; 17535 } 17536 output += "FOCUSED"; 17537 numFlags++; 17538 } 17539 17540 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 17541 if (numFlags > 0) { 17542 output += " "; 17543 } 17544 output += "SELECTED"; 17545 numFlags++; 17546 } 17547 17548 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 17549 if (numFlags > 0) { 17550 output += " "; 17551 } 17552 output += "IS_ROOT_NAMESPACE"; 17553 numFlags++; 17554 } 17555 17556 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 17557 if (numFlags > 0) { 17558 output += " "; 17559 } 17560 output += "HAS_BOUNDS"; 17561 numFlags++; 17562 } 17563 17564 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 17565 if (numFlags > 0) { 17566 output += " "; 17567 } 17568 output += "DRAWN"; 17569 // USELESS HERE numFlags++; 17570 } 17571 return output; 17572 } 17573 17574 /** 17575 * <p>Indicates whether or not this view's layout will be requested during 17576 * the next hierarchy layout pass.</p> 17577 * 17578 * @return true if the layout will be forced during next layout pass 17579 */ isLayoutRequested()17580 public boolean isLayoutRequested() { 17581 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 17582 } 17583 17584 /** 17585 * Return true if o is a ViewGroup that is laying out using optical bounds. 17586 * @hide 17587 */ isLayoutModeOptical(Object o)17588 public static boolean isLayoutModeOptical(Object o) { 17589 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 17590 } 17591 setOpticalFrame(int left, int top, int right, int bottom)17592 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 17593 Insets parentInsets = mParent instanceof View ? 17594 ((View) mParent).getOpticalInsets() : Insets.NONE; 17595 Insets childInsets = getOpticalInsets(); 17596 return setFrame( 17597 left + parentInsets.left - childInsets.left, 17598 top + parentInsets.top - childInsets.top, 17599 right + parentInsets.left + childInsets.right, 17600 bottom + parentInsets.top + childInsets.bottom); 17601 } 17602 17603 /** 17604 * Assign a size and position to a view and all of its 17605 * descendants 17606 * 17607 * <p>This is the second phase of the layout mechanism. 17608 * (The first is measuring). In this phase, each parent calls 17609 * layout on all of its children to position them. 17610 * This is typically done using the child measurements 17611 * that were stored in the measure pass().</p> 17612 * 17613 * <p>Derived classes should not override this method. 17614 * Derived classes with children should override 17615 * onLayout. In that method, they should 17616 * call layout on each of their children.</p> 17617 * 17618 * @param l Left position, relative to parent 17619 * @param t Top position, relative to parent 17620 * @param r Right position, relative to parent 17621 * @param b Bottom position, relative to parent 17622 */ 17623 @SuppressWarnings({"unchecked"}) layout(int l, int t, int r, int b)17624 public void layout(int l, int t, int r, int b) { 17625 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 17626 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 17627 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 17628 } 17629 17630 int oldL = mLeft; 17631 int oldT = mTop; 17632 int oldB = mBottom; 17633 int oldR = mRight; 17634 17635 boolean changed = isLayoutModeOptical(mParent) ? 17636 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 17637 17638 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 17639 onLayout(changed, l, t, r, b); 17640 17641 if (shouldDrawRoundScrollbar()) { 17642 if(mRoundScrollbarRenderer == null) { 17643 mRoundScrollbarRenderer = new RoundScrollbarRenderer(this); 17644 } 17645 } else { 17646 mRoundScrollbarRenderer = null; 17647 } 17648 17649 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 17650 17651 ListenerInfo li = mListenerInfo; 17652 if (li != null && li.mOnLayoutChangeListeners != null) { 17653 ArrayList<OnLayoutChangeListener> listenersCopy = 17654 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 17655 int numListeners = listenersCopy.size(); 17656 for (int i = 0; i < numListeners; ++i) { 17657 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 17658 } 17659 } 17660 } 17661 17662 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 17663 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 17664 } 17665 17666 /** 17667 * Called from layout when this view should 17668 * assign a size and position to each of its children. 17669 * 17670 * Derived classes with children should override 17671 * this method and call layout on each of 17672 * their children. 17673 * @param changed This is a new size or position for this view 17674 * @param left Left position, relative to parent 17675 * @param top Top position, relative to parent 17676 * @param right Right position, relative to parent 17677 * @param bottom Bottom position, relative to parent 17678 */ onLayout(boolean changed, int left, int top, int right, int bottom)17679 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 17680 } 17681 17682 /** 17683 * Assign a size and position to this view. 17684 * 17685 * This is called from layout. 17686 * 17687 * @param left Left position, relative to parent 17688 * @param top Top position, relative to parent 17689 * @param right Right position, relative to parent 17690 * @param bottom Bottom position, relative to parent 17691 * @return true if the new size and position are different than the 17692 * previous ones 17693 * {@hide} 17694 */ setFrame(int left, int top, int right, int bottom)17695 protected boolean setFrame(int left, int top, int right, int bottom) { 17696 boolean changed = false; 17697 17698 if (DBG) { 17699 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 17700 + right + "," + bottom + ")"); 17701 } 17702 17703 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 17704 changed = true; 17705 17706 // Remember our drawn bit 17707 int drawn = mPrivateFlags & PFLAG_DRAWN; 17708 17709 int oldWidth = mRight - mLeft; 17710 int oldHeight = mBottom - mTop; 17711 int newWidth = right - left; 17712 int newHeight = bottom - top; 17713 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 17714 17715 // Invalidate our old position 17716 invalidate(sizeChanged); 17717 17718 mLeft = left; 17719 mTop = top; 17720 mRight = right; 17721 mBottom = bottom; 17722 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 17723 17724 mPrivateFlags |= PFLAG_HAS_BOUNDS; 17725 17726 17727 if (sizeChanged) { 17728 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 17729 } 17730 17731 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { 17732 // If we are visible, force the DRAWN bit to on so that 17733 // this invalidate will go through (at least to our parent). 17734 // This is because someone may have invalidated this view 17735 // before this call to setFrame came in, thereby clearing 17736 // the DRAWN bit. 17737 mPrivateFlags |= PFLAG_DRAWN; 17738 invalidate(sizeChanged); 17739 // parent display list may need to be recreated based on a change in the bounds 17740 // of any child 17741 invalidateParentCaches(); 17742 } 17743 17744 // Reset drawn bit to original value (invalidate turns it off) 17745 mPrivateFlags |= drawn; 17746 17747 mBackgroundSizeChanged = true; 17748 if (mForegroundInfo != null) { 17749 mForegroundInfo.mBoundsChanged = true; 17750 } 17751 17752 notifySubtreeAccessibilityStateChangedIfNeeded(); 17753 } 17754 return changed; 17755 } 17756 17757 /** 17758 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}. 17759 * @hide 17760 */ setLeftTopRightBottom(int left, int top, int right, int bottom)17761 public void setLeftTopRightBottom(int left, int top, int right, int bottom) { 17762 setFrame(left, top, right, bottom); 17763 } 17764 sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight)17765 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 17766 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 17767 if (mOverlay != null) { 17768 mOverlay.getOverlayView().setRight(newWidth); 17769 mOverlay.getOverlayView().setBottom(newHeight); 17770 } 17771 rebuildOutline(); 17772 } 17773 17774 /** 17775 * Finalize inflating a view from XML. This is called as the last phase 17776 * of inflation, after all child views have been added. 17777 * 17778 * <p>Even if the subclass overrides onFinishInflate, they should always be 17779 * sure to call the super method, so that we get called. 17780 */ 17781 @CallSuper onFinishInflate()17782 protected void onFinishInflate() { 17783 } 17784 17785 /** 17786 * Returns the resources associated with this view. 17787 * 17788 * @return Resources object. 17789 */ getResources()17790 public Resources getResources() { 17791 return mResources; 17792 } 17793 17794 /** 17795 * Invalidates the specified Drawable. 17796 * 17797 * @param drawable the drawable to invalidate 17798 */ 17799 @Override invalidateDrawable(@onNull Drawable drawable)17800 public void invalidateDrawable(@NonNull Drawable drawable) { 17801 if (verifyDrawable(drawable)) { 17802 final Rect dirty = drawable.getDirtyBounds(); 17803 final int scrollX = mScrollX; 17804 final int scrollY = mScrollY; 17805 17806 invalidate(dirty.left + scrollX, dirty.top + scrollY, 17807 dirty.right + scrollX, dirty.bottom + scrollY); 17808 rebuildOutline(); 17809 } 17810 } 17811 17812 /** 17813 * Schedules an action on a drawable to occur at a specified time. 17814 * 17815 * @param who the recipient of the action 17816 * @param what the action to run on the drawable 17817 * @param when the time at which the action must occur. Uses the 17818 * {@link SystemClock#uptimeMillis} timebase. 17819 */ 17820 @Override scheduleDrawable(@onNull Drawable who, @NonNull Runnable what, long when)17821 public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { 17822 if (verifyDrawable(who) && what != null) { 17823 final long delay = when - SystemClock.uptimeMillis(); 17824 if (mAttachInfo != null) { 17825 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 17826 Choreographer.CALLBACK_ANIMATION, what, who, 17827 Choreographer.subtractFrameDelay(delay)); 17828 } else { 17829 // Postpone the runnable until we know 17830 // on which thread it needs to run. 17831 getRunQueue().postDelayed(what, delay); 17832 } 17833 } 17834 } 17835 17836 /** 17837 * Cancels a scheduled action on a drawable. 17838 * 17839 * @param who the recipient of the action 17840 * @param what the action to cancel 17841 */ 17842 @Override unscheduleDrawable(@onNull Drawable who, @NonNull Runnable what)17843 public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { 17844 if (verifyDrawable(who) && what != null) { 17845 if (mAttachInfo != null) { 17846 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17847 Choreographer.CALLBACK_ANIMATION, what, who); 17848 } 17849 getRunQueue().removeCallbacks(what); 17850 } 17851 } 17852 17853 /** 17854 * Unschedule any events associated with the given Drawable. This can be 17855 * used when selecting a new Drawable into a view, so that the previous 17856 * one is completely unscheduled. 17857 * 17858 * @param who The Drawable to unschedule. 17859 * 17860 * @see #drawableStateChanged 17861 */ unscheduleDrawable(Drawable who)17862 public void unscheduleDrawable(Drawable who) { 17863 if (mAttachInfo != null && who != null) { 17864 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17865 Choreographer.CALLBACK_ANIMATION, null, who); 17866 } 17867 } 17868 17869 /** 17870 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 17871 * that the View directionality can and will be resolved before its Drawables. 17872 * 17873 * Will call {@link View#onResolveDrawables} when resolution is done. 17874 * 17875 * @hide 17876 */ resolveDrawables()17877 protected void resolveDrawables() { 17878 // Drawables resolution may need to happen before resolving the layout direction (which is 17879 // done only during the measure() call). 17880 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 17881 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 17882 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 17883 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 17884 // direction to be resolved as its resolved value will be the same as its raw value. 17885 if (!isLayoutDirectionResolved() && 17886 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 17887 return; 17888 } 17889 17890 final int layoutDirection = isLayoutDirectionResolved() ? 17891 getLayoutDirection() : getRawLayoutDirection(); 17892 17893 if (mBackground != null) { 17894 mBackground.setLayoutDirection(layoutDirection); 17895 } 17896 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17897 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); 17898 } 17899 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 17900 onResolveDrawables(layoutDirection); 17901 } 17902 areDrawablesResolved()17903 boolean areDrawablesResolved() { 17904 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 17905 } 17906 17907 /** 17908 * Called when layout direction has been resolved. 17909 * 17910 * The default implementation does nothing. 17911 * 17912 * @param layoutDirection The resolved layout direction. 17913 * 17914 * @see #LAYOUT_DIRECTION_LTR 17915 * @see #LAYOUT_DIRECTION_RTL 17916 * 17917 * @hide 17918 */ onResolveDrawables(@esolvedLayoutDir int layoutDirection)17919 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 17920 } 17921 17922 /** 17923 * @hide 17924 */ resetResolvedDrawables()17925 protected void resetResolvedDrawables() { 17926 resetResolvedDrawablesInternal(); 17927 } 17928 resetResolvedDrawablesInternal()17929 void resetResolvedDrawablesInternal() { 17930 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 17931 } 17932 17933 /** 17934 * If your view subclass is displaying its own Drawable objects, it should 17935 * override this function and return true for any Drawable it is 17936 * displaying. This allows animations for those drawables to be 17937 * scheduled. 17938 * 17939 * <p>Be sure to call through to the super class when overriding this 17940 * function. 17941 * 17942 * @param who The Drawable to verify. Return true if it is one you are 17943 * displaying, else return the result of calling through to the 17944 * super class. 17945 * 17946 * @return boolean If true than the Drawable is being displayed in the 17947 * view; else false and it is not allowed to animate. 17948 * 17949 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 17950 * @see #drawableStateChanged() 17951 */ 17952 @CallSuper verifyDrawable(@onNull Drawable who)17953 protected boolean verifyDrawable(@NonNull Drawable who) { 17954 // Avoid verifying the scroll bar drawable so that we don't end up in 17955 // an invalidation loop. This effectively prevents the scroll bar 17956 // drawable from triggering invalidations and scheduling runnables. 17957 return who == mBackground || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); 17958 } 17959 17960 /** 17961 * This function is called whenever the state of the view changes in such 17962 * a way that it impacts the state of drawables being shown. 17963 * <p> 17964 * If the View has a StateListAnimator, it will also be called to run necessary state 17965 * change animations. 17966 * <p> 17967 * Be sure to call through to the superclass when overriding this function. 17968 * 17969 * @see Drawable#setState(int[]) 17970 */ 17971 @CallSuper drawableStateChanged()17972 protected void drawableStateChanged() { 17973 final int[] state = getDrawableState(); 17974 boolean changed = false; 17975 17976 final Drawable bg = mBackground; 17977 if (bg != null && bg.isStateful()) { 17978 changed |= bg.setState(state); 17979 } 17980 17981 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 17982 if (fg != null && fg.isStateful()) { 17983 changed |= fg.setState(state); 17984 } 17985 17986 if (mScrollCache != null) { 17987 final Drawable scrollBar = mScrollCache.scrollBar; 17988 if (scrollBar != null && scrollBar.isStateful()) { 17989 changed |= scrollBar.setState(state) 17990 && mScrollCache.state != ScrollabilityCache.OFF; 17991 } 17992 } 17993 17994 if (mStateListAnimator != null) { 17995 mStateListAnimator.setState(state); 17996 } 17997 17998 if (changed) { 17999 invalidate(); 18000 } 18001 } 18002 18003 /** 18004 * This function is called whenever the view hotspot changes and needs to 18005 * be propagated to drawables or child views managed by the view. 18006 * <p> 18007 * Dispatching to child views is handled by 18008 * {@link #dispatchDrawableHotspotChanged(float, float)}. 18009 * <p> 18010 * Be sure to call through to the superclass when overriding this function. 18011 * 18012 * @param x hotspot x coordinate 18013 * @param y hotspot y coordinate 18014 */ 18015 @CallSuper drawableHotspotChanged(float x, float y)18016 public void drawableHotspotChanged(float x, float y) { 18017 if (mBackground != null) { 18018 mBackground.setHotspot(x, y); 18019 } 18020 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 18021 mForegroundInfo.mDrawable.setHotspot(x, y); 18022 } 18023 18024 dispatchDrawableHotspotChanged(x, y); 18025 } 18026 18027 /** 18028 * Dispatches drawableHotspotChanged to all of this View's children. 18029 * 18030 * @param x hotspot x coordinate 18031 * @param y hotspot y coordinate 18032 * @see #drawableHotspotChanged(float, float) 18033 */ dispatchDrawableHotspotChanged(float x, float y)18034 public void dispatchDrawableHotspotChanged(float x, float y) { 18035 } 18036 18037 /** 18038 * Call this to force a view to update its drawable state. This will cause 18039 * drawableStateChanged to be called on this view. Views that are interested 18040 * in the new state should call getDrawableState. 18041 * 18042 * @see #drawableStateChanged 18043 * @see #getDrawableState 18044 */ refreshDrawableState()18045 public void refreshDrawableState() { 18046 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 18047 drawableStateChanged(); 18048 18049 ViewParent parent = mParent; 18050 if (parent != null) { 18051 parent.childDrawableStateChanged(this); 18052 } 18053 } 18054 18055 /** 18056 * Return an array of resource IDs of the drawable states representing the 18057 * current state of the view. 18058 * 18059 * @return The current drawable state 18060 * 18061 * @see Drawable#setState(int[]) 18062 * @see #drawableStateChanged() 18063 * @see #onCreateDrawableState(int) 18064 */ getDrawableState()18065 public final int[] getDrawableState() { 18066 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 18067 return mDrawableState; 18068 } else { 18069 mDrawableState = onCreateDrawableState(0); 18070 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 18071 return mDrawableState; 18072 } 18073 } 18074 18075 /** 18076 * Generate the new {@link android.graphics.drawable.Drawable} state for 18077 * this view. This is called by the view 18078 * system when the cached Drawable state is determined to be invalid. To 18079 * retrieve the current state, you should use {@link #getDrawableState}. 18080 * 18081 * @param extraSpace if non-zero, this is the number of extra entries you 18082 * would like in the returned array in which you can place your own 18083 * states. 18084 * 18085 * @return Returns an array holding the current {@link Drawable} state of 18086 * the view. 18087 * 18088 * @see #mergeDrawableStates(int[], int[]) 18089 */ onCreateDrawableState(int extraSpace)18090 protected int[] onCreateDrawableState(int extraSpace) { 18091 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 18092 mParent instanceof View) { 18093 return ((View) mParent).onCreateDrawableState(extraSpace); 18094 } 18095 18096 int[] drawableState; 18097 18098 int privateFlags = mPrivateFlags; 18099 18100 int viewStateIndex = 0; 18101 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED; 18102 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED; 18103 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED; 18104 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED; 18105 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED; 18106 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED; 18107 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 18108 ThreadedRenderer.isAvailable()) { 18109 // This is set if HW acceleration is requested, even if the current 18110 // process doesn't allow it. This is just to allow app preview 18111 // windows to better match their app. 18112 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED; 18113 } 18114 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED; 18115 18116 final int privateFlags2 = mPrivateFlags2; 18117 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) { 18118 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT; 18119 } 18120 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) { 18121 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED; 18122 } 18123 18124 drawableState = StateSet.get(viewStateIndex); 18125 18126 //noinspection ConstantIfStatement 18127 if (false) { 18128 Log.i("View", "drawableStateIndex=" + viewStateIndex); 18129 Log.i("View", toString() 18130 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 18131 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 18132 + " fo=" + hasFocus() 18133 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 18134 + " wf=" + hasWindowFocus() 18135 + ": " + Arrays.toString(drawableState)); 18136 } 18137 18138 if (extraSpace == 0) { 18139 return drawableState; 18140 } 18141 18142 final int[] fullState; 18143 if (drawableState != null) { 18144 fullState = new int[drawableState.length + extraSpace]; 18145 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 18146 } else { 18147 fullState = new int[extraSpace]; 18148 } 18149 18150 return fullState; 18151 } 18152 18153 /** 18154 * Merge your own state values in <var>additionalState</var> into the base 18155 * state values <var>baseState</var> that were returned by 18156 * {@link #onCreateDrawableState(int)}. 18157 * 18158 * @param baseState The base state values returned by 18159 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 18160 * own additional state values. 18161 * 18162 * @param additionalState The additional state values you would like 18163 * added to <var>baseState</var>; this array is not modified. 18164 * 18165 * @return As a convenience, the <var>baseState</var> array you originally 18166 * passed into the function is returned. 18167 * 18168 * @see #onCreateDrawableState(int) 18169 */ mergeDrawableStates(int[] baseState, int[] additionalState)18170 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 18171 final int N = baseState.length; 18172 int i = N - 1; 18173 while (i >= 0 && baseState[i] == 0) { 18174 i--; 18175 } 18176 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 18177 return baseState; 18178 } 18179 18180 /** 18181 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 18182 * on all Drawable objects associated with this view. 18183 * <p> 18184 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator 18185 * attached to this view. 18186 */ 18187 @CallSuper jumpDrawablesToCurrentState()18188 public void jumpDrawablesToCurrentState() { 18189 if (mBackground != null) { 18190 mBackground.jumpToCurrentState(); 18191 } 18192 if (mStateListAnimator != null) { 18193 mStateListAnimator.jumpToCurrentState(); 18194 } 18195 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 18196 mForegroundInfo.mDrawable.jumpToCurrentState(); 18197 } 18198 } 18199 18200 /** 18201 * Sets the background color for this view. 18202 * @param color the color of the background 18203 */ 18204 @RemotableViewMethod setBackgroundColor(@olorInt int color)18205 public void setBackgroundColor(@ColorInt int color) { 18206 if (mBackground instanceof ColorDrawable) { 18207 ((ColorDrawable) mBackground.mutate()).setColor(color); 18208 computeOpaqueFlags(); 18209 mBackgroundResource = 0; 18210 } else { 18211 setBackground(new ColorDrawable(color)); 18212 } 18213 } 18214 18215 /** 18216 * Set the background to a given resource. The resource should refer to 18217 * a Drawable object or 0 to remove the background. 18218 * @param resid The identifier of the resource. 18219 * 18220 * @attr ref android.R.styleable#View_background 18221 */ 18222 @RemotableViewMethod setBackgroundResource(@rawableRes int resid)18223 public void setBackgroundResource(@DrawableRes int resid) { 18224 if (resid != 0 && resid == mBackgroundResource) { 18225 return; 18226 } 18227 18228 Drawable d = null; 18229 if (resid != 0) { 18230 d = mContext.getDrawable(resid); 18231 } 18232 setBackground(d); 18233 18234 mBackgroundResource = resid; 18235 } 18236 18237 /** 18238 * Set the background to a given Drawable, or remove the background. If the 18239 * background has padding, this View's padding is set to the background's 18240 * padding. However, when a background is removed, this View's padding isn't 18241 * touched. If setting the padding is desired, please use 18242 * {@link #setPadding(int, int, int, int)}. 18243 * 18244 * @param background The Drawable to use as the background, or null to remove the 18245 * background 18246 */ setBackground(Drawable background)18247 public void setBackground(Drawable background) { 18248 //noinspection deprecation 18249 setBackgroundDrawable(background); 18250 } 18251 18252 /** 18253 * @deprecated use {@link #setBackground(Drawable)} instead 18254 */ 18255 @Deprecated setBackgroundDrawable(Drawable background)18256 public void setBackgroundDrawable(Drawable background) { 18257 computeOpaqueFlags(); 18258 18259 if (background == mBackground) { 18260 return; 18261 } 18262 18263 boolean requestLayout = false; 18264 18265 mBackgroundResource = 0; 18266 18267 /* 18268 * Regardless of whether we're setting a new background or not, we want 18269 * to clear the previous drawable. setVisible first while we still have the callback set. 18270 */ 18271 if (mBackground != null) { 18272 if (isAttachedToWindow()) { 18273 mBackground.setVisible(false, false); 18274 } 18275 mBackground.setCallback(null); 18276 unscheduleDrawable(mBackground); 18277 } 18278 18279 if (background != null) { 18280 Rect padding = sThreadLocal.get(); 18281 if (padding == null) { 18282 padding = new Rect(); 18283 sThreadLocal.set(padding); 18284 } 18285 resetResolvedDrawablesInternal(); 18286 background.setLayoutDirection(getLayoutDirection()); 18287 if (background.getPadding(padding)) { 18288 resetResolvedPaddingInternal(); 18289 switch (background.getLayoutDirection()) { 18290 case LAYOUT_DIRECTION_RTL: 18291 mUserPaddingLeftInitial = padding.right; 18292 mUserPaddingRightInitial = padding.left; 18293 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 18294 break; 18295 case LAYOUT_DIRECTION_LTR: 18296 default: 18297 mUserPaddingLeftInitial = padding.left; 18298 mUserPaddingRightInitial = padding.right; 18299 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 18300 } 18301 mLeftPaddingDefined = false; 18302 mRightPaddingDefined = false; 18303 } 18304 18305 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 18306 // if it has a different minimum size, we should layout again 18307 if (mBackground == null 18308 || mBackground.getMinimumHeight() != background.getMinimumHeight() 18309 || mBackground.getMinimumWidth() != background.getMinimumWidth()) { 18310 requestLayout = true; 18311 } 18312 18313 // Set mBackground before we set this as the callback and start making other 18314 // background drawable state change calls. In particular, the setVisible call below 18315 // can result in drawables attempting to start animations or otherwise invalidate, 18316 // which requires the view set as the callback (us) to recognize the drawable as 18317 // belonging to it as per verifyDrawable. 18318 mBackground = background; 18319 if (background.isStateful()) { 18320 background.setState(getDrawableState()); 18321 } 18322 if (isAttachedToWindow()) { 18323 background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 18324 } 18325 18326 applyBackgroundTint(); 18327 18328 // Set callback last, since the view may still be initializing. 18329 background.setCallback(this); 18330 18331 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 18332 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 18333 requestLayout = true; 18334 } 18335 } else { 18336 /* Remove the background */ 18337 mBackground = null; 18338 if ((mViewFlags & WILL_NOT_DRAW) != 0 18339 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { 18340 mPrivateFlags |= PFLAG_SKIP_DRAW; 18341 } 18342 18343 /* 18344 * When the background is set, we try to apply its padding to this 18345 * View. When the background is removed, we don't touch this View's 18346 * padding. This is noted in the Javadocs. Hence, we don't need to 18347 * requestLayout(), the invalidate() below is sufficient. 18348 */ 18349 18350 // The old background's minimum size could have affected this 18351 // View's layout, so let's requestLayout 18352 requestLayout = true; 18353 } 18354 18355 computeOpaqueFlags(); 18356 18357 if (requestLayout) { 18358 requestLayout(); 18359 } 18360 18361 mBackgroundSizeChanged = true; 18362 invalidate(true); 18363 invalidateOutline(); 18364 } 18365 18366 /** 18367 * Gets the background drawable 18368 * 18369 * @return The drawable used as the background for this view, if any. 18370 * 18371 * @see #setBackground(Drawable) 18372 * 18373 * @attr ref android.R.styleable#View_background 18374 */ getBackground()18375 public Drawable getBackground() { 18376 return mBackground; 18377 } 18378 18379 /** 18380 * Applies a tint to the background drawable. Does not modify the current tint 18381 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 18382 * <p> 18383 * Subsequent calls to {@link #setBackground(Drawable)} will automatically 18384 * mutate the drawable and apply the specified tint and tint mode using 18385 * {@link Drawable#setTintList(ColorStateList)}. 18386 * 18387 * @param tint the tint to apply, may be {@code null} to clear tint 18388 * 18389 * @attr ref android.R.styleable#View_backgroundTint 18390 * @see #getBackgroundTintList() 18391 * @see Drawable#setTintList(ColorStateList) 18392 */ setBackgroundTintList(@ullable ColorStateList tint)18393 public void setBackgroundTintList(@Nullable ColorStateList tint) { 18394 if (mBackgroundTint == null) { 18395 mBackgroundTint = new TintInfo(); 18396 } 18397 mBackgroundTint.mTintList = tint; 18398 mBackgroundTint.mHasTintList = true; 18399 18400 applyBackgroundTint(); 18401 } 18402 18403 /** 18404 * Return the tint applied to the background drawable, if specified. 18405 * 18406 * @return the tint applied to the background drawable 18407 * @attr ref android.R.styleable#View_backgroundTint 18408 * @see #setBackgroundTintList(ColorStateList) 18409 */ 18410 @Nullable getBackgroundTintList()18411 public ColorStateList getBackgroundTintList() { 18412 return mBackgroundTint != null ? mBackgroundTint.mTintList : null; 18413 } 18414 18415 /** 18416 * Specifies the blending mode used to apply the tint specified by 18417 * {@link #setBackgroundTintList(ColorStateList)}} to the background 18418 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 18419 * 18420 * @param tintMode the blending mode used to apply the tint, may be 18421 * {@code null} to clear tint 18422 * @attr ref android.R.styleable#View_backgroundTintMode 18423 * @see #getBackgroundTintMode() 18424 * @see Drawable#setTintMode(PorterDuff.Mode) 18425 */ setBackgroundTintMode(@ullable PorterDuff.Mode tintMode)18426 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { 18427 if (mBackgroundTint == null) { 18428 mBackgroundTint = new TintInfo(); 18429 } 18430 mBackgroundTint.mTintMode = tintMode; 18431 mBackgroundTint.mHasTintMode = true; 18432 18433 applyBackgroundTint(); 18434 } 18435 18436 /** 18437 * Return the blending mode used to apply the tint to the background 18438 * drawable, if specified. 18439 * 18440 * @return the blending mode used to apply the tint to the background 18441 * drawable 18442 * @attr ref android.R.styleable#View_backgroundTintMode 18443 * @see #setBackgroundTintMode(PorterDuff.Mode) 18444 */ 18445 @Nullable getBackgroundTintMode()18446 public PorterDuff.Mode getBackgroundTintMode() { 18447 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; 18448 } 18449 applyBackgroundTint()18450 private void applyBackgroundTint() { 18451 if (mBackground != null && mBackgroundTint != null) { 18452 final TintInfo tintInfo = mBackgroundTint; 18453 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 18454 mBackground = mBackground.mutate(); 18455 18456 if (tintInfo.mHasTintList) { 18457 mBackground.setTintList(tintInfo.mTintList); 18458 } 18459 18460 if (tintInfo.mHasTintMode) { 18461 mBackground.setTintMode(tintInfo.mTintMode); 18462 } 18463 18464 // The drawable (or one of its children) may not have been 18465 // stateful before applying the tint, so let's try again. 18466 if (mBackground.isStateful()) { 18467 mBackground.setState(getDrawableState()); 18468 } 18469 } 18470 } 18471 } 18472 18473 /** 18474 * Returns the drawable used as the foreground of this View. The 18475 * foreground drawable, if non-null, is always drawn on top of the view's content. 18476 * 18477 * @return a Drawable or null if no foreground was set 18478 * 18479 * @see #onDrawForeground(Canvas) 18480 */ getForeground()18481 public Drawable getForeground() { 18482 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 18483 } 18484 18485 /** 18486 * Supply a Drawable that is to be rendered on top of all of the content in the view. 18487 * 18488 * @param foreground the Drawable to be drawn on top of the children 18489 * 18490 * @attr ref android.R.styleable#View_foreground 18491 */ setForeground(Drawable foreground)18492 public void setForeground(Drawable foreground) { 18493 if (mForegroundInfo == null) { 18494 if (foreground == null) { 18495 // Nothing to do. 18496 return; 18497 } 18498 mForegroundInfo = new ForegroundInfo(); 18499 } 18500 18501 if (foreground == mForegroundInfo.mDrawable) { 18502 // Nothing to do 18503 return; 18504 } 18505 18506 if (mForegroundInfo.mDrawable != null) { 18507 if (isAttachedToWindow()) { 18508 mForegroundInfo.mDrawable.setVisible(false, false); 18509 } 18510 mForegroundInfo.mDrawable.setCallback(null); 18511 unscheduleDrawable(mForegroundInfo.mDrawable); 18512 } 18513 18514 mForegroundInfo.mDrawable = foreground; 18515 mForegroundInfo.mBoundsChanged = true; 18516 if (foreground != null) { 18517 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 18518 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 18519 } 18520 foreground.setLayoutDirection(getLayoutDirection()); 18521 if (foreground.isStateful()) { 18522 foreground.setState(getDrawableState()); 18523 } 18524 applyForegroundTint(); 18525 if (isAttachedToWindow()) { 18526 foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); 18527 } 18528 // Set callback last, since the view may still be initializing. 18529 foreground.setCallback(this); 18530 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) { 18531 mPrivateFlags |= PFLAG_SKIP_DRAW; 18532 } 18533 requestLayout(); 18534 invalidate(); 18535 } 18536 18537 /** 18538 * Magic bit used to support features of framework-internal window decor implementation details. 18539 * This used to live exclusively in FrameLayout. 18540 * 18541 * @return true if the foreground should draw inside the padding region or false 18542 * if it should draw inset by the view's padding 18543 * @hide internal use only; only used by FrameLayout and internal screen layouts. 18544 */ isForegroundInsidePadding()18545 public boolean isForegroundInsidePadding() { 18546 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true; 18547 } 18548 18549 /** 18550 * Describes how the foreground is positioned. 18551 * 18552 * @return foreground gravity. 18553 * 18554 * @see #setForegroundGravity(int) 18555 * 18556 * @attr ref android.R.styleable#View_foregroundGravity 18557 */ getForegroundGravity()18558 public int getForegroundGravity() { 18559 return mForegroundInfo != null ? mForegroundInfo.mGravity 18560 : Gravity.START | Gravity.TOP; 18561 } 18562 18563 /** 18564 * Describes how the foreground is positioned. Defaults to START and TOP. 18565 * 18566 * @param gravity see {@link android.view.Gravity} 18567 * 18568 * @see #getForegroundGravity() 18569 * 18570 * @attr ref android.R.styleable#View_foregroundGravity 18571 */ setForegroundGravity(int gravity)18572 public void setForegroundGravity(int gravity) { 18573 if (mForegroundInfo == null) { 18574 mForegroundInfo = new ForegroundInfo(); 18575 } 18576 18577 if (mForegroundInfo.mGravity != gravity) { 18578 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { 18579 gravity |= Gravity.START; 18580 } 18581 18582 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { 18583 gravity |= Gravity.TOP; 18584 } 18585 18586 mForegroundInfo.mGravity = gravity; 18587 requestLayout(); 18588 } 18589 } 18590 18591 /** 18592 * Applies a tint to the foreground drawable. Does not modify the current tint 18593 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 18594 * <p> 18595 * Subsequent calls to {@link #setForeground(Drawable)} will automatically 18596 * mutate the drawable and apply the specified tint and tint mode using 18597 * {@link Drawable#setTintList(ColorStateList)}. 18598 * 18599 * @param tint the tint to apply, may be {@code null} to clear tint 18600 * 18601 * @attr ref android.R.styleable#View_foregroundTint 18602 * @see #getForegroundTintList() 18603 * @see Drawable#setTintList(ColorStateList) 18604 */ setForegroundTintList(@ullable ColorStateList tint)18605 public void setForegroundTintList(@Nullable ColorStateList tint) { 18606 if (mForegroundInfo == null) { 18607 mForegroundInfo = new ForegroundInfo(); 18608 } 18609 if (mForegroundInfo.mTintInfo == null) { 18610 mForegroundInfo.mTintInfo = new TintInfo(); 18611 } 18612 mForegroundInfo.mTintInfo.mTintList = tint; 18613 mForegroundInfo.mTintInfo.mHasTintList = true; 18614 18615 applyForegroundTint(); 18616 } 18617 18618 /** 18619 * Return the tint applied to the foreground drawable, if specified. 18620 * 18621 * @return the tint applied to the foreground drawable 18622 * @attr ref android.R.styleable#View_foregroundTint 18623 * @see #setForegroundTintList(ColorStateList) 18624 */ 18625 @Nullable getForegroundTintList()18626 public ColorStateList getForegroundTintList() { 18627 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 18628 ? mForegroundInfo.mTintInfo.mTintList : null; 18629 } 18630 18631 /** 18632 * Specifies the blending mode used to apply the tint specified by 18633 * {@link #setForegroundTintList(ColorStateList)}} to the background 18634 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 18635 * 18636 * @param tintMode the blending mode used to apply the tint, may be 18637 * {@code null} to clear tint 18638 * @attr ref android.R.styleable#View_foregroundTintMode 18639 * @see #getForegroundTintMode() 18640 * @see Drawable#setTintMode(PorterDuff.Mode) 18641 */ setForegroundTintMode(@ullable PorterDuff.Mode tintMode)18642 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { 18643 if (mForegroundInfo == null) { 18644 mForegroundInfo = new ForegroundInfo(); 18645 } 18646 if (mForegroundInfo.mTintInfo == null) { 18647 mForegroundInfo.mTintInfo = new TintInfo(); 18648 } 18649 mForegroundInfo.mTintInfo.mTintMode = tintMode; 18650 mForegroundInfo.mTintInfo.mHasTintMode = true; 18651 18652 applyForegroundTint(); 18653 } 18654 18655 /** 18656 * Return the blending mode used to apply the tint to the foreground 18657 * drawable, if specified. 18658 * 18659 * @return the blending mode used to apply the tint to the foreground 18660 * drawable 18661 * @attr ref android.R.styleable#View_foregroundTintMode 18662 * @see #setForegroundTintMode(PorterDuff.Mode) 18663 */ 18664 @Nullable getForegroundTintMode()18665 public PorterDuff.Mode getForegroundTintMode() { 18666 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 18667 ? mForegroundInfo.mTintInfo.mTintMode : null; 18668 } 18669 applyForegroundTint()18670 private void applyForegroundTint() { 18671 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 18672 && mForegroundInfo.mTintInfo != null) { 18673 final TintInfo tintInfo = mForegroundInfo.mTintInfo; 18674 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 18675 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); 18676 18677 if (tintInfo.mHasTintList) { 18678 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); 18679 } 18680 18681 if (tintInfo.mHasTintMode) { 18682 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); 18683 } 18684 18685 // The drawable (or one of its children) may not have been 18686 // stateful before applying the tint, so let's try again. 18687 if (mForegroundInfo.mDrawable.isStateful()) { 18688 mForegroundInfo.mDrawable.setState(getDrawableState()); 18689 } 18690 } 18691 } 18692 } 18693 18694 /** 18695 * Draw any foreground content for this view. 18696 * 18697 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground} 18698 * drawable or other view-specific decorations. The foreground is drawn on top of the 18699 * primary view content.</p> 18700 * 18701 * @param canvas canvas to draw into 18702 */ onDrawForeground(Canvas canvas)18703 public void onDrawForeground(Canvas canvas) { 18704 onDrawScrollIndicators(canvas); 18705 onDrawScrollBars(canvas); 18706 18707 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 18708 if (foreground != null) { 18709 if (mForegroundInfo.mBoundsChanged) { 18710 mForegroundInfo.mBoundsChanged = false; 18711 final Rect selfBounds = mForegroundInfo.mSelfBounds; 18712 final Rect overlayBounds = mForegroundInfo.mOverlayBounds; 18713 18714 if (mForegroundInfo.mInsidePadding) { 18715 selfBounds.set(0, 0, getWidth(), getHeight()); 18716 } else { 18717 selfBounds.set(getPaddingLeft(), getPaddingTop(), 18718 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); 18719 } 18720 18721 final int ld = getLayoutDirection(); 18722 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), 18723 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); 18724 foreground.setBounds(overlayBounds); 18725 } 18726 18727 foreground.draw(canvas); 18728 } 18729 } 18730 18731 /** 18732 * Sets the padding. The view may add on the space required to display 18733 * the scrollbars, depending on the style and visibility of the scrollbars. 18734 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 18735 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 18736 * from the values set in this call. 18737 * 18738 * @attr ref android.R.styleable#View_padding 18739 * @attr ref android.R.styleable#View_paddingBottom 18740 * @attr ref android.R.styleable#View_paddingLeft 18741 * @attr ref android.R.styleable#View_paddingRight 18742 * @attr ref android.R.styleable#View_paddingTop 18743 * @param left the left padding in pixels 18744 * @param top the top padding in pixels 18745 * @param right the right padding in pixels 18746 * @param bottom the bottom padding in pixels 18747 */ setPadding(int left, int top, int right, int bottom)18748 public void setPadding(int left, int top, int right, int bottom) { 18749 resetResolvedPaddingInternal(); 18750 18751 mUserPaddingStart = UNDEFINED_PADDING; 18752 mUserPaddingEnd = UNDEFINED_PADDING; 18753 18754 mUserPaddingLeftInitial = left; 18755 mUserPaddingRightInitial = right; 18756 18757 mLeftPaddingDefined = true; 18758 mRightPaddingDefined = true; 18759 18760 internalSetPadding(left, top, right, bottom); 18761 } 18762 18763 /** 18764 * @hide 18765 */ internalSetPadding(int left, int top, int right, int bottom)18766 protected void internalSetPadding(int left, int top, int right, int bottom) { 18767 mUserPaddingLeft = left; 18768 mUserPaddingRight = right; 18769 mUserPaddingBottom = bottom; 18770 18771 final int viewFlags = mViewFlags; 18772 boolean changed = false; 18773 18774 // Common case is there are no scroll bars. 18775 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 18776 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 18777 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 18778 ? 0 : getVerticalScrollbarWidth(); 18779 switch (mVerticalScrollbarPosition) { 18780 case SCROLLBAR_POSITION_DEFAULT: 18781 if (isLayoutRtl()) { 18782 left += offset; 18783 } else { 18784 right += offset; 18785 } 18786 break; 18787 case SCROLLBAR_POSITION_RIGHT: 18788 right += offset; 18789 break; 18790 case SCROLLBAR_POSITION_LEFT: 18791 left += offset; 18792 break; 18793 } 18794 } 18795 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 18796 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 18797 ? 0 : getHorizontalScrollbarHeight(); 18798 } 18799 } 18800 18801 if (mPaddingLeft != left) { 18802 changed = true; 18803 mPaddingLeft = left; 18804 } 18805 if (mPaddingTop != top) { 18806 changed = true; 18807 mPaddingTop = top; 18808 } 18809 if (mPaddingRight != right) { 18810 changed = true; 18811 mPaddingRight = right; 18812 } 18813 if (mPaddingBottom != bottom) { 18814 changed = true; 18815 mPaddingBottom = bottom; 18816 } 18817 18818 if (changed) { 18819 requestLayout(); 18820 invalidateOutline(); 18821 } 18822 } 18823 18824 /** 18825 * Sets the relative padding. The view may add on the space required to display 18826 * the scrollbars, depending on the style and visibility of the scrollbars. 18827 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 18828 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 18829 * from the values set in this call. 18830 * 18831 * @attr ref android.R.styleable#View_padding 18832 * @attr ref android.R.styleable#View_paddingBottom 18833 * @attr ref android.R.styleable#View_paddingStart 18834 * @attr ref android.R.styleable#View_paddingEnd 18835 * @attr ref android.R.styleable#View_paddingTop 18836 * @param start the start padding in pixels 18837 * @param top the top padding in pixels 18838 * @param end the end padding in pixels 18839 * @param bottom the bottom padding in pixels 18840 */ setPaddingRelative(int start, int top, int end, int bottom)18841 public void setPaddingRelative(int start, int top, int end, int bottom) { 18842 resetResolvedPaddingInternal(); 18843 18844 mUserPaddingStart = start; 18845 mUserPaddingEnd = end; 18846 mLeftPaddingDefined = true; 18847 mRightPaddingDefined = true; 18848 18849 switch(getLayoutDirection()) { 18850 case LAYOUT_DIRECTION_RTL: 18851 mUserPaddingLeftInitial = end; 18852 mUserPaddingRightInitial = start; 18853 internalSetPadding(end, top, start, bottom); 18854 break; 18855 case LAYOUT_DIRECTION_LTR: 18856 default: 18857 mUserPaddingLeftInitial = start; 18858 mUserPaddingRightInitial = end; 18859 internalSetPadding(start, top, end, bottom); 18860 } 18861 } 18862 18863 /** 18864 * Returns the top padding of this view. 18865 * 18866 * @return the top padding in pixels 18867 */ getPaddingTop()18868 public int getPaddingTop() { 18869 return mPaddingTop; 18870 } 18871 18872 /** 18873 * Returns the bottom padding of this view. If there are inset and enabled 18874 * scrollbars, this value may include the space required to display the 18875 * scrollbars as well. 18876 * 18877 * @return the bottom padding in pixels 18878 */ getPaddingBottom()18879 public int getPaddingBottom() { 18880 return mPaddingBottom; 18881 } 18882 18883 /** 18884 * Returns the left padding of this view. If there are inset and enabled 18885 * scrollbars, this value may include the space required to display the 18886 * scrollbars as well. 18887 * 18888 * @return the left padding in pixels 18889 */ getPaddingLeft()18890 public int getPaddingLeft() { 18891 if (!isPaddingResolved()) { 18892 resolvePadding(); 18893 } 18894 return mPaddingLeft; 18895 } 18896 18897 /** 18898 * Returns the start padding of this view depending on its resolved layout direction. 18899 * If there are inset and enabled scrollbars, this value may include the space 18900 * required to display the scrollbars as well. 18901 * 18902 * @return the start padding in pixels 18903 */ getPaddingStart()18904 public int getPaddingStart() { 18905 if (!isPaddingResolved()) { 18906 resolvePadding(); 18907 } 18908 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18909 mPaddingRight : mPaddingLeft; 18910 } 18911 18912 /** 18913 * Returns the right padding of this view. If there are inset and enabled 18914 * scrollbars, this value may include the space required to display the 18915 * scrollbars as well. 18916 * 18917 * @return the right padding in pixels 18918 */ getPaddingRight()18919 public int getPaddingRight() { 18920 if (!isPaddingResolved()) { 18921 resolvePadding(); 18922 } 18923 return mPaddingRight; 18924 } 18925 18926 /** 18927 * Returns the end padding of this view depending on its resolved layout direction. 18928 * If there are inset and enabled scrollbars, this value may include the space 18929 * required to display the scrollbars as well. 18930 * 18931 * @return the end padding in pixels 18932 */ getPaddingEnd()18933 public int getPaddingEnd() { 18934 if (!isPaddingResolved()) { 18935 resolvePadding(); 18936 } 18937 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18938 mPaddingLeft : mPaddingRight; 18939 } 18940 18941 /** 18942 * Return if the padding has been set through relative values 18943 * {@link #setPaddingRelative(int, int, int, int)} or through 18944 * @attr ref android.R.styleable#View_paddingStart or 18945 * @attr ref android.R.styleable#View_paddingEnd 18946 * 18947 * @return true if the padding is relative or false if it is not. 18948 */ isPaddingRelative()18949 public boolean isPaddingRelative() { 18950 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 18951 } 18952 computeOpticalInsets()18953 Insets computeOpticalInsets() { 18954 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 18955 } 18956 18957 /** 18958 * @hide 18959 */ resetPaddingToInitialValues()18960 public void resetPaddingToInitialValues() { 18961 if (isRtlCompatibilityMode()) { 18962 mPaddingLeft = mUserPaddingLeftInitial; 18963 mPaddingRight = mUserPaddingRightInitial; 18964 return; 18965 } 18966 if (isLayoutRtl()) { 18967 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 18968 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 18969 } else { 18970 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 18971 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 18972 } 18973 } 18974 18975 /** 18976 * @hide 18977 */ getOpticalInsets()18978 public Insets getOpticalInsets() { 18979 if (mLayoutInsets == null) { 18980 mLayoutInsets = computeOpticalInsets(); 18981 } 18982 return mLayoutInsets; 18983 } 18984 18985 /** 18986 * Set this view's optical insets. 18987 * 18988 * <p>This method should be treated similarly to setMeasuredDimension and not as a general 18989 * property. Views that compute their own optical insets should call it as part of measurement. 18990 * This method does not request layout. If you are setting optical insets outside of 18991 * measure/layout itself you will want to call requestLayout() yourself. 18992 * </p> 18993 * @hide 18994 */ setOpticalInsets(Insets insets)18995 public void setOpticalInsets(Insets insets) { 18996 mLayoutInsets = insets; 18997 } 18998 18999 /** 19000 * Changes the selection state of this view. A view can be selected or not. 19001 * Note that selection is not the same as focus. Views are typically 19002 * selected in the context of an AdapterView like ListView or GridView; 19003 * the selected view is the view that is highlighted. 19004 * 19005 * @param selected true if the view must be selected, false otherwise 19006 */ setSelected(boolean selected)19007 public void setSelected(boolean selected) { 19008 //noinspection DoubleNegation 19009 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 19010 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 19011 if (!selected) resetPressedState(); 19012 invalidate(true); 19013 refreshDrawableState(); 19014 dispatchSetSelected(selected); 19015 if (selected) { 19016 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 19017 } else { 19018 notifyViewAccessibilityStateChangedIfNeeded( 19019 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 19020 } 19021 } 19022 } 19023 19024 /** 19025 * Dispatch setSelected to all of this View's children. 19026 * 19027 * @see #setSelected(boolean) 19028 * 19029 * @param selected The new selected state 19030 */ dispatchSetSelected(boolean selected)19031 protected void dispatchSetSelected(boolean selected) { 19032 } 19033 19034 /** 19035 * Indicates the selection state of this view. 19036 * 19037 * @return true if the view is selected, false otherwise 19038 */ 19039 @ViewDebug.ExportedProperty isSelected()19040 public boolean isSelected() { 19041 return (mPrivateFlags & PFLAG_SELECTED) != 0; 19042 } 19043 19044 /** 19045 * Changes the activated state of this view. A view can be activated or not. 19046 * Note that activation is not the same as selection. Selection is 19047 * a transient property, representing the view (hierarchy) the user is 19048 * currently interacting with. Activation is a longer-term state that the 19049 * user can move views in and out of. For example, in a list view with 19050 * single or multiple selection enabled, the views in the current selection 19051 * set are activated. (Um, yeah, we are deeply sorry about the terminology 19052 * here.) The activated state is propagated down to children of the view it 19053 * is set on. 19054 * 19055 * @param activated true if the view must be activated, false otherwise 19056 */ setActivated(boolean activated)19057 public void setActivated(boolean activated) { 19058 //noinspection DoubleNegation 19059 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 19060 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 19061 invalidate(true); 19062 refreshDrawableState(); 19063 dispatchSetActivated(activated); 19064 } 19065 } 19066 19067 /** 19068 * Dispatch setActivated to all of this View's children. 19069 * 19070 * @see #setActivated(boolean) 19071 * 19072 * @param activated The new activated state 19073 */ dispatchSetActivated(boolean activated)19074 protected void dispatchSetActivated(boolean activated) { 19075 } 19076 19077 /** 19078 * Indicates the activation state of this view. 19079 * 19080 * @return true if the view is activated, false otherwise 19081 */ 19082 @ViewDebug.ExportedProperty isActivated()19083 public boolean isActivated() { 19084 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 19085 } 19086 19087 /** 19088 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 19089 * observer can be used to get notifications when global events, like 19090 * layout, happen. 19091 * 19092 * The returned ViewTreeObserver observer is not guaranteed to remain 19093 * valid for the lifetime of this View. If the caller of this method keeps 19094 * a long-lived reference to ViewTreeObserver, it should always check for 19095 * the return value of {@link ViewTreeObserver#isAlive()}. 19096 * 19097 * @return The ViewTreeObserver for this view's hierarchy. 19098 */ getViewTreeObserver()19099 public ViewTreeObserver getViewTreeObserver() { 19100 if (mAttachInfo != null) { 19101 return mAttachInfo.mTreeObserver; 19102 } 19103 if (mFloatingTreeObserver == null) { 19104 mFloatingTreeObserver = new ViewTreeObserver(); 19105 } 19106 return mFloatingTreeObserver; 19107 } 19108 19109 /** 19110 * <p>Finds the topmost view in the current view hierarchy.</p> 19111 * 19112 * @return the topmost view containing this view 19113 */ getRootView()19114 public View getRootView() { 19115 if (mAttachInfo != null) { 19116 final View v = mAttachInfo.mRootView; 19117 if (v != null) { 19118 return v; 19119 } 19120 } 19121 19122 View parent = this; 19123 19124 while (parent.mParent != null && parent.mParent instanceof View) { 19125 parent = (View) parent.mParent; 19126 } 19127 19128 return parent; 19129 } 19130 19131 /** 19132 * Transforms a motion event from view-local coordinates to on-screen 19133 * coordinates. 19134 * 19135 * @param ev the view-local motion event 19136 * @return false if the transformation could not be applied 19137 * @hide 19138 */ toGlobalMotionEvent(MotionEvent ev)19139 public boolean toGlobalMotionEvent(MotionEvent ev) { 19140 final AttachInfo info = mAttachInfo; 19141 if (info == null) { 19142 return false; 19143 } 19144 19145 final Matrix m = info.mTmpMatrix; 19146 m.set(Matrix.IDENTITY_MATRIX); 19147 transformMatrixToGlobal(m); 19148 ev.transform(m); 19149 return true; 19150 } 19151 19152 /** 19153 * Transforms a motion event from on-screen coordinates to view-local 19154 * coordinates. 19155 * 19156 * @param ev the on-screen motion event 19157 * @return false if the transformation could not be applied 19158 * @hide 19159 */ toLocalMotionEvent(MotionEvent ev)19160 public boolean toLocalMotionEvent(MotionEvent ev) { 19161 final AttachInfo info = mAttachInfo; 19162 if (info == null) { 19163 return false; 19164 } 19165 19166 final Matrix m = info.mTmpMatrix; 19167 m.set(Matrix.IDENTITY_MATRIX); 19168 transformMatrixToLocal(m); 19169 ev.transform(m); 19170 return true; 19171 } 19172 19173 /** 19174 * Modifies the input matrix such that it maps view-local coordinates to 19175 * on-screen coordinates. 19176 * 19177 * @param m input matrix to modify 19178 * @hide 19179 */ transformMatrixToGlobal(Matrix m)19180 public void transformMatrixToGlobal(Matrix m) { 19181 final ViewParent parent = mParent; 19182 if (parent instanceof View) { 19183 final View vp = (View) parent; 19184 vp.transformMatrixToGlobal(m); 19185 m.preTranslate(-vp.mScrollX, -vp.mScrollY); 19186 } else if (parent instanceof ViewRootImpl) { 19187 final ViewRootImpl vr = (ViewRootImpl) parent; 19188 vr.transformMatrixToGlobal(m); 19189 m.preTranslate(0, -vr.mCurScrollY); 19190 } 19191 19192 m.preTranslate(mLeft, mTop); 19193 19194 if (!hasIdentityMatrix()) { 19195 m.preConcat(getMatrix()); 19196 } 19197 } 19198 19199 /** 19200 * Modifies the input matrix such that it maps on-screen coordinates to 19201 * view-local coordinates. 19202 * 19203 * @param m input matrix to modify 19204 * @hide 19205 */ transformMatrixToLocal(Matrix m)19206 public void transformMatrixToLocal(Matrix m) { 19207 final ViewParent parent = mParent; 19208 if (parent instanceof View) { 19209 final View vp = (View) parent; 19210 vp.transformMatrixToLocal(m); 19211 m.postTranslate(vp.mScrollX, vp.mScrollY); 19212 } else if (parent instanceof ViewRootImpl) { 19213 final ViewRootImpl vr = (ViewRootImpl) parent; 19214 vr.transformMatrixToLocal(m); 19215 m.postTranslate(0, vr.mCurScrollY); 19216 } 19217 19218 m.postTranslate(-mLeft, -mTop); 19219 19220 if (!hasIdentityMatrix()) { 19221 m.postConcat(getInverseMatrix()); 19222 } 19223 } 19224 19225 /** 19226 * @hide 19227 */ 19228 @ViewDebug.ExportedProperty(category = "layout", indexMapping = { 19229 @ViewDebug.IntToString(from = 0, to = "x"), 19230 @ViewDebug.IntToString(from = 1, to = "y") 19231 }) getLocationOnScreen()19232 public int[] getLocationOnScreen() { 19233 int[] location = new int[2]; 19234 getLocationOnScreen(location); 19235 return location; 19236 } 19237 19238 /** 19239 * <p>Computes the coordinates of this view on the screen. The argument 19240 * must be an array of two integers. After the method returns, the array 19241 * contains the x and y location in that order.</p> 19242 * 19243 * @param outLocation an array of two integers in which to hold the coordinates 19244 */ getLocationOnScreen(@ize2) int[] outLocation)19245 public void getLocationOnScreen(@Size(2) int[] outLocation) { 19246 getLocationInWindow(outLocation); 19247 19248 final AttachInfo info = mAttachInfo; 19249 if (info != null) { 19250 outLocation[0] += info.mWindowLeft; 19251 outLocation[1] += info.mWindowTop; 19252 } 19253 } 19254 19255 /** 19256 * <p>Computes the coordinates of this view in its window. The argument 19257 * must be an array of two integers. After the method returns, the array 19258 * contains the x and y location in that order.</p> 19259 * 19260 * @param outLocation an array of two integers in which to hold the coordinates 19261 */ getLocationInWindow(@ize2) int[] outLocation)19262 public void getLocationInWindow(@Size(2) int[] outLocation) { 19263 if (outLocation == null || outLocation.length < 2) { 19264 throw new IllegalArgumentException("outLocation must be an array of two integers"); 19265 } 19266 19267 outLocation[0] = 0; 19268 outLocation[1] = 0; 19269 19270 transformFromViewToWindowSpace(outLocation); 19271 } 19272 19273 /** @hide */ transformFromViewToWindowSpace(@ize2) int[] inOutLocation)19274 public void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) { 19275 if (inOutLocation == null || inOutLocation.length < 2) { 19276 throw new IllegalArgumentException("inOutLocation must be an array of two integers"); 19277 } 19278 19279 if (mAttachInfo == null) { 19280 // When the view is not attached to a window, this method does not make sense 19281 inOutLocation[0] = inOutLocation[1] = 0; 19282 return; 19283 } 19284 19285 float position[] = mAttachInfo.mTmpTransformLocation; 19286 position[0] = inOutLocation[0]; 19287 position[1] = inOutLocation[1]; 19288 19289 if (!hasIdentityMatrix()) { 19290 getMatrix().mapPoints(position); 19291 } 19292 19293 position[0] += mLeft; 19294 position[1] += mTop; 19295 19296 ViewParent viewParent = mParent; 19297 while (viewParent instanceof View) { 19298 final View view = (View) viewParent; 19299 19300 position[0] -= view.mScrollX; 19301 position[1] -= view.mScrollY; 19302 19303 if (!view.hasIdentityMatrix()) { 19304 view.getMatrix().mapPoints(position); 19305 } 19306 19307 position[0] += view.mLeft; 19308 position[1] += view.mTop; 19309 19310 viewParent = view.mParent; 19311 } 19312 19313 if (viewParent instanceof ViewRootImpl) { 19314 // *cough* 19315 final ViewRootImpl vr = (ViewRootImpl) viewParent; 19316 position[1] -= vr.mCurScrollY; 19317 } 19318 19319 inOutLocation[0] = Math.round(position[0]); 19320 inOutLocation[1] = Math.round(position[1]); 19321 } 19322 19323 /** 19324 * {@hide} 19325 * @param id the id of the view to be found 19326 * @return the view of the specified id, null if cannot be found 19327 */ findViewTraversal(@dRes int id)19328 protected View findViewTraversal(@IdRes int id) { 19329 if (id == mID) { 19330 return this; 19331 } 19332 return null; 19333 } 19334 19335 /** 19336 * {@hide} 19337 * @param tag the tag of the view to be found 19338 * @return the view of specified tag, null if cannot be found 19339 */ findViewWithTagTraversal(Object tag)19340 protected View findViewWithTagTraversal(Object tag) { 19341 if (tag != null && tag.equals(mTag)) { 19342 return this; 19343 } 19344 return null; 19345 } 19346 19347 /** 19348 * {@hide} 19349 * @param predicate The predicate to evaluate. 19350 * @param childToSkip If not null, ignores this child during the recursive traversal. 19351 * @return The first view that matches the predicate or null. 19352 */ findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)19353 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 19354 if (predicate.apply(this)) { 19355 return this; 19356 } 19357 return null; 19358 } 19359 19360 /** 19361 * Look for a child view with the given id. If this view has the given 19362 * id, return this view. 19363 * 19364 * @param id The id to search for. 19365 * @return The view that has the given id in the hierarchy or null 19366 */ 19367 @Nullable findViewById(@dRes int id)19368 public final View findViewById(@IdRes int id) { 19369 if (id < 0) { 19370 return null; 19371 } 19372 return findViewTraversal(id); 19373 } 19374 19375 /** 19376 * Finds a view by its unuque and stable accessibility id. 19377 * 19378 * @param accessibilityId The searched accessibility id. 19379 * @return The found view. 19380 */ findViewByAccessibilityId(int accessibilityId)19381 final View findViewByAccessibilityId(int accessibilityId) { 19382 if (accessibilityId < 0) { 19383 return null; 19384 } 19385 View view = findViewByAccessibilityIdTraversal(accessibilityId); 19386 if (view != null) { 19387 return view.includeForAccessibility() ? view : null; 19388 } 19389 return null; 19390 } 19391 19392 /** 19393 * Performs the traversal to find a view by its unuque and stable accessibility id. 19394 * 19395 * <strong>Note:</strong>This method does not stop at the root namespace 19396 * boundary since the user can touch the screen at an arbitrary location 19397 * potentially crossing the root namespace bounday which will send an 19398 * accessibility event to accessibility services and they should be able 19399 * to obtain the event source. Also accessibility ids are guaranteed to be 19400 * unique in the window. 19401 * 19402 * @param accessibilityId The accessibility id. 19403 * @return The found view. 19404 * 19405 * @hide 19406 */ findViewByAccessibilityIdTraversal(int accessibilityId)19407 public View findViewByAccessibilityIdTraversal(int accessibilityId) { 19408 if (getAccessibilityViewId() == accessibilityId) { 19409 return this; 19410 } 19411 return null; 19412 } 19413 19414 /** 19415 * Look for a child view with the given tag. If this view has the given 19416 * tag, return this view. 19417 * 19418 * @param tag The tag to search for, using "tag.equals(getTag())". 19419 * @return The View that has the given tag in the hierarchy or null 19420 */ findViewWithTag(Object tag)19421 public final View findViewWithTag(Object tag) { 19422 if (tag == null) { 19423 return null; 19424 } 19425 return findViewWithTagTraversal(tag); 19426 } 19427 19428 /** 19429 * {@hide} 19430 * Look for a child view that matches the specified predicate. 19431 * If this view matches the predicate, return this view. 19432 * 19433 * @param predicate The predicate to evaluate. 19434 * @return The first view that matches the predicate or null. 19435 */ findViewByPredicate(Predicate<View> predicate)19436 public final View findViewByPredicate(Predicate<View> predicate) { 19437 return findViewByPredicateTraversal(predicate, null); 19438 } 19439 19440 /** 19441 * {@hide} 19442 * Look for a child view that matches the specified predicate, 19443 * starting with the specified view and its descendents and then 19444 * recusively searching the ancestors and siblings of that view 19445 * until this view is reached. 19446 * 19447 * This method is useful in cases where the predicate does not match 19448 * a single unique view (perhaps multiple views use the same id) 19449 * and we are trying to find the view that is "closest" in scope to the 19450 * starting view. 19451 * 19452 * @param start The view to start from. 19453 * @param predicate The predicate to evaluate. 19454 * @return The first view that matches the predicate or null. 19455 */ findViewByPredicateInsideOut(View start, Predicate<View> predicate)19456 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 19457 View childToSkip = null; 19458 for (;;) { 19459 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 19460 if (view != null || start == this) { 19461 return view; 19462 } 19463 19464 ViewParent parent = start.getParent(); 19465 if (parent == null || !(parent instanceof View)) { 19466 return null; 19467 } 19468 19469 childToSkip = start; 19470 start = (View) parent; 19471 } 19472 } 19473 19474 /** 19475 * Sets the identifier for this view. The identifier does not have to be 19476 * unique in this view's hierarchy. The identifier should be a positive 19477 * number. 19478 * 19479 * @see #NO_ID 19480 * @see #getId() 19481 * @see #findViewById(int) 19482 * 19483 * @param id a number used to identify the view 19484 * 19485 * @attr ref android.R.styleable#View_id 19486 */ setId(@dRes int id)19487 public void setId(@IdRes int id) { 19488 mID = id; 19489 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 19490 mID = generateViewId(); 19491 } 19492 } 19493 19494 /** 19495 * {@hide} 19496 * 19497 * @param isRoot true if the view belongs to the root namespace, false 19498 * otherwise 19499 */ setIsRootNamespace(boolean isRoot)19500 public void setIsRootNamespace(boolean isRoot) { 19501 if (isRoot) { 19502 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 19503 } else { 19504 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 19505 } 19506 } 19507 19508 /** 19509 * {@hide} 19510 * 19511 * @return true if the view belongs to the root namespace, false otherwise 19512 */ isRootNamespace()19513 public boolean isRootNamespace() { 19514 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 19515 } 19516 19517 /** 19518 * Returns this view's identifier. 19519 * 19520 * @return a positive integer used to identify the view or {@link #NO_ID} 19521 * if the view has no ID 19522 * 19523 * @see #setId(int) 19524 * @see #findViewById(int) 19525 * @attr ref android.R.styleable#View_id 19526 */ 19527 @IdRes 19528 @ViewDebug.CapturedViewProperty getId()19529 public int getId() { 19530 return mID; 19531 } 19532 19533 /** 19534 * Returns this view's tag. 19535 * 19536 * @return the Object stored in this view as a tag, or {@code null} if not 19537 * set 19538 * 19539 * @see #setTag(Object) 19540 * @see #getTag(int) 19541 */ 19542 @ViewDebug.ExportedProperty getTag()19543 public Object getTag() { 19544 return mTag; 19545 } 19546 19547 /** 19548 * Sets the tag associated with this view. A tag can be used to mark 19549 * a view in its hierarchy and does not have to be unique within the 19550 * hierarchy. Tags can also be used to store data within a view without 19551 * resorting to another data structure. 19552 * 19553 * @param tag an Object to tag the view with 19554 * 19555 * @see #getTag() 19556 * @see #setTag(int, Object) 19557 */ setTag(final Object tag)19558 public void setTag(final Object tag) { 19559 mTag = tag; 19560 } 19561 19562 /** 19563 * Returns the tag associated with this view and the specified key. 19564 * 19565 * @param key The key identifying the tag 19566 * 19567 * @return the Object stored in this view as a tag, or {@code null} if not 19568 * set 19569 * 19570 * @see #setTag(int, Object) 19571 * @see #getTag() 19572 */ getTag(int key)19573 public Object getTag(int key) { 19574 if (mKeyedTags != null) return mKeyedTags.get(key); 19575 return null; 19576 } 19577 19578 /** 19579 * Sets a tag associated with this view and a key. A tag can be used 19580 * to mark a view in its hierarchy and does not have to be unique within 19581 * the hierarchy. Tags can also be used to store data within a view 19582 * without resorting to another data structure. 19583 * 19584 * The specified key should be an id declared in the resources of the 19585 * application to ensure it is unique (see the <a 19586 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 19587 * Keys identified as belonging to 19588 * the Android framework or not associated with any package will cause 19589 * an {@link IllegalArgumentException} to be thrown. 19590 * 19591 * @param key The key identifying the tag 19592 * @param tag An Object to tag the view with 19593 * 19594 * @throws IllegalArgumentException If they specified key is not valid 19595 * 19596 * @see #setTag(Object) 19597 * @see #getTag(int) 19598 */ setTag(int key, final Object tag)19599 public void setTag(int key, final Object tag) { 19600 // If the package id is 0x00 or 0x01, it's either an undefined package 19601 // or a framework id 19602 if ((key >>> 24) < 2) { 19603 throw new IllegalArgumentException("The key must be an application-specific " 19604 + "resource id."); 19605 } 19606 19607 setKeyedTag(key, tag); 19608 } 19609 19610 /** 19611 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 19612 * framework id. 19613 * 19614 * @hide 19615 */ setTagInternal(int key, Object tag)19616 public void setTagInternal(int key, Object tag) { 19617 if ((key >>> 24) != 0x1) { 19618 throw new IllegalArgumentException("The key must be a framework-specific " 19619 + "resource id."); 19620 } 19621 19622 setKeyedTag(key, tag); 19623 } 19624 setKeyedTag(int key, Object tag)19625 private void setKeyedTag(int key, Object tag) { 19626 if (mKeyedTags == null) { 19627 mKeyedTags = new SparseArray<Object>(2); 19628 } 19629 19630 mKeyedTags.put(key, tag); 19631 } 19632 19633 /** 19634 * Prints information about this view in the log output, with the tag 19635 * {@link #VIEW_LOG_TAG}. 19636 * 19637 * @hide 19638 */ debug()19639 public void debug() { 19640 debug(0); 19641 } 19642 19643 /** 19644 * Prints information about this view in the log output, with the tag 19645 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 19646 * indentation defined by the <code>depth</code>. 19647 * 19648 * @param depth the indentation level 19649 * 19650 * @hide 19651 */ debug(int depth)19652 protected void debug(int depth) { 19653 String output = debugIndent(depth - 1); 19654 19655 output += "+ " + this; 19656 int id = getId(); 19657 if (id != -1) { 19658 output += " (id=" + id + ")"; 19659 } 19660 Object tag = getTag(); 19661 if (tag != null) { 19662 output += " (tag=" + tag + ")"; 19663 } 19664 Log.d(VIEW_LOG_TAG, output); 19665 19666 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 19667 output = debugIndent(depth) + " FOCUSED"; 19668 Log.d(VIEW_LOG_TAG, output); 19669 } 19670 19671 output = debugIndent(depth); 19672 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 19673 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 19674 + "} "; 19675 Log.d(VIEW_LOG_TAG, output); 19676 19677 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 19678 || mPaddingBottom != 0) { 19679 output = debugIndent(depth); 19680 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 19681 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 19682 Log.d(VIEW_LOG_TAG, output); 19683 } 19684 19685 output = debugIndent(depth); 19686 output += "mMeasureWidth=" + mMeasuredWidth + 19687 " mMeasureHeight=" + mMeasuredHeight; 19688 Log.d(VIEW_LOG_TAG, output); 19689 19690 output = debugIndent(depth); 19691 if (mLayoutParams == null) { 19692 output += "BAD! no layout params"; 19693 } else { 19694 output = mLayoutParams.debug(output); 19695 } 19696 Log.d(VIEW_LOG_TAG, output); 19697 19698 output = debugIndent(depth); 19699 output += "flags={"; 19700 output += View.printFlags(mViewFlags); 19701 output += "}"; 19702 Log.d(VIEW_LOG_TAG, output); 19703 19704 output = debugIndent(depth); 19705 output += "privateFlags={"; 19706 output += View.printPrivateFlags(mPrivateFlags); 19707 output += "}"; 19708 Log.d(VIEW_LOG_TAG, output); 19709 } 19710 19711 /** 19712 * Creates a string of whitespaces used for indentation. 19713 * 19714 * @param depth the indentation level 19715 * @return a String containing (depth * 2 + 3) * 2 white spaces 19716 * 19717 * @hide 19718 */ debugIndent(int depth)19719 protected static String debugIndent(int depth) { 19720 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 19721 for (int i = 0; i < (depth * 2) + 3; i++) { 19722 spaces.append(' ').append(' '); 19723 } 19724 return spaces.toString(); 19725 } 19726 19727 /** 19728 * <p>Return the offset of the widget's text baseline from the widget's top 19729 * boundary. If this widget does not support baseline alignment, this 19730 * method returns -1. </p> 19731 * 19732 * @return the offset of the baseline within the widget's bounds or -1 19733 * if baseline alignment is not supported 19734 */ 19735 @ViewDebug.ExportedProperty(category = "layout") getBaseline()19736 public int getBaseline() { 19737 return -1; 19738 } 19739 19740 /** 19741 * Returns whether the view hierarchy is currently undergoing a layout pass. This 19742 * information is useful to avoid situations such as calling {@link #requestLayout()} during 19743 * a layout pass. 19744 * 19745 * @return whether the view hierarchy is currently undergoing a layout pass 19746 */ isInLayout()19747 public boolean isInLayout() { 19748 ViewRootImpl viewRoot = getViewRootImpl(); 19749 return (viewRoot != null && viewRoot.isInLayout()); 19750 } 19751 19752 /** 19753 * Call this when something has changed which has invalidated the 19754 * layout of this view. This will schedule a layout pass of the view 19755 * tree. This should not be called while the view hierarchy is currently in a layout 19756 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 19757 * end of the current layout pass (and then layout will run again) or after the current 19758 * frame is drawn and the next layout occurs. 19759 * 19760 * <p>Subclasses which override this method should call the superclass method to 19761 * handle possible request-during-layout errors correctly.</p> 19762 */ 19763 @CallSuper requestLayout()19764 public void requestLayout() { 19765 if (mMeasureCache != null) mMeasureCache.clear(); 19766 19767 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 19768 // Only trigger request-during-layout logic if this is the view requesting it, 19769 // not the views in its parent hierarchy 19770 ViewRootImpl viewRoot = getViewRootImpl(); 19771 if (viewRoot != null && viewRoot.isInLayout()) { 19772 if (!viewRoot.requestLayoutDuringLayout(this)) { 19773 return; 19774 } 19775 } 19776 mAttachInfo.mViewRequestingLayout = this; 19777 } 19778 19779 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19780 mPrivateFlags |= PFLAG_INVALIDATED; 19781 19782 if (mParent != null && !mParent.isLayoutRequested()) { 19783 mParent.requestLayout(); 19784 } 19785 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 19786 mAttachInfo.mViewRequestingLayout = null; 19787 } 19788 } 19789 19790 /** 19791 * Forces this view to be laid out during the next layout pass. 19792 * This method does not call requestLayout() or forceLayout() 19793 * on the parent. 19794 */ forceLayout()19795 public void forceLayout() { 19796 if (mMeasureCache != null) mMeasureCache.clear(); 19797 19798 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19799 mPrivateFlags |= PFLAG_INVALIDATED; 19800 } 19801 19802 /** 19803 * <p> 19804 * This is called to find out how big a view should be. The parent 19805 * supplies constraint information in the width and height parameters. 19806 * </p> 19807 * 19808 * <p> 19809 * The actual measurement work of a view is performed in 19810 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 19811 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 19812 * </p> 19813 * 19814 * 19815 * @param widthMeasureSpec Horizontal space requirements as imposed by the 19816 * parent 19817 * @param heightMeasureSpec Vertical space requirements as imposed by the 19818 * parent 19819 * 19820 * @see #onMeasure(int, int) 19821 */ measure(int widthMeasureSpec, int heightMeasureSpec)19822 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 19823 boolean optical = isLayoutModeOptical(this); 19824 if (optical != isLayoutModeOptical(mParent)) { 19825 Insets insets = getOpticalInsets(); 19826 int oWidth = insets.left + insets.right; 19827 int oHeight = insets.top + insets.bottom; 19828 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 19829 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 19830 } 19831 19832 // Suppress sign extension for the low bytes 19833 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 19834 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 19835 19836 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 19837 19838 // Optimize layout by avoiding an extra EXACTLY pass when the view is 19839 // already measured as the correct size. In API 23 and below, this 19840 // extra pass is required to make LinearLayout re-distribute weight. 19841 final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec 19842 || heightMeasureSpec != mOldHeightMeasureSpec; 19843 final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY 19844 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; 19845 final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) 19846 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); 19847 final boolean needsLayout = specChanged 19848 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize); 19849 19850 if (forceLayout || needsLayout) { 19851 // first clears the measured dimension flag 19852 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 19853 19854 resolveRtlPropertiesIfNeeded(); 19855 19856 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); 19857 if (cacheIndex < 0 || sIgnoreMeasureCache) { 19858 // measure ourselves, this should set the measured dimension flag back 19859 onMeasure(widthMeasureSpec, heightMeasureSpec); 19860 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19861 } else { 19862 long value = mMeasureCache.valueAt(cacheIndex); 19863 // Casting a long to int drops the high 32 bits, no mask needed 19864 setMeasuredDimensionRaw((int) (value >> 32), (int) value); 19865 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19866 } 19867 19868 // flag not set, setMeasuredDimension() was not invoked, we raise 19869 // an exception to warn the developer 19870 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 19871 throw new IllegalStateException("View with id " + getId() + ": " 19872 + getClass().getName() + "#onMeasure() did not set the" 19873 + " measured dimension by calling" 19874 + " setMeasuredDimension()"); 19875 } 19876 19877 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 19878 } 19879 19880 mOldWidthMeasureSpec = widthMeasureSpec; 19881 mOldHeightMeasureSpec = heightMeasureSpec; 19882 19883 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 19884 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 19885 } 19886 19887 /** 19888 * <p> 19889 * Measure the view and its content to determine the measured width and the 19890 * measured height. This method is invoked by {@link #measure(int, int)} and 19891 * should be overridden by subclasses to provide accurate and efficient 19892 * measurement of their contents. 19893 * </p> 19894 * 19895 * <p> 19896 * <strong>CONTRACT:</strong> When overriding this method, you 19897 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 19898 * measured width and height of this view. Failure to do so will trigger an 19899 * <code>IllegalStateException</code>, thrown by 19900 * {@link #measure(int, int)}. Calling the superclass' 19901 * {@link #onMeasure(int, int)} is a valid use. 19902 * </p> 19903 * 19904 * <p> 19905 * The base class implementation of measure defaults to the background size, 19906 * unless a larger size is allowed by the MeasureSpec. Subclasses should 19907 * override {@link #onMeasure(int, int)} to provide better measurements of 19908 * their content. 19909 * </p> 19910 * 19911 * <p> 19912 * If this method is overridden, it is the subclass's responsibility to make 19913 * sure the measured height and width are at least the view's minimum height 19914 * and width ({@link #getSuggestedMinimumHeight()} and 19915 * {@link #getSuggestedMinimumWidth()}). 19916 * </p> 19917 * 19918 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 19919 * The requirements are encoded with 19920 * {@link android.view.View.MeasureSpec}. 19921 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 19922 * The requirements are encoded with 19923 * {@link android.view.View.MeasureSpec}. 19924 * 19925 * @see #getMeasuredWidth() 19926 * @see #getMeasuredHeight() 19927 * @see #setMeasuredDimension(int, int) 19928 * @see #getSuggestedMinimumHeight() 19929 * @see #getSuggestedMinimumWidth() 19930 * @see android.view.View.MeasureSpec#getMode(int) 19931 * @see android.view.View.MeasureSpec#getSize(int) 19932 */ onMeasure(int widthMeasureSpec, int heightMeasureSpec)19933 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 19934 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 19935 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 19936 } 19937 19938 /** 19939 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 19940 * measured width and measured height. Failing to do so will trigger an 19941 * exception at measurement time.</p> 19942 * 19943 * @param measuredWidth The measured width of this view. May be a complex 19944 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19945 * {@link #MEASURED_STATE_TOO_SMALL}. 19946 * @param measuredHeight The measured height of this view. May be a complex 19947 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19948 * {@link #MEASURED_STATE_TOO_SMALL}. 19949 */ setMeasuredDimension(int measuredWidth, int measuredHeight)19950 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 19951 boolean optical = isLayoutModeOptical(this); 19952 if (optical != isLayoutModeOptical(mParent)) { 19953 Insets insets = getOpticalInsets(); 19954 int opticalWidth = insets.left + insets.right; 19955 int opticalHeight = insets.top + insets.bottom; 19956 19957 measuredWidth += optical ? opticalWidth : -opticalWidth; 19958 measuredHeight += optical ? opticalHeight : -opticalHeight; 19959 } 19960 setMeasuredDimensionRaw(measuredWidth, measuredHeight); 19961 } 19962 19963 /** 19964 * Sets the measured dimension without extra processing for things like optical bounds. 19965 * Useful for reapplying consistent values that have already been cooked with adjustments 19966 * for optical bounds, etc. such as those from the measurement cache. 19967 * 19968 * @param measuredWidth The measured width of this view. May be a complex 19969 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19970 * {@link #MEASURED_STATE_TOO_SMALL}. 19971 * @param measuredHeight The measured height of this view. May be a complex 19972 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19973 * {@link #MEASURED_STATE_TOO_SMALL}. 19974 */ setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)19975 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { 19976 mMeasuredWidth = measuredWidth; 19977 mMeasuredHeight = measuredHeight; 19978 19979 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 19980 } 19981 19982 /** 19983 * Merge two states as returned by {@link #getMeasuredState()}. 19984 * @param curState The current state as returned from a view or the result 19985 * of combining multiple views. 19986 * @param newState The new view state to combine. 19987 * @return Returns a new integer reflecting the combination of the two 19988 * states. 19989 */ combineMeasuredStates(int curState, int newState)19990 public static int combineMeasuredStates(int curState, int newState) { 19991 return curState | newState; 19992 } 19993 19994 /** 19995 * Version of {@link #resolveSizeAndState(int, int, int)} 19996 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 19997 */ resolveSize(int size, int measureSpec)19998 public static int resolveSize(int size, int measureSpec) { 19999 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 20000 } 20001 20002 /** 20003 * Utility to reconcile a desired size and state, with constraints imposed 20004 * by a MeasureSpec. Will take the desired size, unless a different size 20005 * is imposed by the constraints. The returned value is a compound integer, 20006 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 20007 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the 20008 * resulting size is smaller than the size the view wants to be. 20009 * 20010 * @param size How big the view wants to be. 20011 * @param measureSpec Constraints imposed by the parent. 20012 * @param childMeasuredState Size information bit mask for the view's 20013 * children. 20014 * @return Size information bit mask as defined by 20015 * {@link #MEASURED_SIZE_MASK} and 20016 * {@link #MEASURED_STATE_TOO_SMALL}. 20017 */ resolveSizeAndState(int size, int measureSpec, int childMeasuredState)20018 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 20019 final int specMode = MeasureSpec.getMode(measureSpec); 20020 final int specSize = MeasureSpec.getSize(measureSpec); 20021 final int result; 20022 switch (specMode) { 20023 case MeasureSpec.AT_MOST: 20024 if (specSize < size) { 20025 result = specSize | MEASURED_STATE_TOO_SMALL; 20026 } else { 20027 result = size; 20028 } 20029 break; 20030 case MeasureSpec.EXACTLY: 20031 result = specSize; 20032 break; 20033 case MeasureSpec.UNSPECIFIED: 20034 default: 20035 result = size; 20036 } 20037 return result | (childMeasuredState & MEASURED_STATE_MASK); 20038 } 20039 20040 /** 20041 * Utility to return a default size. Uses the supplied size if the 20042 * MeasureSpec imposed no constraints. Will get larger if allowed 20043 * by the MeasureSpec. 20044 * 20045 * @param size Default size for this view 20046 * @param measureSpec Constraints imposed by the parent 20047 * @return The size this view should be. 20048 */ getDefaultSize(int size, int measureSpec)20049 public static int getDefaultSize(int size, int measureSpec) { 20050 int result = size; 20051 int specMode = MeasureSpec.getMode(measureSpec); 20052 int specSize = MeasureSpec.getSize(measureSpec); 20053 20054 switch (specMode) { 20055 case MeasureSpec.UNSPECIFIED: 20056 result = size; 20057 break; 20058 case MeasureSpec.AT_MOST: 20059 case MeasureSpec.EXACTLY: 20060 result = specSize; 20061 break; 20062 } 20063 return result; 20064 } 20065 20066 /** 20067 * Returns the suggested minimum height that the view should use. This 20068 * returns the maximum of the view's minimum height 20069 * and the background's minimum height 20070 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 20071 * <p> 20072 * When being used in {@link #onMeasure(int, int)}, the caller should still 20073 * ensure the returned height is within the requirements of the parent. 20074 * 20075 * @return The suggested minimum height of the view. 20076 */ getSuggestedMinimumHeight()20077 protected int getSuggestedMinimumHeight() { 20078 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 20079 20080 } 20081 20082 /** 20083 * Returns the suggested minimum width that the view should use. This 20084 * returns the maximum of the view's minimum width 20085 * and the background's minimum width 20086 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 20087 * <p> 20088 * When being used in {@link #onMeasure(int, int)}, the caller should still 20089 * ensure the returned width is within the requirements of the parent. 20090 * 20091 * @return The suggested minimum width of the view. 20092 */ getSuggestedMinimumWidth()20093 protected int getSuggestedMinimumWidth() { 20094 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 20095 } 20096 20097 /** 20098 * Returns the minimum height of the view. 20099 * 20100 * @return the minimum height the view will try to be. 20101 * 20102 * @see #setMinimumHeight(int) 20103 * 20104 * @attr ref android.R.styleable#View_minHeight 20105 */ getMinimumHeight()20106 public int getMinimumHeight() { 20107 return mMinHeight; 20108 } 20109 20110 /** 20111 * Sets the minimum height of the view. It is not guaranteed the view will 20112 * be able to achieve this minimum height (for example, if its parent layout 20113 * constrains it with less available height). 20114 * 20115 * @param minHeight The minimum height the view will try to be. 20116 * 20117 * @see #getMinimumHeight() 20118 * 20119 * @attr ref android.R.styleable#View_minHeight 20120 */ 20121 @RemotableViewMethod setMinimumHeight(int minHeight)20122 public void setMinimumHeight(int minHeight) { 20123 mMinHeight = minHeight; 20124 requestLayout(); 20125 } 20126 20127 /** 20128 * Returns the minimum width of the view. 20129 * 20130 * @return the minimum width the view will try to be. 20131 * 20132 * @see #setMinimumWidth(int) 20133 * 20134 * @attr ref android.R.styleable#View_minWidth 20135 */ getMinimumWidth()20136 public int getMinimumWidth() { 20137 return mMinWidth; 20138 } 20139 20140 /** 20141 * Sets the minimum width of the view. It is not guaranteed the view will 20142 * be able to achieve this minimum width (for example, if its parent layout 20143 * constrains it with less available width). 20144 * 20145 * @param minWidth The minimum width the view will try to be. 20146 * 20147 * @see #getMinimumWidth() 20148 * 20149 * @attr ref android.R.styleable#View_minWidth 20150 */ setMinimumWidth(int minWidth)20151 public void setMinimumWidth(int minWidth) { 20152 mMinWidth = minWidth; 20153 requestLayout(); 20154 20155 } 20156 20157 /** 20158 * Get the animation currently associated with this view. 20159 * 20160 * @return The animation that is currently playing or 20161 * scheduled to play for this view. 20162 */ getAnimation()20163 public Animation getAnimation() { 20164 return mCurrentAnimation; 20165 } 20166 20167 /** 20168 * Start the specified animation now. 20169 * 20170 * @param animation the animation to start now 20171 */ startAnimation(Animation animation)20172 public void startAnimation(Animation animation) { 20173 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 20174 setAnimation(animation); 20175 invalidateParentCaches(); 20176 invalidate(true); 20177 } 20178 20179 /** 20180 * Cancels any animations for this view. 20181 */ clearAnimation()20182 public void clearAnimation() { 20183 if (mCurrentAnimation != null) { 20184 mCurrentAnimation.detach(); 20185 } 20186 mCurrentAnimation = null; 20187 invalidateParentIfNeeded(); 20188 } 20189 20190 /** 20191 * Sets the next animation to play for this view. 20192 * If you want the animation to play immediately, use 20193 * {@link #startAnimation(android.view.animation.Animation)} instead. 20194 * This method provides allows fine-grained 20195 * control over the start time and invalidation, but you 20196 * must make sure that 1) the animation has a start time set, and 20197 * 2) the view's parent (which controls animations on its children) 20198 * will be invalidated when the animation is supposed to 20199 * start. 20200 * 20201 * @param animation The next animation, or null. 20202 */ setAnimation(Animation animation)20203 public void setAnimation(Animation animation) { 20204 mCurrentAnimation = animation; 20205 20206 if (animation != null) { 20207 // If the screen is off assume the animation start time is now instead of 20208 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 20209 // would cause the animation to start when the screen turns back on 20210 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF 20211 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 20212 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 20213 } 20214 animation.reset(); 20215 } 20216 } 20217 20218 /** 20219 * Invoked by a parent ViewGroup to notify the start of the animation 20220 * currently associated with this view. If you override this method, 20221 * always call super.onAnimationStart(); 20222 * 20223 * @see #setAnimation(android.view.animation.Animation) 20224 * @see #getAnimation() 20225 */ 20226 @CallSuper onAnimationStart()20227 protected void onAnimationStart() { 20228 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 20229 } 20230 20231 /** 20232 * Invoked by a parent ViewGroup to notify the end of the animation 20233 * currently associated with this view. If you override this method, 20234 * always call super.onAnimationEnd(); 20235 * 20236 * @see #setAnimation(android.view.animation.Animation) 20237 * @see #getAnimation() 20238 */ 20239 @CallSuper onAnimationEnd()20240 protected void onAnimationEnd() { 20241 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 20242 } 20243 20244 /** 20245 * Invoked if there is a Transform that involves alpha. Subclass that can 20246 * draw themselves with the specified alpha should return true, and then 20247 * respect that alpha when their onDraw() is called. If this returns false 20248 * then the view may be redirected to draw into an offscreen buffer to 20249 * fulfill the request, which will look fine, but may be slower than if the 20250 * subclass handles it internally. The default implementation returns false. 20251 * 20252 * @param alpha The alpha (0..255) to apply to the view's drawing 20253 * @return true if the view can draw with the specified alpha. 20254 */ onSetAlpha(int alpha)20255 protected boolean onSetAlpha(int alpha) { 20256 return false; 20257 } 20258 20259 /** 20260 * This is used by the RootView to perform an optimization when 20261 * the view hierarchy contains one or several SurfaceView. 20262 * SurfaceView is always considered transparent, but its children are not, 20263 * therefore all View objects remove themselves from the global transparent 20264 * region (passed as a parameter to this function). 20265 * 20266 * @param region The transparent region for this ViewAncestor (window). 20267 * 20268 * @return Returns true if the effective visibility of the view at this 20269 * point is opaque, regardless of the transparent region; returns false 20270 * if it is possible for underlying windows to be seen behind the view. 20271 * 20272 * {@hide} 20273 */ gatherTransparentRegion(Region region)20274 public boolean gatherTransparentRegion(Region region) { 20275 final AttachInfo attachInfo = mAttachInfo; 20276 if (region != null && attachInfo != null) { 20277 final int pflags = mPrivateFlags; 20278 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 20279 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 20280 // remove it from the transparent region. 20281 final int[] location = attachInfo.mTransparentLocation; 20282 getLocationInWindow(location); 20283 region.op(location[0], location[1], location[0] + mRight - mLeft, 20284 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 20285 } else { 20286 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) { 20287 // The SKIP_DRAW flag IS set and the background drawable exists, we remove 20288 // the background drawable's non-transparent parts from this transparent region. 20289 applyDrawableToTransparentRegion(mBackground, region); 20290 } 20291 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 20292 && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) { 20293 // Similarly, we remove the foreground drawable's non-transparent parts. 20294 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region); 20295 } 20296 } 20297 } 20298 return true; 20299 } 20300 20301 /** 20302 * Play a sound effect for this view. 20303 * 20304 * <p>The framework will play sound effects for some built in actions, such as 20305 * clicking, but you may wish to play these effects in your widget, 20306 * for instance, for internal navigation. 20307 * 20308 * <p>The sound effect will only be played if sound effects are enabled by the user, and 20309 * {@link #isSoundEffectsEnabled()} is true. 20310 * 20311 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 20312 */ playSoundEffect(int soundConstant)20313 public void playSoundEffect(int soundConstant) { 20314 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 20315 return; 20316 } 20317 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 20318 } 20319 20320 /** 20321 * BZZZTT!!1! 20322 * 20323 * <p>Provide haptic feedback to the user for this view. 20324 * 20325 * <p>The framework will provide haptic feedback for some built in actions, 20326 * such as long presses, but you may wish to provide feedback for your 20327 * own widget. 20328 * 20329 * <p>The feedback will only be performed if 20330 * {@link #isHapticFeedbackEnabled()} is true. 20331 * 20332 * @param feedbackConstant One of the constants defined in 20333 * {@link HapticFeedbackConstants} 20334 */ performHapticFeedback(int feedbackConstant)20335 public boolean performHapticFeedback(int feedbackConstant) { 20336 return performHapticFeedback(feedbackConstant, 0); 20337 } 20338 20339 /** 20340 * BZZZTT!!1! 20341 * 20342 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 20343 * 20344 * @param feedbackConstant One of the constants defined in 20345 * {@link HapticFeedbackConstants} 20346 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 20347 */ performHapticFeedback(int feedbackConstant, int flags)20348 public boolean performHapticFeedback(int feedbackConstant, int flags) { 20349 if (mAttachInfo == null) { 20350 return false; 20351 } 20352 //noinspection SimplifiableIfStatement 20353 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 20354 && !isHapticFeedbackEnabled()) { 20355 return false; 20356 } 20357 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 20358 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 20359 } 20360 20361 /** 20362 * Request that the visibility of the status bar or other screen/window 20363 * decorations be changed. 20364 * 20365 * <p>This method is used to put the over device UI into temporary modes 20366 * where the user's attention is focused more on the application content, 20367 * by dimming or hiding surrounding system affordances. This is typically 20368 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 20369 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 20370 * to be placed behind the action bar (and with these flags other system 20371 * affordances) so that smooth transitions between hiding and showing them 20372 * can be done. 20373 * 20374 * <p>Two representative examples of the use of system UI visibility is 20375 * implementing a content browsing application (like a magazine reader) 20376 * and a video playing application. 20377 * 20378 * <p>The first code shows a typical implementation of a View in a content 20379 * browsing application. In this implementation, the application goes 20380 * into a content-oriented mode by hiding the status bar and action bar, 20381 * and putting the navigation elements into lights out mode. The user can 20382 * then interact with content while in this mode. Such an application should 20383 * provide an easy way for the user to toggle out of the mode (such as to 20384 * check information in the status bar or access notifications). In the 20385 * implementation here, this is done simply by tapping on the content. 20386 * 20387 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 20388 * content} 20389 * 20390 * <p>This second code sample shows a typical implementation of a View 20391 * in a video playing application. In this situation, while the video is 20392 * playing the application would like to go into a complete full-screen mode, 20393 * to use as much of the display as possible for the video. When in this state 20394 * the user can not interact with the application; the system intercepts 20395 * touching on the screen to pop the UI out of full screen mode. See 20396 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 20397 * 20398 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 20399 * content} 20400 * 20401 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 20402 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 20403 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 20404 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 20405 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 20406 */ setSystemUiVisibility(int visibility)20407 public void setSystemUiVisibility(int visibility) { 20408 if (visibility != mSystemUiVisibility) { 20409 mSystemUiVisibility = visibility; 20410 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 20411 mParent.recomputeViewAttributes(this); 20412 } 20413 } 20414 } 20415 20416 /** 20417 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 20418 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 20419 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 20420 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 20421 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 20422 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 20423 */ getSystemUiVisibility()20424 public int getSystemUiVisibility() { 20425 return mSystemUiVisibility; 20426 } 20427 20428 /** 20429 * Returns the current system UI visibility that is currently set for 20430 * the entire window. This is the combination of the 20431 * {@link #setSystemUiVisibility(int)} values supplied by all of the 20432 * views in the window. 20433 */ getWindowSystemUiVisibility()20434 public int getWindowSystemUiVisibility() { 20435 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 20436 } 20437 20438 /** 20439 * Override to find out when the window's requested system UI visibility 20440 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 20441 * This is different from the callbacks received through 20442 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 20443 * in that this is only telling you about the local request of the window, 20444 * not the actual values applied by the system. 20445 */ onWindowSystemUiVisibilityChanged(int visible)20446 public void onWindowSystemUiVisibilityChanged(int visible) { 20447 } 20448 20449 /** 20450 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 20451 * the view hierarchy. 20452 */ dispatchWindowSystemUiVisiblityChanged(int visible)20453 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 20454 onWindowSystemUiVisibilityChanged(visible); 20455 } 20456 20457 /** 20458 * Set a listener to receive callbacks when the visibility of the system bar changes. 20459 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 20460 */ setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l)20461 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 20462 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 20463 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 20464 mParent.recomputeViewAttributes(this); 20465 } 20466 } 20467 20468 /** 20469 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 20470 * the view hierarchy. 20471 */ dispatchSystemUiVisibilityChanged(int visibility)20472 public void dispatchSystemUiVisibilityChanged(int visibility) { 20473 ListenerInfo li = mListenerInfo; 20474 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 20475 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 20476 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 20477 } 20478 } 20479 updateLocalSystemUiVisibility(int localValue, int localChanges)20480 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 20481 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 20482 if (val != mSystemUiVisibility) { 20483 setSystemUiVisibility(val); 20484 return true; 20485 } 20486 return false; 20487 } 20488 20489 /** @hide */ setDisabledSystemUiVisibility(int flags)20490 public void setDisabledSystemUiVisibility(int flags) { 20491 if (mAttachInfo != null) { 20492 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 20493 mAttachInfo.mDisabledSystemUiVisibility = flags; 20494 if (mParent != null) { 20495 mParent.recomputeViewAttributes(this); 20496 } 20497 } 20498 } 20499 } 20500 20501 /** 20502 * Creates an image that the system displays during the drag and drop 20503 * operation. This is called a "drag shadow". The default implementation 20504 * for a DragShadowBuilder based on a View returns an image that has exactly the same 20505 * appearance as the given View. The default also positions the center of the drag shadow 20506 * directly under the touch point. If no View is provided (the constructor with no parameters 20507 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 20508 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the 20509 * default is an invisible drag shadow. 20510 * <p> 20511 * You are not required to use the View you provide to the constructor as the basis of the 20512 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 20513 * anything you want as the drag shadow. 20514 * </p> 20515 * <p> 20516 * You pass a DragShadowBuilder object to the system when you start the drag. The system 20517 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 20518 * size and position of the drag shadow. It uses this data to construct a 20519 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 20520 * so that your application can draw the shadow image in the Canvas. 20521 * </p> 20522 * 20523 * <div class="special reference"> 20524 * <h3>Developer Guides</h3> 20525 * <p>For a guide to implementing drag and drop features, read the 20526 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 20527 * </div> 20528 */ 20529 public static class DragShadowBuilder { 20530 private final WeakReference<View> mView; 20531 20532 /** 20533 * Constructs a shadow image builder based on a View. By default, the resulting drag 20534 * shadow will have the same appearance and dimensions as the View, with the touch point 20535 * over the center of the View. 20536 * @param view A View. Any View in scope can be used. 20537 */ DragShadowBuilder(View view)20538 public DragShadowBuilder(View view) { 20539 mView = new WeakReference<View>(view); 20540 } 20541 20542 /** 20543 * Construct a shadow builder object with no associated View. This 20544 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 20545 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 20546 * to supply the drag shadow's dimensions and appearance without 20547 * reference to any View object. If they are not overridden, then the result is an 20548 * invisible drag shadow. 20549 */ DragShadowBuilder()20550 public DragShadowBuilder() { 20551 mView = new WeakReference<View>(null); 20552 } 20553 20554 /** 20555 * Returns the View object that had been passed to the 20556 * {@link #View.DragShadowBuilder(View)} 20557 * constructor. If that View parameter was {@code null} or if the 20558 * {@link #View.DragShadowBuilder()} 20559 * constructor was used to instantiate the builder object, this method will return 20560 * null. 20561 * 20562 * @return The View object associate with this builder object. 20563 */ 20564 @SuppressWarnings({"JavadocReference"}) getView()20565 final public View getView() { 20566 return mView.get(); 20567 } 20568 20569 /** 20570 * Provides the metrics for the shadow image. These include the dimensions of 20571 * the shadow image, and the point within that shadow that should 20572 * be centered under the touch location while dragging. 20573 * <p> 20574 * The default implementation sets the dimensions of the shadow to be the 20575 * same as the dimensions of the View itself and centers the shadow under 20576 * the touch point. 20577 * </p> 20578 * 20579 * @param outShadowSize A {@link android.graphics.Point} containing the width and height 20580 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 20581 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 20582 * image. 20583 * 20584 * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the 20585 * shadow image that should be underneath the touch point during the drag and drop 20586 * operation. Your application must set {@link android.graphics.Point#x} to the 20587 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 20588 */ onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint)20589 public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { 20590 final View view = mView.get(); 20591 if (view != null) { 20592 outShadowSize.set(view.getWidth(), view.getHeight()); 20593 outShadowTouchPoint.set(outShadowSize.x / 2, outShadowSize.y / 2); 20594 } else { 20595 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 20596 } 20597 } 20598 20599 /** 20600 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 20601 * based on the dimensions it received from the 20602 * {@link #onProvideShadowMetrics(Point, Point)} callback. 20603 * 20604 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 20605 */ onDrawShadow(Canvas canvas)20606 public void onDrawShadow(Canvas canvas) { 20607 final View view = mView.get(); 20608 if (view != null) { 20609 view.draw(canvas); 20610 } else { 20611 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 20612 } 20613 } 20614 } 20615 20616 /** 20617 * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) 20618 * startDragAndDrop()} for newer platform versions. 20619 */ startDrag(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20620 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 20621 Object myLocalState, int flags) { 20622 return startDragAndDrop(data, shadowBuilder, myLocalState, flags); 20623 } 20624 20625 /** 20626 * Starts a drag and drop operation. When your application calls this method, it passes a 20627 * {@link android.view.View.DragShadowBuilder} object to the system. The 20628 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 20629 * to get metrics for the drag shadow, and then calls the object's 20630 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 20631 * <p> 20632 * Once the system has the drag shadow, it begins the drag and drop operation by sending 20633 * drag events to all the View objects in your application that are currently visible. It does 20634 * this either by calling the View object's drag listener (an implementation of 20635 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 20636 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 20637 * Both are passed a {@link android.view.DragEvent} object that has a 20638 * {@link android.view.DragEvent#getAction()} value of 20639 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 20640 * </p> 20641 * <p> 20642 * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, 20643 * int) startDragAndDrop()} on any attached View object. The View object does not need to be 20644 * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related 20645 * to the View the user selected for dragging. 20646 * </p> 20647 * @param data A {@link android.content.ClipData} object pointing to the data to be 20648 * transferred by the drag and drop operation. 20649 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 20650 * drag shadow. 20651 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 20652 * drop operation. This Object is put into every DragEvent object sent by the system during the 20653 * current drag. 20654 * <p> 20655 * myLocalState is a lightweight mechanism for the sending information from the dragged View 20656 * to the target Views. For example, it can contain flags that differentiate between a 20657 * a copy operation and a move operation. 20658 * </p> 20659 * @param flags Flags that control the drag and drop operation. This can be set to 0 for no 20660 * flags, or any combination of the following: 20661 * <ul> 20662 * <li>{@link #DRAG_FLAG_GLOBAL}</li> 20663 * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li> 20664 * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> 20665 * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li> 20666 * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li> 20667 * <li>{@link #DRAG_FLAG_OPAQUE}</li> 20668 * </ul> 20669 * @return {@code true} if the method completes successfully, or 20670 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 20671 * do a drag, and so no drag operation is in progress. 20672 */ startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, Object myLocalState, int flags)20673 public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, 20674 Object myLocalState, int flags) { 20675 if (ViewDebug.DEBUG_DRAG) { 20676 Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags); 20677 } 20678 if (mAttachInfo == null) { 20679 Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view."); 20680 return false; 20681 } 20682 boolean okay = false; 20683 20684 Point shadowSize = new Point(); 20685 Point shadowTouchPoint = new Point(); 20686 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 20687 20688 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 20689 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 20690 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 20691 } 20692 20693 if (ViewDebug.DEBUG_DRAG) { 20694 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 20695 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 20696 } 20697 if (mAttachInfo.mDragSurface != null) { 20698 mAttachInfo.mDragSurface.release(); 20699 } 20700 mAttachInfo.mDragSurface = new Surface(); 20701 try { 20702 mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 20703 flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface); 20704 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" 20705 + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface); 20706 if (mAttachInfo.mDragToken != null) { 20707 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20708 try { 20709 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20710 shadowBuilder.onDrawShadow(canvas); 20711 } finally { 20712 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20713 } 20714 20715 final ViewRootImpl root = getViewRootImpl(); 20716 20717 // Cache the local state object for delivery with DragEvents 20718 root.setLocalDragState(myLocalState); 20719 20720 // repurpose 'shadowSize' for the last touch point 20721 root.getLastTouchPoint(shadowSize); 20722 20723 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken, 20724 root.getLastTouchSource(), shadowSize.x, shadowSize.y, 20725 shadowTouchPoint.x, shadowTouchPoint.y, data); 20726 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 20727 } 20728 } catch (Exception e) { 20729 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 20730 mAttachInfo.mDragSurface.destroy(); 20731 mAttachInfo.mDragSurface = null; 20732 } 20733 20734 return okay; 20735 } 20736 20737 /** 20738 * Cancels an ongoing drag and drop operation. 20739 * <p> 20740 * A {@link android.view.DragEvent} object with 20741 * {@link android.view.DragEvent#getAction()} value of 20742 * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and 20743 * {@link android.view.DragEvent#getResult()} value of {@code false} 20744 * will be sent to every 20745 * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED} 20746 * even if they are not currently visible. 20747 * </p> 20748 * <p> 20749 * This method can be called on any View in the same window as the View on which 20750 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop} 20751 * was called. 20752 * </p> 20753 */ cancelDragAndDrop()20754 public final void cancelDragAndDrop() { 20755 if (ViewDebug.DEBUG_DRAG) { 20756 Log.d(VIEW_LOG_TAG, "cancelDragAndDrop"); 20757 } 20758 if (mAttachInfo == null) { 20759 Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view."); 20760 return; 20761 } 20762 if (mAttachInfo.mDragToken != null) { 20763 try { 20764 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken); 20765 } catch (Exception e) { 20766 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e); 20767 } 20768 mAttachInfo.mDragToken = null; 20769 } else { 20770 Log.e(VIEW_LOG_TAG, "No active drag to cancel"); 20771 } 20772 } 20773 20774 /** 20775 * Updates the drag shadow for the ongoing drag and drop operation. 20776 * 20777 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 20778 * new drag shadow. 20779 */ updateDragShadow(DragShadowBuilder shadowBuilder)20780 public final void updateDragShadow(DragShadowBuilder shadowBuilder) { 20781 if (ViewDebug.DEBUG_DRAG) { 20782 Log.d(VIEW_LOG_TAG, "updateDragShadow"); 20783 } 20784 if (mAttachInfo == null) { 20785 Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view."); 20786 return; 20787 } 20788 if (mAttachInfo.mDragToken != null) { 20789 try { 20790 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20791 try { 20792 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20793 shadowBuilder.onDrawShadow(canvas); 20794 } finally { 20795 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20796 } 20797 } catch (Exception e) { 20798 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e); 20799 } 20800 } else { 20801 Log.e(VIEW_LOG_TAG, "No active drag"); 20802 } 20803 } 20804 20805 /** 20806 * Starts a move from {startX, startY}, the amount of the movement will be the offset 20807 * between {startX, startY} and the new cursor positon. 20808 * @param startX horizontal coordinate where the move started. 20809 * @param startY vertical coordinate where the move started. 20810 * @return whether moving was started successfully. 20811 * @hide 20812 */ startMovingTask(float startX, float startY)20813 public final boolean startMovingTask(float startX, float startY) { 20814 if (ViewDebug.DEBUG_POSITIONING) { 20815 Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}"); 20816 } 20817 try { 20818 return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY); 20819 } catch (RemoteException e) { 20820 Log.e(VIEW_LOG_TAG, "Unable to start moving", e); 20821 } 20822 return false; 20823 } 20824 20825 /** 20826 * Handles drag events sent by the system following a call to 20827 * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int) 20828 * startDragAndDrop()}. 20829 *<p> 20830 * When the system calls this method, it passes a 20831 * {@link android.view.DragEvent} object. A call to 20832 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 20833 * in DragEvent. The method uses these to determine what is happening in the drag and drop 20834 * operation. 20835 * @param event The {@link android.view.DragEvent} sent by the system. 20836 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 20837 * in DragEvent, indicating the type of drag event represented by this object. 20838 * @return {@code true} if the method was successful, otherwise {@code false}. 20839 * <p> 20840 * The method should return {@code true} in response to an action type of 20841 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 20842 * operation. 20843 * </p> 20844 * <p> 20845 * The method should also return {@code true} in response to an action type of 20846 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 20847 * {@code false} if it didn't. 20848 * </p> 20849 */ onDragEvent(DragEvent event)20850 public boolean onDragEvent(DragEvent event) { 20851 return false; 20852 } 20853 20854 /** 20855 * Detects if this View is enabled and has a drag event listener. 20856 * If both are true, then it calls the drag event listener with the 20857 * {@link android.view.DragEvent} it received. If the drag event listener returns 20858 * {@code true}, then dispatchDragEvent() returns {@code true}. 20859 * <p> 20860 * For all other cases, the method calls the 20861 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 20862 * method and returns its result. 20863 * </p> 20864 * <p> 20865 * This ensures that a drag event is always consumed, even if the View does not have a drag 20866 * event listener. However, if the View has a listener and the listener returns true, then 20867 * onDragEvent() is not called. 20868 * </p> 20869 */ dispatchDragEvent(DragEvent event)20870 public boolean dispatchDragEvent(DragEvent event) { 20871 ListenerInfo li = mListenerInfo; 20872 //noinspection SimplifiableIfStatement 20873 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 20874 && li.mOnDragListener.onDrag(this, event)) { 20875 return true; 20876 } 20877 return onDragEvent(event); 20878 } 20879 canAcceptDrag()20880 boolean canAcceptDrag() { 20881 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 20882 } 20883 20884 /** 20885 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 20886 * it is ever exposed at all. 20887 * @hide 20888 */ onCloseSystemDialogs(String reason)20889 public void onCloseSystemDialogs(String reason) { 20890 } 20891 20892 /** 20893 * Given a Drawable whose bounds have been set to draw into this view, 20894 * update a Region being computed for 20895 * {@link #gatherTransparentRegion(android.graphics.Region)} so 20896 * that any non-transparent parts of the Drawable are removed from the 20897 * given transparent region. 20898 * 20899 * @param dr The Drawable whose transparency is to be applied to the region. 20900 * @param region A Region holding the current transparency information, 20901 * where any parts of the region that are set are considered to be 20902 * transparent. On return, this region will be modified to have the 20903 * transparency information reduced by the corresponding parts of the 20904 * Drawable that are not transparent. 20905 * {@hide} 20906 */ applyDrawableToTransparentRegion(Drawable dr, Region region)20907 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 20908 if (DBG) { 20909 Log.i("View", "Getting transparent region for: " + this); 20910 } 20911 final Region r = dr.getTransparentRegion(); 20912 final Rect db = dr.getBounds(); 20913 final AttachInfo attachInfo = mAttachInfo; 20914 if (r != null && attachInfo != null) { 20915 final int w = getRight()-getLeft(); 20916 final int h = getBottom()-getTop(); 20917 if (db.left > 0) { 20918 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 20919 r.op(0, 0, db.left, h, Region.Op.UNION); 20920 } 20921 if (db.right < w) { 20922 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 20923 r.op(db.right, 0, w, h, Region.Op.UNION); 20924 } 20925 if (db.top > 0) { 20926 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 20927 r.op(0, 0, w, db.top, Region.Op.UNION); 20928 } 20929 if (db.bottom < h) { 20930 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 20931 r.op(0, db.bottom, w, h, Region.Op.UNION); 20932 } 20933 final int[] location = attachInfo.mTransparentLocation; 20934 getLocationInWindow(location); 20935 r.translate(location[0], location[1]); 20936 region.op(r, Region.Op.INTERSECT); 20937 } else { 20938 region.op(db, Region.Op.DIFFERENCE); 20939 } 20940 } 20941 checkForLongClick(int delayOffset, float x, float y)20942 private void checkForLongClick(int delayOffset, float x, float y) { 20943 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 20944 mHasPerformedLongPress = false; 20945 20946 if (mPendingCheckForLongPress == null) { 20947 mPendingCheckForLongPress = new CheckForLongPress(); 20948 } 20949 mPendingCheckForLongPress.setAnchor(x, y); 20950 mPendingCheckForLongPress.rememberWindowAttachCount(); 20951 postDelayed(mPendingCheckForLongPress, 20952 ViewConfiguration.getLongPressTimeout() - delayOffset); 20953 } 20954 } 20955 20956 /** 20957 * Inflate a view from an XML resource. This convenience method wraps the {@link 20958 * LayoutInflater} class, which provides a full range of options for view inflation. 20959 * 20960 * @param context The Context object for your activity or application. 20961 * @param resource The resource ID to inflate 20962 * @param root A view group that will be the parent. Used to properly inflate the 20963 * layout_* parameters. 20964 * @see LayoutInflater 20965 */ inflate(Context context, @LayoutRes int resource, ViewGroup root)20966 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { 20967 LayoutInflater factory = LayoutInflater.from(context); 20968 return factory.inflate(resource, root); 20969 } 20970 20971 /** 20972 * Scroll the view with standard behavior for scrolling beyond the normal 20973 * content boundaries. Views that call this method should override 20974 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 20975 * results of an over-scroll operation. 20976 * 20977 * Views can use this method to handle any touch or fling-based scrolling. 20978 * 20979 * @param deltaX Change in X in pixels 20980 * @param deltaY Change in Y in pixels 20981 * @param scrollX Current X scroll value in pixels before applying deltaX 20982 * @param scrollY Current Y scroll value in pixels before applying deltaY 20983 * @param scrollRangeX Maximum content scroll range along the X axis 20984 * @param scrollRangeY Maximum content scroll range along the Y axis 20985 * @param maxOverScrollX Number of pixels to overscroll by in either direction 20986 * along the X axis. 20987 * @param maxOverScrollY Number of pixels to overscroll by in either direction 20988 * along the Y axis. 20989 * @param isTouchEvent true if this scroll operation is the result of a touch event. 20990 * @return true if scrolling was clamped to an over-scroll boundary along either 20991 * axis, false otherwise. 20992 */ 20993 @SuppressWarnings({"UnusedParameters"}) overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent)20994 protected boolean overScrollBy(int deltaX, int deltaY, 20995 int scrollX, int scrollY, 20996 int scrollRangeX, int scrollRangeY, 20997 int maxOverScrollX, int maxOverScrollY, 20998 boolean isTouchEvent) { 20999 final int overScrollMode = mOverScrollMode; 21000 final boolean canScrollHorizontal = 21001 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 21002 final boolean canScrollVertical = 21003 computeVerticalScrollRange() > computeVerticalScrollExtent(); 21004 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 21005 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 21006 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 21007 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 21008 21009 int newScrollX = scrollX + deltaX; 21010 if (!overScrollHorizontal) { 21011 maxOverScrollX = 0; 21012 } 21013 21014 int newScrollY = scrollY + deltaY; 21015 if (!overScrollVertical) { 21016 maxOverScrollY = 0; 21017 } 21018 21019 // Clamp values if at the limits and record 21020 final int left = -maxOverScrollX; 21021 final int right = maxOverScrollX + scrollRangeX; 21022 final int top = -maxOverScrollY; 21023 final int bottom = maxOverScrollY + scrollRangeY; 21024 21025 boolean clampedX = false; 21026 if (newScrollX > right) { 21027 newScrollX = right; 21028 clampedX = true; 21029 } else if (newScrollX < left) { 21030 newScrollX = left; 21031 clampedX = true; 21032 } 21033 21034 boolean clampedY = false; 21035 if (newScrollY > bottom) { 21036 newScrollY = bottom; 21037 clampedY = true; 21038 } else if (newScrollY < top) { 21039 newScrollY = top; 21040 clampedY = true; 21041 } 21042 21043 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 21044 21045 return clampedX || clampedY; 21046 } 21047 21048 /** 21049 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 21050 * respond to the results of an over-scroll operation. 21051 * 21052 * @param scrollX New X scroll value in pixels 21053 * @param scrollY New Y scroll value in pixels 21054 * @param clampedX True if scrollX was clamped to an over-scroll boundary 21055 * @param clampedY True if scrollY was clamped to an over-scroll boundary 21056 */ onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY)21057 protected void onOverScrolled(int scrollX, int scrollY, 21058 boolean clampedX, boolean clampedY) { 21059 // Intentionally empty. 21060 } 21061 21062 /** 21063 * Returns the over-scroll mode for this view. The result will be 21064 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 21065 * (allow over-scrolling only if the view content is larger than the container), 21066 * or {@link #OVER_SCROLL_NEVER}. 21067 * 21068 * @return This view's over-scroll mode. 21069 */ getOverScrollMode()21070 public int getOverScrollMode() { 21071 return mOverScrollMode; 21072 } 21073 21074 /** 21075 * Set the over-scroll mode for this view. Valid over-scroll modes are 21076 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 21077 * (allow over-scrolling only if the view content is larger than the container), 21078 * or {@link #OVER_SCROLL_NEVER}. 21079 * 21080 * Setting the over-scroll mode of a view will have an effect only if the 21081 * view is capable of scrolling. 21082 * 21083 * @param overScrollMode The new over-scroll mode for this view. 21084 */ setOverScrollMode(int overScrollMode)21085 public void setOverScrollMode(int overScrollMode) { 21086 if (overScrollMode != OVER_SCROLL_ALWAYS && 21087 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 21088 overScrollMode != OVER_SCROLL_NEVER) { 21089 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 21090 } 21091 mOverScrollMode = overScrollMode; 21092 } 21093 21094 /** 21095 * Enable or disable nested scrolling for this view. 21096 * 21097 * <p>If this property is set to true the view will be permitted to initiate nested 21098 * scrolling operations with a compatible parent view in the current hierarchy. If this 21099 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling 21100 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping} 21101 * the nested scroll.</p> 21102 * 21103 * @param enabled true to enable nested scrolling, false to disable 21104 * 21105 * @see #isNestedScrollingEnabled() 21106 */ setNestedScrollingEnabled(boolean enabled)21107 public void setNestedScrollingEnabled(boolean enabled) { 21108 if (enabled) { 21109 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED; 21110 } else { 21111 stopNestedScroll(); 21112 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED; 21113 } 21114 } 21115 21116 /** 21117 * Returns true if nested scrolling is enabled for this view. 21118 * 21119 * <p>If nested scrolling is enabled and this View class implementation supports it, 21120 * this view will act as a nested scrolling child view when applicable, forwarding data 21121 * about the scroll operation in progress to a compatible and cooperating nested scrolling 21122 * parent.</p> 21123 * 21124 * @return true if nested scrolling is enabled 21125 * 21126 * @see #setNestedScrollingEnabled(boolean) 21127 */ isNestedScrollingEnabled()21128 public boolean isNestedScrollingEnabled() { 21129 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) == 21130 PFLAG3_NESTED_SCROLLING_ENABLED; 21131 } 21132 21133 /** 21134 * Begin a nestable scroll operation along the given axes. 21135 * 21136 * <p>A view starting a nested scroll promises to abide by the following contract:</p> 21137 * 21138 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case 21139 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}. 21140 * In the case of touch scrolling the nested scroll will be terminated automatically in 21141 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}. 21142 * In the event of programmatic scrolling the caller must explicitly call 21143 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p> 21144 * 21145 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found. 21146 * If it returns false the caller may ignore the rest of this contract until the next scroll. 21147 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p> 21148 * 21149 * <p>At each incremental step of the scroll the caller should invoke 21150 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} 21151 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling 21152 * parent at least partially consumed the scroll and the caller should adjust the amount it 21153 * scrolls by.</p> 21154 * 21155 * <p>After applying the remainder of the scroll delta the caller should invoke 21156 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing 21157 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat 21158 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}. 21159 * </p> 21160 * 21161 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or 21162 * {@link #SCROLL_AXIS_VERTICAL}. 21163 * @return true if a cooperative parent was found and nested scrolling has been enabled for 21164 * the current gesture. 21165 * 21166 * @see #stopNestedScroll() 21167 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 21168 * @see #dispatchNestedScroll(int, int, int, int, int[]) 21169 */ startNestedScroll(int axes)21170 public boolean startNestedScroll(int axes) { 21171 if (hasNestedScrollingParent()) { 21172 // Already in progress 21173 return true; 21174 } 21175 if (isNestedScrollingEnabled()) { 21176 ViewParent p = getParent(); 21177 View child = this; 21178 while (p != null) { 21179 try { 21180 if (p.onStartNestedScroll(child, this, axes)) { 21181 mNestedScrollingParent = p; 21182 p.onNestedScrollAccepted(child, this, axes); 21183 return true; 21184 } 21185 } catch (AbstractMethodError e) { 21186 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " + 21187 "method onStartNestedScroll", e); 21188 // Allow the search upward to continue 21189 } 21190 if (p instanceof View) { 21191 child = (View) p; 21192 } 21193 p = p.getParent(); 21194 } 21195 } 21196 return false; 21197 } 21198 21199 /** 21200 * Stop a nested scroll in progress. 21201 * 21202 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p> 21203 * 21204 * @see #startNestedScroll(int) 21205 */ stopNestedScroll()21206 public void stopNestedScroll() { 21207 if (mNestedScrollingParent != null) { 21208 mNestedScrollingParent.onStopNestedScroll(this); 21209 mNestedScrollingParent = null; 21210 } 21211 } 21212 21213 /** 21214 * Returns true if this view has a nested scrolling parent. 21215 * 21216 * <p>The presence of a nested scrolling parent indicates that this view has initiated 21217 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p> 21218 * 21219 * @return whether this view has a nested scrolling parent 21220 */ hasNestedScrollingParent()21221 public boolean hasNestedScrollingParent() { 21222 return mNestedScrollingParent != null; 21223 } 21224 21225 /** 21226 * Dispatch one step of a nested scroll in progress. 21227 * 21228 * <p>Implementations of views that support nested scrolling should call this to report 21229 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll 21230 * is not currently in progress or nested scrolling is not 21231 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p> 21232 * 21233 * <p>Compatible View implementations should also call 21234 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before 21235 * consuming a component of the scroll event themselves.</p> 21236 * 21237 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step 21238 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step 21239 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view 21240 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view 21241 * @param offsetInWindow Optional. If not null, on return this will contain the offset 21242 * in local view coordinates of this view from before this operation 21243 * to after it completes. View implementations may use this to adjust 21244 * expected input coordinate tracking. 21245 * @return true if the event was dispatched, false if it could not be dispatched. 21246 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 21247 */ dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow)21248 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 21249 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) { 21250 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21251 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 21252 int startX = 0; 21253 int startY = 0; 21254 if (offsetInWindow != null) { 21255 getLocationInWindow(offsetInWindow); 21256 startX = offsetInWindow[0]; 21257 startY = offsetInWindow[1]; 21258 } 21259 21260 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed, 21261 dxUnconsumed, dyUnconsumed); 21262 21263 if (offsetInWindow != null) { 21264 getLocationInWindow(offsetInWindow); 21265 offsetInWindow[0] -= startX; 21266 offsetInWindow[1] -= startY; 21267 } 21268 return true; 21269 } else if (offsetInWindow != null) { 21270 // No motion, no dispatch. Keep offsetInWindow up to date. 21271 offsetInWindow[0] = 0; 21272 offsetInWindow[1] = 0; 21273 } 21274 } 21275 return false; 21276 } 21277 21278 /** 21279 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it. 21280 * 21281 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch. 21282 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested 21283 * scrolling operation to consume some or all of the scroll operation before the child view 21284 * consumes it.</p> 21285 * 21286 * @param dx Horizontal scroll distance in pixels 21287 * @param dy Vertical scroll distance in pixels 21288 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx 21289 * and consumed[1] the consumed dy. 21290 * @param offsetInWindow Optional. If not null, on return this will contain the offset 21291 * in local view coordinates of this view from before this operation 21292 * to after it completes. View implementations may use this to adjust 21293 * expected input coordinate tracking. 21294 * @return true if the parent consumed some or all of the scroll delta 21295 * @see #dispatchNestedScroll(int, int, int, int, int[]) 21296 */ dispatchNestedPreScroll(int dx, int dy, @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow)21297 public boolean dispatchNestedPreScroll(int dx, int dy, 21298 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) { 21299 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21300 if (dx != 0 || dy != 0) { 21301 int startX = 0; 21302 int startY = 0; 21303 if (offsetInWindow != null) { 21304 getLocationInWindow(offsetInWindow); 21305 startX = offsetInWindow[0]; 21306 startY = offsetInWindow[1]; 21307 } 21308 21309 if (consumed == null) { 21310 if (mTempNestedScrollConsumed == null) { 21311 mTempNestedScrollConsumed = new int[2]; 21312 } 21313 consumed = mTempNestedScrollConsumed; 21314 } 21315 consumed[0] = 0; 21316 consumed[1] = 0; 21317 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed); 21318 21319 if (offsetInWindow != null) { 21320 getLocationInWindow(offsetInWindow); 21321 offsetInWindow[0] -= startX; 21322 offsetInWindow[1] -= startY; 21323 } 21324 return consumed[0] != 0 || consumed[1] != 0; 21325 } else if (offsetInWindow != null) { 21326 offsetInWindow[0] = 0; 21327 offsetInWindow[1] = 0; 21328 } 21329 } 21330 return false; 21331 } 21332 21333 /** 21334 * Dispatch a fling to a nested scrolling parent. 21335 * 21336 * <p>This method should be used to indicate that a nested scrolling child has detected 21337 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a 21338 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 21339 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 21340 * along a scrollable axis.</p> 21341 * 21342 * <p>If a nested scrolling child view would normally fling but it is at the edge of 21343 * its own content, it can use this method to delegate the fling to its nested scrolling 21344 * parent instead. The parent may optionally consume the fling or observe a child fling.</p> 21345 * 21346 * @param velocityX Horizontal fling velocity in pixels per second 21347 * @param velocityY Vertical fling velocity in pixels per second 21348 * @param consumed true if the child consumed the fling, false otherwise 21349 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling 21350 */ dispatchNestedFling(float velocityX, float velocityY, boolean consumed)21351 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 21352 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21353 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed); 21354 } 21355 return false; 21356 } 21357 21358 /** 21359 * Dispatch a fling to a nested scrolling parent before it is processed by this view. 21360 * 21361 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch 21362 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code> 21363 * offsets an opportunity for the parent view in a nested fling to fully consume the fling 21364 * before the child view consumes it. If this method returns <code>true</code>, a nested 21365 * parent view consumed the fling and this view should not scroll as a result.</p> 21366 * 21367 * <p>For a better user experience, only one view in a nested scrolling chain should consume 21368 * the fling at a time. If a parent view consumed the fling this method will return false. 21369 * Custom view implementations should account for this in two ways:</p> 21370 * 21371 * <ul> 21372 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not 21373 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid 21374 * position regardless.</li> 21375 * <li>If a nested parent does consume the fling, this view should not scroll at all, 21376 * even to settle back to a valid idle position.</li> 21377 * </ul> 21378 * 21379 * <p>Views should also not offer fling velocities to nested parent views along an axis 21380 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView} 21381 * should not offer a horizontal fling velocity to its parents since scrolling along that 21382 * axis is not permitted and carrying velocity along that motion does not make sense.</p> 21383 * 21384 * @param velocityX Horizontal fling velocity in pixels per second 21385 * @param velocityY Vertical fling velocity in pixels per second 21386 * @return true if a nested scrolling parent consumed the fling 21387 */ dispatchNestedPreFling(float velocityX, float velocityY)21388 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 21389 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 21390 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY); 21391 } 21392 return false; 21393 } 21394 21395 /** 21396 * Gets a scale factor that determines the distance the view should scroll 21397 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 21398 * @return The vertical scroll scale factor. 21399 * @hide 21400 */ getVerticalScrollFactor()21401 protected float getVerticalScrollFactor() { 21402 if (mVerticalScrollFactor == 0) { 21403 TypedValue outValue = new TypedValue(); 21404 if (!mContext.getTheme().resolveAttribute( 21405 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 21406 throw new IllegalStateException( 21407 "Expected theme to define listPreferredItemHeight."); 21408 } 21409 mVerticalScrollFactor = outValue.getDimension( 21410 mContext.getResources().getDisplayMetrics()); 21411 } 21412 return mVerticalScrollFactor; 21413 } 21414 21415 /** 21416 * Gets a scale factor that determines the distance the view should scroll 21417 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 21418 * @return The horizontal scroll scale factor. 21419 * @hide 21420 */ getHorizontalScrollFactor()21421 protected float getHorizontalScrollFactor() { 21422 // TODO: Should use something else. 21423 return getVerticalScrollFactor(); 21424 } 21425 21426 /** 21427 * Return the value specifying the text direction or policy that was set with 21428 * {@link #setTextDirection(int)}. 21429 * 21430 * @return the defined text direction. It can be one of: 21431 * 21432 * {@link #TEXT_DIRECTION_INHERIT}, 21433 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21434 * {@link #TEXT_DIRECTION_ANY_RTL}, 21435 * {@link #TEXT_DIRECTION_LTR}, 21436 * {@link #TEXT_DIRECTION_RTL}, 21437 * {@link #TEXT_DIRECTION_LOCALE}, 21438 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21439 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 21440 * 21441 * @attr ref android.R.styleable#View_textDirection 21442 * 21443 * @hide 21444 */ 21445 @ViewDebug.ExportedProperty(category = "text", mapping = { 21446 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 21447 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 21448 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 21449 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 21450 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 21451 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 21452 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 21453 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 21454 }) getRawTextDirection()21455 public int getRawTextDirection() { 21456 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 21457 } 21458 21459 /** 21460 * Set the text direction. 21461 * 21462 * @param textDirection the direction to set. Should be one of: 21463 * 21464 * {@link #TEXT_DIRECTION_INHERIT}, 21465 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21466 * {@link #TEXT_DIRECTION_ANY_RTL}, 21467 * {@link #TEXT_DIRECTION_LTR}, 21468 * {@link #TEXT_DIRECTION_RTL}, 21469 * {@link #TEXT_DIRECTION_LOCALE} 21470 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21471 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}, 21472 * 21473 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 21474 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 21475 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 21476 * 21477 * @attr ref android.R.styleable#View_textDirection 21478 */ setTextDirection(int textDirection)21479 public void setTextDirection(int textDirection) { 21480 if (getRawTextDirection() != textDirection) { 21481 // Reset the current text direction and the resolved one 21482 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 21483 resetResolvedTextDirection(); 21484 // Set the new text direction 21485 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 21486 // Do resolution 21487 resolveTextDirection(); 21488 // Notify change 21489 onRtlPropertiesChanged(getLayoutDirection()); 21490 // Refresh 21491 requestLayout(); 21492 invalidate(true); 21493 } 21494 } 21495 21496 /** 21497 * Return the resolved text direction. 21498 * 21499 * @return the resolved text direction. Returns one of: 21500 * 21501 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 21502 * {@link #TEXT_DIRECTION_ANY_RTL}, 21503 * {@link #TEXT_DIRECTION_LTR}, 21504 * {@link #TEXT_DIRECTION_RTL}, 21505 * {@link #TEXT_DIRECTION_LOCALE}, 21506 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 21507 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 21508 * 21509 * @attr ref android.R.styleable#View_textDirection 21510 */ 21511 @ViewDebug.ExportedProperty(category = "text", mapping = { 21512 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 21513 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 21514 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 21515 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 21516 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 21517 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 21518 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 21519 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 21520 }) getTextDirection()21521 public int getTextDirection() { 21522 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 21523 } 21524 21525 /** 21526 * Resolve the text direction. 21527 * 21528 * @return true if resolution has been done, false otherwise. 21529 * 21530 * @hide 21531 */ resolveTextDirection()21532 public boolean resolveTextDirection() { 21533 // Reset any previous text direction resolution 21534 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 21535 21536 if (hasRtlSupport()) { 21537 // Set resolved text direction flag depending on text direction flag 21538 final int textDirection = getRawTextDirection(); 21539 switch(textDirection) { 21540 case TEXT_DIRECTION_INHERIT: 21541 if (!canResolveTextDirection()) { 21542 // We cannot do the resolution if there is no parent, so use the default one 21543 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21544 // Resolution will need to happen again later 21545 return false; 21546 } 21547 21548 // Parent has not yet resolved, so we still return the default 21549 try { 21550 if (!mParent.isTextDirectionResolved()) { 21551 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21552 // Resolution will need to happen again later 21553 return false; 21554 } 21555 } catch (AbstractMethodError e) { 21556 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21557 " does not fully implement ViewParent", e); 21558 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 21559 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21560 return true; 21561 } 21562 21563 // Set current resolved direction to the same value as the parent's one 21564 int parentResolvedDirection; 21565 try { 21566 parentResolvedDirection = mParent.getTextDirection(); 21567 } catch (AbstractMethodError e) { 21568 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21569 " does not fully implement ViewParent", e); 21570 parentResolvedDirection = TEXT_DIRECTION_LTR; 21571 } 21572 switch (parentResolvedDirection) { 21573 case TEXT_DIRECTION_FIRST_STRONG: 21574 case TEXT_DIRECTION_ANY_RTL: 21575 case TEXT_DIRECTION_LTR: 21576 case TEXT_DIRECTION_RTL: 21577 case TEXT_DIRECTION_LOCALE: 21578 case TEXT_DIRECTION_FIRST_STRONG_LTR: 21579 case TEXT_DIRECTION_FIRST_STRONG_RTL: 21580 mPrivateFlags2 |= 21581 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 21582 break; 21583 default: 21584 // Default resolved direction is "first strong" heuristic 21585 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21586 } 21587 break; 21588 case TEXT_DIRECTION_FIRST_STRONG: 21589 case TEXT_DIRECTION_ANY_RTL: 21590 case TEXT_DIRECTION_LTR: 21591 case TEXT_DIRECTION_RTL: 21592 case TEXT_DIRECTION_LOCALE: 21593 case TEXT_DIRECTION_FIRST_STRONG_LTR: 21594 case TEXT_DIRECTION_FIRST_STRONG_RTL: 21595 // Resolved direction is the same as text direction 21596 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 21597 break; 21598 default: 21599 // Default resolved direction is "first strong" heuristic 21600 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21601 } 21602 } else { 21603 // Default resolved direction is "first strong" heuristic 21604 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21605 } 21606 21607 // Set to resolved 21608 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 21609 return true; 21610 } 21611 21612 /** 21613 * Check if text direction resolution can be done. 21614 * 21615 * @return true if text direction resolution can be done otherwise return false. 21616 */ canResolveTextDirection()21617 public boolean canResolveTextDirection() { 21618 switch (getRawTextDirection()) { 21619 case TEXT_DIRECTION_INHERIT: 21620 if (mParent != null) { 21621 try { 21622 return mParent.canResolveTextDirection(); 21623 } catch (AbstractMethodError e) { 21624 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21625 " does not fully implement ViewParent", e); 21626 } 21627 } 21628 return false; 21629 21630 default: 21631 return true; 21632 } 21633 } 21634 21635 /** 21636 * Reset resolved text direction. Text direction will be resolved during a call to 21637 * {@link #onMeasure(int, int)}. 21638 * 21639 * @hide 21640 */ resetResolvedTextDirection()21641 public void resetResolvedTextDirection() { 21642 // Reset any previous text direction resolution 21643 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 21644 // Set to default value 21645 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 21646 } 21647 21648 /** 21649 * @return true if text direction is inherited. 21650 * 21651 * @hide 21652 */ isTextDirectionInherited()21653 public boolean isTextDirectionInherited() { 21654 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 21655 } 21656 21657 /** 21658 * @return true if text direction is resolved. 21659 */ isTextDirectionResolved()21660 public boolean isTextDirectionResolved() { 21661 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 21662 } 21663 21664 /** 21665 * Return the value specifying the text alignment or policy that was set with 21666 * {@link #setTextAlignment(int)}. 21667 * 21668 * @return the defined text alignment. It can be one of: 21669 * 21670 * {@link #TEXT_ALIGNMENT_INHERIT}, 21671 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21672 * {@link #TEXT_ALIGNMENT_CENTER}, 21673 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21674 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21675 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21676 * {@link #TEXT_ALIGNMENT_VIEW_END} 21677 * 21678 * @attr ref android.R.styleable#View_textAlignment 21679 * 21680 * @hide 21681 */ 21682 @ViewDebug.ExportedProperty(category = "text", mapping = { 21683 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 21684 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 21685 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 21686 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 21687 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 21688 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 21689 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21690 }) 21691 @TextAlignment getRawTextAlignment()21692 public int getRawTextAlignment() { 21693 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 21694 } 21695 21696 /** 21697 * Set the text alignment. 21698 * 21699 * @param textAlignment The text alignment to set. Should be one of 21700 * 21701 * {@link #TEXT_ALIGNMENT_INHERIT}, 21702 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21703 * {@link #TEXT_ALIGNMENT_CENTER}, 21704 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21705 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21706 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21707 * {@link #TEXT_ALIGNMENT_VIEW_END} 21708 * 21709 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 21710 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 21711 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 21712 * 21713 * @attr ref android.R.styleable#View_textAlignment 21714 */ setTextAlignment(@extAlignment int textAlignment)21715 public void setTextAlignment(@TextAlignment int textAlignment) { 21716 if (textAlignment != getRawTextAlignment()) { 21717 // Reset the current and resolved text alignment 21718 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 21719 resetResolvedTextAlignment(); 21720 // Set the new text alignment 21721 mPrivateFlags2 |= 21722 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 21723 // Do resolution 21724 resolveTextAlignment(); 21725 // Notify change 21726 onRtlPropertiesChanged(getLayoutDirection()); 21727 // Refresh 21728 requestLayout(); 21729 invalidate(true); 21730 } 21731 } 21732 21733 /** 21734 * Return the resolved text alignment. 21735 * 21736 * @return the resolved text alignment. Returns one of: 21737 * 21738 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21739 * {@link #TEXT_ALIGNMENT_CENTER}, 21740 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21741 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21742 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21743 * {@link #TEXT_ALIGNMENT_VIEW_END} 21744 * 21745 * @attr ref android.R.styleable#View_textAlignment 21746 */ 21747 @ViewDebug.ExportedProperty(category = "text", mapping = { 21748 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 21749 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 21750 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 21751 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 21752 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 21753 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 21754 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21755 }) 21756 @TextAlignment getTextAlignment()21757 public int getTextAlignment() { 21758 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 21759 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 21760 } 21761 21762 /** 21763 * Resolve the text alignment. 21764 * 21765 * @return true if resolution has been done, false otherwise. 21766 * 21767 * @hide 21768 */ resolveTextAlignment()21769 public boolean resolveTextAlignment() { 21770 // Reset any previous text alignment resolution 21771 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21772 21773 if (hasRtlSupport()) { 21774 // Set resolved text alignment flag depending on text alignment flag 21775 final int textAlignment = getRawTextAlignment(); 21776 switch (textAlignment) { 21777 case TEXT_ALIGNMENT_INHERIT: 21778 // Check if we can resolve the text alignment 21779 if (!canResolveTextAlignment()) { 21780 // We cannot do the resolution if there is no parent so use the default 21781 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21782 // Resolution will need to happen again later 21783 return false; 21784 } 21785 21786 // Parent has not yet resolved, so we still return the default 21787 try { 21788 if (!mParent.isTextAlignmentResolved()) { 21789 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21790 // Resolution will need to happen again later 21791 return false; 21792 } 21793 } catch (AbstractMethodError e) { 21794 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21795 " does not fully implement ViewParent", e); 21796 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 21797 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21798 return true; 21799 } 21800 21801 int parentResolvedTextAlignment; 21802 try { 21803 parentResolvedTextAlignment = mParent.getTextAlignment(); 21804 } catch (AbstractMethodError e) { 21805 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21806 " does not fully implement ViewParent", e); 21807 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 21808 } 21809 switch (parentResolvedTextAlignment) { 21810 case TEXT_ALIGNMENT_GRAVITY: 21811 case TEXT_ALIGNMENT_TEXT_START: 21812 case TEXT_ALIGNMENT_TEXT_END: 21813 case TEXT_ALIGNMENT_CENTER: 21814 case TEXT_ALIGNMENT_VIEW_START: 21815 case TEXT_ALIGNMENT_VIEW_END: 21816 // Resolved text alignment is the same as the parent resolved 21817 // text alignment 21818 mPrivateFlags2 |= 21819 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21820 break; 21821 default: 21822 // Use default resolved text alignment 21823 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21824 } 21825 break; 21826 case TEXT_ALIGNMENT_GRAVITY: 21827 case TEXT_ALIGNMENT_TEXT_START: 21828 case TEXT_ALIGNMENT_TEXT_END: 21829 case TEXT_ALIGNMENT_CENTER: 21830 case TEXT_ALIGNMENT_VIEW_START: 21831 case TEXT_ALIGNMENT_VIEW_END: 21832 // Resolved text alignment is the same as text alignment 21833 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21834 break; 21835 default: 21836 // Use default resolved text alignment 21837 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21838 } 21839 } else { 21840 // Use default resolved text alignment 21841 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21842 } 21843 21844 // Set the resolved 21845 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21846 return true; 21847 } 21848 21849 /** 21850 * Check if text alignment resolution can be done. 21851 * 21852 * @return true if text alignment resolution can be done otherwise return false. 21853 */ canResolveTextAlignment()21854 public boolean canResolveTextAlignment() { 21855 switch (getRawTextAlignment()) { 21856 case TEXT_DIRECTION_INHERIT: 21857 if (mParent != null) { 21858 try { 21859 return mParent.canResolveTextAlignment(); 21860 } catch (AbstractMethodError e) { 21861 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21862 " does not fully implement ViewParent", e); 21863 } 21864 } 21865 return false; 21866 21867 default: 21868 return true; 21869 } 21870 } 21871 21872 /** 21873 * Reset resolved text alignment. Text alignment will be resolved during a call to 21874 * {@link #onMeasure(int, int)}. 21875 * 21876 * @hide 21877 */ resetResolvedTextAlignment()21878 public void resetResolvedTextAlignment() { 21879 // Reset any previous text alignment resolution 21880 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21881 // Set to default 21882 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21883 } 21884 21885 /** 21886 * @return true if text alignment is inherited. 21887 * 21888 * @hide 21889 */ isTextAlignmentInherited()21890 public boolean isTextAlignmentInherited() { 21891 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 21892 } 21893 21894 /** 21895 * @return true if text alignment is resolved. 21896 */ isTextAlignmentResolved()21897 public boolean isTextAlignmentResolved() { 21898 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21899 } 21900 21901 /** 21902 * Generate a value suitable for use in {@link #setId(int)}. 21903 * This value will not collide with ID values generated at build time by aapt for R.id. 21904 * 21905 * @return a generated ID value 21906 */ generateViewId()21907 public static int generateViewId() { 21908 for (;;) { 21909 final int result = sNextGeneratedId.get(); 21910 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 21911 int newValue = result + 1; 21912 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 21913 if (sNextGeneratedId.compareAndSet(result, newValue)) { 21914 return result; 21915 } 21916 } 21917 } 21918 21919 /** 21920 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. 21921 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and 21922 * a normal View or a ViewGroup with 21923 * {@link android.view.ViewGroup#isTransitionGroup()} true. 21924 * @hide 21925 */ captureTransitioningViews(List<View> transitioningViews)21926 public void captureTransitioningViews(List<View> transitioningViews) { 21927 if (getVisibility() == View.VISIBLE) { 21928 transitioningViews.add(this); 21929 } 21930 } 21931 21932 /** 21933 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements. 21934 * @param namedElements Will contain all Views in the hierarchy having a transitionName. 21935 * @hide 21936 */ findNamedViews(Map<String, View> namedElements)21937 public void findNamedViews(Map<String, View> namedElements) { 21938 if (getVisibility() == VISIBLE || mGhostView != null) { 21939 String transitionName = getTransitionName(); 21940 if (transitionName != null) { 21941 namedElements.put(transitionName, this); 21942 } 21943 } 21944 } 21945 21946 /** 21947 * Returns the pointer icon for the motion event, or null if it doesn't specify the icon. 21948 * The default implementation does not care the location or event types, but some subclasses 21949 * may use it (such as WebViews). 21950 * @param event The MotionEvent from a mouse 21951 * @param pointerIndex The index of the pointer for which to retrieve the {@link PointerIcon}. 21952 * This will be between 0 and {@link MotionEvent#getPointerCount()}. 21953 * @see PointerIcon 21954 */ onResolvePointerIcon(MotionEvent event, int pointerIndex)21955 public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) { 21956 final float x = event.getX(pointerIndex); 21957 final float y = event.getY(pointerIndex); 21958 if (isDraggingScrollBar() || isOnScrollbarThumb(x, y)) { 21959 return PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW); 21960 } 21961 return mPointerIcon; 21962 } 21963 21964 /** 21965 * Set the pointer icon for the current view. 21966 * Passing {@code null} will restore the pointer icon to its default value. 21967 * @param pointerIcon A PointerIcon instance which will be shown when the mouse hovers. 21968 */ setPointerIcon(PointerIcon pointerIcon)21969 public void setPointerIcon(PointerIcon pointerIcon) { 21970 mPointerIcon = pointerIcon; 21971 if (mAttachInfo == null || mAttachInfo.mHandlingPointerEvent) { 21972 return; 21973 } 21974 try { 21975 mAttachInfo.mSession.updatePointerIcon(mAttachInfo.mWindow); 21976 } catch (RemoteException e) { 21977 } 21978 } 21979 21980 /** 21981 * Gets the pointer icon for the current view. 21982 */ getPointerIcon()21983 public PointerIcon getPointerIcon() { 21984 return mPointerIcon; 21985 } 21986 21987 // 21988 // Properties 21989 // 21990 /** 21991 * A Property wrapper around the <code>alpha</code> functionality handled by the 21992 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 21993 */ 21994 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 21995 @Override 21996 public void setValue(View object, float value) { 21997 object.setAlpha(value); 21998 } 21999 22000 @Override 22001 public Float get(View object) { 22002 return object.getAlpha(); 22003 } 22004 }; 22005 22006 /** 22007 * A Property wrapper around the <code>translationX</code> functionality handled by the 22008 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 22009 */ 22010 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 22011 @Override 22012 public void setValue(View object, float value) { 22013 object.setTranslationX(value); 22014 } 22015 22016 @Override 22017 public Float get(View object) { 22018 return object.getTranslationX(); 22019 } 22020 }; 22021 22022 /** 22023 * A Property wrapper around the <code>translationY</code> functionality handled by the 22024 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 22025 */ 22026 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 22027 @Override 22028 public void setValue(View object, float value) { 22029 object.setTranslationY(value); 22030 } 22031 22032 @Override 22033 public Float get(View object) { 22034 return object.getTranslationY(); 22035 } 22036 }; 22037 22038 /** 22039 * A Property wrapper around the <code>translationZ</code> functionality handled by the 22040 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods. 22041 */ 22042 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") { 22043 @Override 22044 public void setValue(View object, float value) { 22045 object.setTranslationZ(value); 22046 } 22047 22048 @Override 22049 public Float get(View object) { 22050 return object.getTranslationZ(); 22051 } 22052 }; 22053 22054 /** 22055 * A Property wrapper around the <code>x</code> functionality handled by the 22056 * {@link View#setX(float)} and {@link View#getX()} methods. 22057 */ 22058 public static final Property<View, Float> X = new FloatProperty<View>("x") { 22059 @Override 22060 public void setValue(View object, float value) { 22061 object.setX(value); 22062 } 22063 22064 @Override 22065 public Float get(View object) { 22066 return object.getX(); 22067 } 22068 }; 22069 22070 /** 22071 * A Property wrapper around the <code>y</code> functionality handled by the 22072 * {@link View#setY(float)} and {@link View#getY()} methods. 22073 */ 22074 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 22075 @Override 22076 public void setValue(View object, float value) { 22077 object.setY(value); 22078 } 22079 22080 @Override 22081 public Float get(View object) { 22082 return object.getY(); 22083 } 22084 }; 22085 22086 /** 22087 * A Property wrapper around the <code>z</code> functionality handled by the 22088 * {@link View#setZ(float)} and {@link View#getZ()} methods. 22089 */ 22090 public static final Property<View, Float> Z = new FloatProperty<View>("z") { 22091 @Override 22092 public void setValue(View object, float value) { 22093 object.setZ(value); 22094 } 22095 22096 @Override 22097 public Float get(View object) { 22098 return object.getZ(); 22099 } 22100 }; 22101 22102 /** 22103 * A Property wrapper around the <code>rotation</code> functionality handled by the 22104 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 22105 */ 22106 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 22107 @Override 22108 public void setValue(View object, float value) { 22109 object.setRotation(value); 22110 } 22111 22112 @Override 22113 public Float get(View object) { 22114 return object.getRotation(); 22115 } 22116 }; 22117 22118 /** 22119 * A Property wrapper around the <code>rotationX</code> functionality handled by the 22120 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 22121 */ 22122 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 22123 @Override 22124 public void setValue(View object, float value) { 22125 object.setRotationX(value); 22126 } 22127 22128 @Override 22129 public Float get(View object) { 22130 return object.getRotationX(); 22131 } 22132 }; 22133 22134 /** 22135 * A Property wrapper around the <code>rotationY</code> functionality handled by the 22136 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 22137 */ 22138 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 22139 @Override 22140 public void setValue(View object, float value) { 22141 object.setRotationY(value); 22142 } 22143 22144 @Override 22145 public Float get(View object) { 22146 return object.getRotationY(); 22147 } 22148 }; 22149 22150 /** 22151 * A Property wrapper around the <code>scaleX</code> functionality handled by the 22152 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 22153 */ 22154 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 22155 @Override 22156 public void setValue(View object, float value) { 22157 object.setScaleX(value); 22158 } 22159 22160 @Override 22161 public Float get(View object) { 22162 return object.getScaleX(); 22163 } 22164 }; 22165 22166 /** 22167 * A Property wrapper around the <code>scaleY</code> functionality handled by the 22168 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 22169 */ 22170 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 22171 @Override 22172 public void setValue(View object, float value) { 22173 object.setScaleY(value); 22174 } 22175 22176 @Override 22177 public Float get(View object) { 22178 return object.getScaleY(); 22179 } 22180 }; 22181 22182 /** 22183 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 22184 * Each MeasureSpec represents a requirement for either the width or the height. 22185 * A MeasureSpec is comprised of a size and a mode. There are three possible 22186 * modes: 22187 * <dl> 22188 * <dt>UNSPECIFIED</dt> 22189 * <dd> 22190 * The parent has not imposed any constraint on the child. It can be whatever size 22191 * it wants. 22192 * </dd> 22193 * 22194 * <dt>EXACTLY</dt> 22195 * <dd> 22196 * The parent has determined an exact size for the child. The child is going to be 22197 * given those bounds regardless of how big it wants to be. 22198 * </dd> 22199 * 22200 * <dt>AT_MOST</dt> 22201 * <dd> 22202 * The child can be as large as it wants up to the specified size. 22203 * </dd> 22204 * </dl> 22205 * 22206 * MeasureSpecs are implemented as ints to reduce object allocation. This class 22207 * is provided to pack and unpack the <size, mode> tuple into the int. 22208 */ 22209 public static class MeasureSpec { 22210 private static final int MODE_SHIFT = 30; 22211 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 22212 22213 /** @hide */ 22214 @IntDef({UNSPECIFIED, EXACTLY, AT_MOST}) 22215 @Retention(RetentionPolicy.SOURCE) 22216 public @interface MeasureSpecMode {} 22217 22218 /** 22219 * Measure specification mode: The parent has not imposed any constraint 22220 * on the child. It can be whatever size it wants. 22221 */ 22222 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 22223 22224 /** 22225 * Measure specification mode: The parent has determined an exact size 22226 * for the child. The child is going to be given those bounds regardless 22227 * of how big it wants to be. 22228 */ 22229 public static final int EXACTLY = 1 << MODE_SHIFT; 22230 22231 /** 22232 * Measure specification mode: The child can be as large as it wants up 22233 * to the specified size. 22234 */ 22235 public static final int AT_MOST = 2 << MODE_SHIFT; 22236 22237 /** 22238 * Creates a measure specification based on the supplied size and mode. 22239 * 22240 * The mode must always be one of the following: 22241 * <ul> 22242 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 22243 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 22244 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 22245 * </ul> 22246 * 22247 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 22248 * implementation was such that the order of arguments did not matter 22249 * and overflow in either value could impact the resulting MeasureSpec. 22250 * {@link android.widget.RelativeLayout} was affected by this bug. 22251 * Apps targeting API levels greater than 17 will get the fixed, more strict 22252 * behavior.</p> 22253 * 22254 * @param size the size of the measure specification 22255 * @param mode the mode of the measure specification 22256 * @return the measure specification based on size and mode 22257 */ makeMeasureSpec(@ntRangefrom = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode)22258 public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, 22259 @MeasureSpecMode int mode) { 22260 if (sUseBrokenMakeMeasureSpec) { 22261 return size + mode; 22262 } else { 22263 return (size & ~MODE_MASK) | (mode & MODE_MASK); 22264 } 22265 } 22266 22267 /** 22268 * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED 22269 * will automatically get a size of 0. Older apps expect this. 22270 * 22271 * @hide internal use only for compatibility with system widgets and older apps 22272 */ makeSafeMeasureSpec(int size, int mode)22273 public static int makeSafeMeasureSpec(int size, int mode) { 22274 if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) { 22275 return 0; 22276 } 22277 return makeMeasureSpec(size, mode); 22278 } 22279 22280 /** 22281 * Extracts the mode from the supplied measure specification. 22282 * 22283 * @param measureSpec the measure specification to extract the mode from 22284 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 22285 * {@link android.view.View.MeasureSpec#AT_MOST} or 22286 * {@link android.view.View.MeasureSpec#EXACTLY} 22287 */ 22288 @MeasureSpecMode getMode(int measureSpec)22289 public static int getMode(int measureSpec) { 22290 //noinspection ResourceType 22291 return (measureSpec & MODE_MASK); 22292 } 22293 22294 /** 22295 * Extracts the size from the supplied measure specification. 22296 * 22297 * @param measureSpec the measure specification to extract the size from 22298 * @return the size in pixels defined in the supplied measure specification 22299 */ getSize(int measureSpec)22300 public static int getSize(int measureSpec) { 22301 return (measureSpec & ~MODE_MASK); 22302 } 22303 adjust(int measureSpec, int delta)22304 static int adjust(int measureSpec, int delta) { 22305 final int mode = getMode(measureSpec); 22306 int size = getSize(measureSpec); 22307 if (mode == UNSPECIFIED) { 22308 // No need to adjust size for UNSPECIFIED mode. 22309 return makeMeasureSpec(size, UNSPECIFIED); 22310 } 22311 size += delta; 22312 if (size < 0) { 22313 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + 22314 ") spec: " + toString(measureSpec) + " delta: " + delta); 22315 size = 0; 22316 } 22317 return makeMeasureSpec(size, mode); 22318 } 22319 22320 /** 22321 * Returns a String representation of the specified measure 22322 * specification. 22323 * 22324 * @param measureSpec the measure specification to convert to a String 22325 * @return a String with the following format: "MeasureSpec: MODE SIZE" 22326 */ toString(int measureSpec)22327 public static String toString(int measureSpec) { 22328 int mode = getMode(measureSpec); 22329 int size = getSize(measureSpec); 22330 22331 StringBuilder sb = new StringBuilder("MeasureSpec: "); 22332 22333 if (mode == UNSPECIFIED) 22334 sb.append("UNSPECIFIED "); 22335 else if (mode == EXACTLY) 22336 sb.append("EXACTLY "); 22337 else if (mode == AT_MOST) 22338 sb.append("AT_MOST "); 22339 else 22340 sb.append(mode).append(" "); 22341 22342 sb.append(size); 22343 return sb.toString(); 22344 } 22345 } 22346 22347 private final class CheckForLongPress implements Runnable { 22348 private int mOriginalWindowAttachCount; 22349 private float mX; 22350 private float mY; 22351 22352 @Override run()22353 public void run() { 22354 if (isPressed() && (mParent != null) 22355 && mOriginalWindowAttachCount == mWindowAttachCount) { 22356 if (performLongClick(mX, mY)) { 22357 mHasPerformedLongPress = true; 22358 } 22359 } 22360 } 22361 setAnchor(float x, float y)22362 public void setAnchor(float x, float y) { 22363 mX = x; 22364 mY = y; 22365 } 22366 rememberWindowAttachCount()22367 public void rememberWindowAttachCount() { 22368 mOriginalWindowAttachCount = mWindowAttachCount; 22369 } 22370 } 22371 22372 private final class CheckForTap implements Runnable { 22373 public float x; 22374 public float y; 22375 22376 @Override run()22377 public void run() { 22378 mPrivateFlags &= ~PFLAG_PREPRESSED; 22379 setPressed(true, x, y); 22380 checkForLongClick(ViewConfiguration.getTapTimeout(), x, y); 22381 } 22382 } 22383 22384 private final class PerformClick implements Runnable { 22385 @Override run()22386 public void run() { 22387 performClick(); 22388 } 22389 } 22390 22391 /** 22392 * This method returns a ViewPropertyAnimator object, which can be used to animate 22393 * specific properties on this View. 22394 * 22395 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 22396 */ animate()22397 public ViewPropertyAnimator animate() { 22398 if (mAnimator == null) { 22399 mAnimator = new ViewPropertyAnimator(this); 22400 } 22401 return mAnimator; 22402 } 22403 22404 /** 22405 * Sets the name of the View to be used to identify Views in Transitions. 22406 * Names should be unique in the View hierarchy. 22407 * 22408 * @param transitionName The name of the View to uniquely identify it for Transitions. 22409 */ setTransitionName(String transitionName)22410 public final void setTransitionName(String transitionName) { 22411 mTransitionName = transitionName; 22412 } 22413 22414 /** 22415 * Returns the name of the View to be used to identify Views in Transitions. 22416 * Names should be unique in the View hierarchy. 22417 * 22418 * <p>This returns null if the View has not been given a name.</p> 22419 * 22420 * @return The name used of the View to be used to identify Views in Transitions or null 22421 * if no name has been given. 22422 */ 22423 @ViewDebug.ExportedProperty getTransitionName()22424 public String getTransitionName() { 22425 return mTransitionName; 22426 } 22427 22428 /** 22429 * @hide 22430 */ requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId)22431 public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data, int deviceId) { 22432 // Do nothing. 22433 } 22434 22435 /** 22436 * Interface definition for a callback to be invoked when a hardware key event is 22437 * dispatched to this view. The callback will be invoked before the key event is 22438 * given to the view. This is only useful for hardware keyboards; a software input 22439 * method has no obligation to trigger this listener. 22440 */ 22441 public interface OnKeyListener { 22442 /** 22443 * Called when a hardware key is dispatched to a view. This allows listeners to 22444 * get a chance to respond before the target view. 22445 * <p>Key presses in software keyboards will generally NOT trigger this method, 22446 * although some may elect to do so in some situations. Do not assume a 22447 * software input method has to be key-based; even if it is, it may use key presses 22448 * in a different way than you expect, so there is no way to reliably catch soft 22449 * input key presses. 22450 * 22451 * @param v The view the key has been dispatched to. 22452 * @param keyCode The code for the physical key that was pressed 22453 * @param event The KeyEvent object containing full information about 22454 * the event. 22455 * @return True if the listener has consumed the event, false otherwise. 22456 */ onKey(View v, int keyCode, KeyEvent event)22457 boolean onKey(View v, int keyCode, KeyEvent event); 22458 } 22459 22460 /** 22461 * Interface definition for a callback to be invoked when a touch event is 22462 * dispatched to this view. The callback will be invoked before the touch 22463 * event is given to the view. 22464 */ 22465 public interface OnTouchListener { 22466 /** 22467 * Called when a touch event is dispatched to a view. This allows listeners to 22468 * get a chance to respond before the target view. 22469 * 22470 * @param v The view the touch event has been dispatched to. 22471 * @param event The MotionEvent object containing full information about 22472 * the event. 22473 * @return True if the listener has consumed the event, false otherwise. 22474 */ onTouch(View v, MotionEvent event)22475 boolean onTouch(View v, MotionEvent event); 22476 } 22477 22478 /** 22479 * Interface definition for a callback to be invoked when a hover event is 22480 * dispatched to this view. The callback will be invoked before the hover 22481 * event is given to the view. 22482 */ 22483 public interface OnHoverListener { 22484 /** 22485 * Called when a hover event is dispatched to a view. This allows listeners to 22486 * get a chance to respond before the target view. 22487 * 22488 * @param v The view the hover event has been dispatched to. 22489 * @param event The MotionEvent object containing full information about 22490 * the event. 22491 * @return True if the listener has consumed the event, false otherwise. 22492 */ onHover(View v, MotionEvent event)22493 boolean onHover(View v, MotionEvent event); 22494 } 22495 22496 /** 22497 * Interface definition for a callback to be invoked when a generic motion event is 22498 * dispatched to this view. The callback will be invoked before the generic motion 22499 * event is given to the view. 22500 */ 22501 public interface OnGenericMotionListener { 22502 /** 22503 * Called when a generic motion event is dispatched to a view. This allows listeners to 22504 * get a chance to respond before the target view. 22505 * 22506 * @param v The view the generic motion event has been dispatched to. 22507 * @param event The MotionEvent object containing full information about 22508 * the event. 22509 * @return True if the listener has consumed the event, false otherwise. 22510 */ onGenericMotion(View v, MotionEvent event)22511 boolean onGenericMotion(View v, MotionEvent event); 22512 } 22513 22514 /** 22515 * Interface definition for a callback to be invoked when a view has been clicked and held. 22516 */ 22517 public interface OnLongClickListener { 22518 /** 22519 * Called when a view has been clicked and held. 22520 * 22521 * @param v The view that was clicked and held. 22522 * 22523 * @return true if the callback consumed the long click, false otherwise. 22524 */ onLongClick(View v)22525 boolean onLongClick(View v); 22526 } 22527 22528 /** 22529 * Interface definition for a callback to be invoked when a drag is being dispatched 22530 * to this view. The callback will be invoked before the hosting view's own 22531 * onDrag(event) method. If the listener wants to fall back to the hosting view's 22532 * onDrag(event) behavior, it should return 'false' from this callback. 22533 * 22534 * <div class="special reference"> 22535 * <h3>Developer Guides</h3> 22536 * <p>For a guide to implementing drag and drop features, read the 22537 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 22538 * </div> 22539 */ 22540 public interface OnDragListener { 22541 /** 22542 * Called when a drag event is dispatched to a view. This allows listeners 22543 * to get a chance to override base View behavior. 22544 * 22545 * @param v The View that received the drag event. 22546 * @param event The {@link android.view.DragEvent} object for the drag event. 22547 * @return {@code true} if the drag event was handled successfully, or {@code false} 22548 * if the drag event was not handled. Note that {@code false} will trigger the View 22549 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 22550 */ onDrag(View v, DragEvent event)22551 boolean onDrag(View v, DragEvent event); 22552 } 22553 22554 /** 22555 * Interface definition for a callback to be invoked when the focus state of 22556 * a view changed. 22557 */ 22558 public interface OnFocusChangeListener { 22559 /** 22560 * Called when the focus state of a view has changed. 22561 * 22562 * @param v The view whose state has changed. 22563 * @param hasFocus The new focus state of v. 22564 */ onFocusChange(View v, boolean hasFocus)22565 void onFocusChange(View v, boolean hasFocus); 22566 } 22567 22568 /** 22569 * Interface definition for a callback to be invoked when a view is clicked. 22570 */ 22571 public interface OnClickListener { 22572 /** 22573 * Called when a view has been clicked. 22574 * 22575 * @param v The view that was clicked. 22576 */ onClick(View v)22577 void onClick(View v); 22578 } 22579 22580 /** 22581 * Interface definition for a callback to be invoked when a view is context clicked. 22582 */ 22583 public interface OnContextClickListener { 22584 /** 22585 * Called when a view is context clicked. 22586 * 22587 * @param v The view that has been context clicked. 22588 * @return true if the callback consumed the context click, false otherwise. 22589 */ onContextClick(View v)22590 boolean onContextClick(View v); 22591 } 22592 22593 /** 22594 * Interface definition for a callback to be invoked when the context menu 22595 * for this view is being built. 22596 */ 22597 public interface OnCreateContextMenuListener { 22598 /** 22599 * Called when the context menu for this view is being built. It is not 22600 * safe to hold onto the menu after this method returns. 22601 * 22602 * @param menu The context menu that is being built 22603 * @param v The view for which the context menu is being built 22604 * @param menuInfo Extra information about the item for which the 22605 * context menu should be shown. This information will vary 22606 * depending on the class of v. 22607 */ onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)22608 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 22609 } 22610 22611 /** 22612 * Interface definition for a callback to be invoked when the status bar changes 22613 * visibility. This reports <strong>global</strong> changes to the system UI 22614 * state, not what the application is requesting. 22615 * 22616 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 22617 */ 22618 public interface OnSystemUiVisibilityChangeListener { 22619 /** 22620 * Called when the status bar changes visibility because of a call to 22621 * {@link View#setSystemUiVisibility(int)}. 22622 * 22623 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 22624 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 22625 * This tells you the <strong>global</strong> state of these UI visibility 22626 * flags, not what your app is currently applying. 22627 */ onSystemUiVisibilityChange(int visibility)22628 public void onSystemUiVisibilityChange(int visibility); 22629 } 22630 22631 /** 22632 * Interface definition for a callback to be invoked when this view is attached 22633 * or detached from its window. 22634 */ 22635 public interface OnAttachStateChangeListener { 22636 /** 22637 * Called when the view is attached to a window. 22638 * @param v The view that was attached 22639 */ onViewAttachedToWindow(View v)22640 public void onViewAttachedToWindow(View v); 22641 /** 22642 * Called when the view is detached from a window. 22643 * @param v The view that was detached 22644 */ onViewDetachedFromWindow(View v)22645 public void onViewDetachedFromWindow(View v); 22646 } 22647 22648 /** 22649 * Listener for applying window insets on a view in a custom way. 22650 * 22651 * <p>Apps may choose to implement this interface if they want to apply custom policy 22652 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener 22653 * is set, its 22654 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 22655 * method will be called instead of the View's own 22656 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener 22657 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply 22658 * the View's normal behavior as part of its own.</p> 22659 */ 22660 public interface OnApplyWindowInsetsListener { 22661 /** 22662 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set} 22663 * on a View, this listener method will be called instead of the view's own 22664 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 22665 * 22666 * @param v The view applying window insets 22667 * @param insets The insets to apply 22668 * @return The insets supplied, minus any insets that were consumed 22669 */ onApplyWindowInsets(View v, WindowInsets insets)22670 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets); 22671 } 22672 22673 private final class UnsetPressedState implements Runnable { 22674 @Override run()22675 public void run() { 22676 setPressed(false); 22677 } 22678 } 22679 22680 /** 22681 * Base class for derived classes that want to save and restore their own 22682 * state in {@link android.view.View#onSaveInstanceState()}. 22683 */ 22684 public static class BaseSavedState extends AbsSavedState { 22685 String mStartActivityRequestWhoSaved; 22686 22687 /** 22688 * Constructor used when reading from a parcel. Reads the state of the superclass. 22689 * 22690 * @param source parcel to read from 22691 */ BaseSavedState(Parcel source)22692 public BaseSavedState(Parcel source) { 22693 this(source, null); 22694 } 22695 22696 /** 22697 * Constructor used when reading from a parcel using a given class loader. 22698 * Reads the state of the superclass. 22699 * 22700 * @param source parcel to read from 22701 * @param loader ClassLoader to use for reading 22702 */ BaseSavedState(Parcel source, ClassLoader loader)22703 public BaseSavedState(Parcel source, ClassLoader loader) { 22704 super(source, loader); 22705 mStartActivityRequestWhoSaved = source.readString(); 22706 } 22707 22708 /** 22709 * Constructor called by derived classes when creating their SavedState objects 22710 * 22711 * @param superState The state of the superclass of this view 22712 */ BaseSavedState(Parcelable superState)22713 public BaseSavedState(Parcelable superState) { 22714 super(superState); 22715 } 22716 22717 @Override writeToParcel(Parcel out, int flags)22718 public void writeToParcel(Parcel out, int flags) { 22719 super.writeToParcel(out, flags); 22720 out.writeString(mStartActivityRequestWhoSaved); 22721 } 22722 22723 public static final Parcelable.Creator<BaseSavedState> CREATOR 22724 = new Parcelable.ClassLoaderCreator<BaseSavedState>() { 22725 @Override 22726 public BaseSavedState createFromParcel(Parcel in) { 22727 return new BaseSavedState(in); 22728 } 22729 22730 @Override 22731 public BaseSavedState createFromParcel(Parcel in, ClassLoader loader) { 22732 return new BaseSavedState(in, loader); 22733 } 22734 22735 @Override 22736 public BaseSavedState[] newArray(int size) { 22737 return new BaseSavedState[size]; 22738 } 22739 }; 22740 } 22741 22742 /** 22743 * A set of information given to a view when it is attached to its parent 22744 * window. 22745 */ 22746 final static class AttachInfo { 22747 interface Callbacks { playSoundEffect(int effectId)22748 void playSoundEffect(int effectId); performHapticFeedback(int effectId, boolean always)22749 boolean performHapticFeedback(int effectId, boolean always); 22750 } 22751 22752 /** 22753 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 22754 * to a Handler. This class contains the target (View) to invalidate and 22755 * the coordinates of the dirty rectangle. 22756 * 22757 * For performance purposes, this class also implements a pool of up to 22758 * POOL_LIMIT objects that get reused. This reduces memory allocations 22759 * whenever possible. 22760 */ 22761 static class InvalidateInfo { 22762 private static final int POOL_LIMIT = 10; 22763 22764 private static final SynchronizedPool<InvalidateInfo> sPool = 22765 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 22766 22767 View target; 22768 22769 int left; 22770 int top; 22771 int right; 22772 int bottom; 22773 obtain()22774 public static InvalidateInfo obtain() { 22775 InvalidateInfo instance = sPool.acquire(); 22776 return (instance != null) ? instance : new InvalidateInfo(); 22777 } 22778 recycle()22779 public void recycle() { 22780 target = null; 22781 sPool.release(this); 22782 } 22783 } 22784 22785 final IWindowSession mSession; 22786 22787 final IWindow mWindow; 22788 22789 final IBinder mWindowToken; 22790 22791 final Display mDisplay; 22792 22793 final Callbacks mRootCallbacks; 22794 22795 IWindowId mIWindowId; 22796 WindowId mWindowId; 22797 22798 /** 22799 * The top view of the hierarchy. 22800 */ 22801 View mRootView; 22802 22803 IBinder mPanelParentWindowToken; 22804 22805 boolean mHardwareAccelerated; 22806 boolean mHardwareAccelerationRequested; 22807 ThreadedRenderer mHardwareRenderer; 22808 List<RenderNode> mPendingAnimatingRenderNodes; 22809 22810 /** 22811 * The state of the display to which the window is attached, as reported 22812 * by {@link Display#getState()}. Note that the display state constants 22813 * declared by {@link Display} do not exactly line up with the screen state 22814 * constants declared by {@link View} (there are more display states than 22815 * screen states). 22816 */ 22817 int mDisplayState = Display.STATE_UNKNOWN; 22818 22819 /** 22820 * Scale factor used by the compatibility mode 22821 */ 22822 float mApplicationScale; 22823 22824 /** 22825 * Indicates whether the application is in compatibility mode 22826 */ 22827 boolean mScalingRequired; 22828 22829 /** 22830 * Left position of this view's window 22831 */ 22832 int mWindowLeft; 22833 22834 /** 22835 * Top position of this view's window 22836 */ 22837 int mWindowTop; 22838 22839 /** 22840 * Indicates whether views need to use 32-bit drawing caches 22841 */ 22842 boolean mUse32BitDrawingCache; 22843 22844 /** 22845 * For windows that are full-screen but using insets to layout inside 22846 * of the screen areas, these are the current insets to appear inside 22847 * the overscan area of the display. 22848 */ 22849 final Rect mOverscanInsets = new Rect(); 22850 22851 /** 22852 * For windows that are full-screen but using insets to layout inside 22853 * of the screen decorations, these are the current insets for the 22854 * content of the window. 22855 */ 22856 final Rect mContentInsets = new Rect(); 22857 22858 /** 22859 * For windows that are full-screen but using insets to layout inside 22860 * of the screen decorations, these are the current insets for the 22861 * actual visible parts of the window. 22862 */ 22863 final Rect mVisibleInsets = new Rect(); 22864 22865 /** 22866 * For windows that are full-screen but using insets to layout inside 22867 * of the screen decorations, these are the current insets for the 22868 * stable system windows. 22869 */ 22870 final Rect mStableInsets = new Rect(); 22871 22872 /** 22873 * For windows that include areas that are not covered by real surface these are the outsets 22874 * for real surface. 22875 */ 22876 final Rect mOutsets = new Rect(); 22877 22878 /** 22879 * In multi-window we force show the navigation bar. Because we don't want that the surface 22880 * size changes in this mode, we instead have a flag whether the navigation bar size should 22881 * always be consumed, so the app is treated like there is no virtual navigation bar at all. 22882 */ 22883 boolean mAlwaysConsumeNavBar; 22884 22885 /** 22886 * The internal insets given by this window. This value is 22887 * supplied by the client (through 22888 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 22889 * be given to the window manager when changed to be used in laying 22890 * out windows behind it. 22891 */ 22892 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 22893 = new ViewTreeObserver.InternalInsetsInfo(); 22894 22895 /** 22896 * Set to true when mGivenInternalInsets is non-empty. 22897 */ 22898 boolean mHasNonEmptyGivenInternalInsets; 22899 22900 /** 22901 * All views in the window's hierarchy that serve as scroll containers, 22902 * used to determine if the window can be resized or must be panned 22903 * to adjust for a soft input area. 22904 */ 22905 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 22906 22907 final KeyEvent.DispatcherState mKeyDispatchState 22908 = new KeyEvent.DispatcherState(); 22909 22910 /** 22911 * Indicates whether the view's window currently has the focus. 22912 */ 22913 boolean mHasWindowFocus; 22914 22915 /** 22916 * The current visibility of the window. 22917 */ 22918 int mWindowVisibility; 22919 22920 /** 22921 * Indicates the time at which drawing started to occur. 22922 */ 22923 long mDrawingTime; 22924 22925 /** 22926 * Indicates whether or not ignoring the DIRTY_MASK flags. 22927 */ 22928 boolean mIgnoreDirtyState; 22929 22930 /** 22931 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 22932 * to avoid clearing that flag prematurely. 22933 */ 22934 boolean mSetIgnoreDirtyState = false; 22935 22936 /** 22937 * Indicates whether the view's window is currently in touch mode. 22938 */ 22939 boolean mInTouchMode; 22940 22941 /** 22942 * Indicates whether the view has requested unbuffered input dispatching for the current 22943 * event stream. 22944 */ 22945 boolean mUnbufferedDispatchRequested; 22946 22947 /** 22948 * Indicates that ViewAncestor should trigger a global layout change 22949 * the next time it performs a traversal 22950 */ 22951 boolean mRecomputeGlobalAttributes; 22952 22953 /** 22954 * Always report new attributes at next traversal. 22955 */ 22956 boolean mForceReportNewAttributes; 22957 22958 /** 22959 * Set during a traveral if any views want to keep the screen on. 22960 */ 22961 boolean mKeepScreenOn; 22962 22963 /** 22964 * Set during a traveral if the light center needs to be updated. 22965 */ 22966 boolean mNeedsUpdateLightCenter; 22967 22968 /** 22969 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 22970 */ 22971 int mSystemUiVisibility; 22972 22973 /** 22974 * Hack to force certain system UI visibility flags to be cleared. 22975 */ 22976 int mDisabledSystemUiVisibility; 22977 22978 /** 22979 * Last global system UI visibility reported by the window manager. 22980 */ 22981 int mGlobalSystemUiVisibility = -1; 22982 22983 /** 22984 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 22985 * attached. 22986 */ 22987 boolean mHasSystemUiListeners; 22988 22989 /** 22990 * Set if the window has requested to extend into the overscan region 22991 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 22992 */ 22993 boolean mOverscanRequested; 22994 22995 /** 22996 * Set if the visibility of any views has changed. 22997 */ 22998 boolean mViewVisibilityChanged; 22999 23000 /** 23001 * Set to true if a view has been scrolled. 23002 */ 23003 boolean mViewScrollChanged; 23004 23005 /** 23006 * Set to true if high contrast mode enabled 23007 */ 23008 boolean mHighContrastText; 23009 23010 /** 23011 * Set to true if a pointer event is currently being handled. 23012 */ 23013 boolean mHandlingPointerEvent; 23014 23015 /** 23016 * Global to the view hierarchy used as a temporary for dealing with 23017 * x/y points in the transparent region computations. 23018 */ 23019 final int[] mTransparentLocation = new int[2]; 23020 23021 /** 23022 * Global to the view hierarchy used as a temporary for dealing with 23023 * x/y points in the ViewGroup.invalidateChild implementation. 23024 */ 23025 final int[] mInvalidateChildLocation = new int[2]; 23026 23027 /** 23028 * Global to the view hierarchy used as a temporary for dealing with 23029 * computing absolute on-screen location. 23030 */ 23031 final int[] mTmpLocation = new int[2]; 23032 23033 /** 23034 * Global to the view hierarchy used as a temporary for dealing with 23035 * x/y location when view is transformed. 23036 */ 23037 final float[] mTmpTransformLocation = new float[2]; 23038 23039 /** 23040 * The view tree observer used to dispatch global events like 23041 * layout, pre-draw, touch mode change, etc. 23042 */ 23043 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 23044 23045 /** 23046 * A Canvas used by the view hierarchy to perform bitmap caching. 23047 */ 23048 Canvas mCanvas; 23049 23050 /** 23051 * The view root impl. 23052 */ 23053 final ViewRootImpl mViewRootImpl; 23054 23055 /** 23056 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 23057 * handler can be used to pump events in the UI events queue. 23058 */ 23059 final Handler mHandler; 23060 23061 /** 23062 * Temporary for use in computing invalidate rectangles while 23063 * calling up the hierarchy. 23064 */ 23065 final Rect mTmpInvalRect = new Rect(); 23066 23067 /** 23068 * Temporary for use in computing hit areas with transformed views 23069 */ 23070 final RectF mTmpTransformRect = new RectF(); 23071 23072 /** 23073 * Temporary for use in computing hit areas with transformed views 23074 */ 23075 final RectF mTmpTransformRect1 = new RectF(); 23076 23077 /** 23078 * Temporary list of rectanges. 23079 */ 23080 final List<RectF> mTmpRectList = new ArrayList<>(); 23081 23082 /** 23083 * Temporary for use in transforming invalidation rect 23084 */ 23085 final Matrix mTmpMatrix = new Matrix(); 23086 23087 /** 23088 * Temporary for use in transforming invalidation rect 23089 */ 23090 final Transformation mTmpTransformation = new Transformation(); 23091 23092 /** 23093 * Temporary for use in querying outlines from OutlineProviders 23094 */ 23095 final Outline mTmpOutline = new Outline(); 23096 23097 /** 23098 * Temporary list for use in collecting focusable descendents of a view. 23099 */ 23100 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 23101 23102 /** 23103 * The id of the window for accessibility purposes. 23104 */ 23105 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 23106 23107 /** 23108 * Flags related to accessibility processing. 23109 * 23110 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 23111 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 23112 */ 23113 int mAccessibilityFetchFlags; 23114 23115 /** 23116 * The drawable for highlighting accessibility focus. 23117 */ 23118 Drawable mAccessibilityFocusDrawable; 23119 23120 /** 23121 * Show where the margins, bounds and layout bounds are for each view. 23122 */ 23123 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 23124 23125 /** 23126 * Point used to compute visible regions. 23127 */ 23128 final Point mPoint = new Point(); 23129 23130 /** 23131 * Used to track which View originated a requestLayout() call, used when 23132 * requestLayout() is called during layout. 23133 */ 23134 View mViewRequestingLayout; 23135 23136 /** 23137 * Used to track views that need (at least) a partial relayout at their current size 23138 * during the next traversal. 23139 */ 23140 List<View> mPartialLayoutViews = new ArrayList<>(); 23141 23142 /** 23143 * Swapped with mPartialLayoutViews during layout to avoid concurrent 23144 * modification. Lazily assigned during ViewRootImpl layout. 23145 */ 23146 List<View> mEmptyPartialLayoutViews; 23147 23148 /** 23149 * Used to track the identity of the current drag operation. 23150 */ 23151 IBinder mDragToken; 23152 23153 /** 23154 * The drag shadow surface for the current drag operation. 23155 */ 23156 public Surface mDragSurface; 23157 23158 /** 23159 * Creates a new set of attachment information with the specified 23160 * events handler and thread. 23161 * 23162 * @param handler the events handler the view must use 23163 */ AttachInfo(IWindowSession session, IWindow window, Display display, ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer)23164 AttachInfo(IWindowSession session, IWindow window, Display display, 23165 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { 23166 mSession = session; 23167 mWindow = window; 23168 mWindowToken = window.asBinder(); 23169 mDisplay = display; 23170 mViewRootImpl = viewRootImpl; 23171 mHandler = handler; 23172 mRootCallbacks = effectPlayer; 23173 } 23174 } 23175 23176 /** 23177 * <p>ScrollabilityCache holds various fields used by a View when scrolling 23178 * is supported. This avoids keeping too many unused fields in most 23179 * instances of View.</p> 23180 */ 23181 private static class ScrollabilityCache implements Runnable { 23182 23183 /** 23184 * Scrollbars are not visible 23185 */ 23186 public static final int OFF = 0; 23187 23188 /** 23189 * Scrollbars are visible 23190 */ 23191 public static final int ON = 1; 23192 23193 /** 23194 * Scrollbars are fading away 23195 */ 23196 public static final int FADING = 2; 23197 23198 public boolean fadeScrollBars; 23199 23200 public int fadingEdgeLength; 23201 public int scrollBarDefaultDelayBeforeFade; 23202 public int scrollBarFadeDuration; 23203 23204 public int scrollBarSize; 23205 public ScrollBarDrawable scrollBar; 23206 public float[] interpolatorValues; 23207 public View host; 23208 23209 public final Paint paint; 23210 public final Matrix matrix; 23211 public Shader shader; 23212 23213 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 23214 23215 private static final float[] OPAQUE = { 255 }; 23216 private static final float[] TRANSPARENT = { 0.0f }; 23217 23218 /** 23219 * When fading should start. This time moves into the future every time 23220 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 23221 */ 23222 public long fadeStartTime; 23223 23224 23225 /** 23226 * The current state of the scrollbars: ON, OFF, or FADING 23227 */ 23228 public int state = OFF; 23229 23230 private int mLastColor; 23231 23232 public final Rect mScrollBarBounds = new Rect(); 23233 23234 public static final int NOT_DRAGGING = 0; 23235 public static final int DRAGGING_VERTICAL_SCROLL_BAR = 1; 23236 public static final int DRAGGING_HORIZONTAL_SCROLL_BAR = 2; 23237 public int mScrollBarDraggingState = NOT_DRAGGING; 23238 23239 public float mScrollBarDraggingPos = 0; 23240 ScrollabilityCache(ViewConfiguration configuration, View host)23241 public ScrollabilityCache(ViewConfiguration configuration, View host) { 23242 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 23243 scrollBarSize = configuration.getScaledScrollBarSize(); 23244 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 23245 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 23246 23247 paint = new Paint(); 23248 matrix = new Matrix(); 23249 // use use a height of 1, and then wack the matrix each time we 23250 // actually use it. 23251 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 23252 paint.setShader(shader); 23253 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 23254 23255 this.host = host; 23256 } 23257 setFadeColor(int color)23258 public void setFadeColor(int color) { 23259 if (color != mLastColor) { 23260 mLastColor = color; 23261 23262 if (color != 0) { 23263 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 23264 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 23265 paint.setShader(shader); 23266 // Restore the default transfer mode (src_over) 23267 paint.setXfermode(null); 23268 } else { 23269 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 23270 paint.setShader(shader); 23271 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 23272 } 23273 } 23274 } 23275 run()23276 public void run() { 23277 long now = AnimationUtils.currentAnimationTimeMillis(); 23278 if (now >= fadeStartTime) { 23279 23280 // the animation fades the scrollbars out by changing 23281 // the opacity (alpha) from fully opaque to fully 23282 // transparent 23283 int nextFrame = (int) now; 23284 int framesCount = 0; 23285 23286 Interpolator interpolator = scrollBarInterpolator; 23287 23288 // Start opaque 23289 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 23290 23291 // End transparent 23292 nextFrame += scrollBarFadeDuration; 23293 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 23294 23295 state = FADING; 23296 23297 // Kick off the fade animation 23298 host.invalidate(true); 23299 } 23300 } 23301 } 23302 23303 /** 23304 * Resuable callback for sending 23305 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 23306 */ 23307 private class SendViewScrolledAccessibilityEvent implements Runnable { 23308 public volatile boolean mIsPending; 23309 run()23310 public void run() { 23311 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 23312 mIsPending = false; 23313 } 23314 } 23315 23316 /** 23317 * <p> 23318 * This class represents a delegate that can be registered in a {@link View} 23319 * to enhance accessibility support via composition rather via inheritance. 23320 * It is specifically targeted to widget developers that extend basic View 23321 * classes i.e. classes in package android.view, that would like their 23322 * applications to be backwards compatible. 23323 * </p> 23324 * <div class="special reference"> 23325 * <h3>Developer Guides</h3> 23326 * <p>For more information about making applications accessible, read the 23327 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 23328 * developer guide.</p> 23329 * </div> 23330 * <p> 23331 * A scenario in which a developer would like to use an accessibility delegate 23332 * is overriding a method introduced in a later API version then the minimal API 23333 * version supported by the application. For example, the method 23334 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 23335 * in API version 4 when the accessibility APIs were first introduced. If a 23336 * developer would like his application to run on API version 4 devices (assuming 23337 * all other APIs used by the application are version 4 or lower) and take advantage 23338 * of this method, instead of overriding the method which would break the application's 23339 * backwards compatibility, he can override the corresponding method in this 23340 * delegate and register the delegate in the target View if the API version of 23341 * the system is high enough i.e. the API version is same or higher to the API 23342 * version that introduced 23343 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 23344 * </p> 23345 * <p> 23346 * Here is an example implementation: 23347 * </p> 23348 * <code><pre><p> 23349 * if (Build.VERSION.SDK_INT >= 14) { 23350 * // If the API version is equal of higher than the version in 23351 * // which onInitializeAccessibilityNodeInfo was introduced we 23352 * // register a delegate with a customized implementation. 23353 * View view = findViewById(R.id.view_id); 23354 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 23355 * public void onInitializeAccessibilityNodeInfo(View host, 23356 * AccessibilityNodeInfo info) { 23357 * // Let the default implementation populate the info. 23358 * super.onInitializeAccessibilityNodeInfo(host, info); 23359 * // Set some other information. 23360 * info.setEnabled(host.isEnabled()); 23361 * } 23362 * }); 23363 * } 23364 * </code></pre></p> 23365 * <p> 23366 * This delegate contains methods that correspond to the accessibility methods 23367 * in View. If a delegate has been specified the implementation in View hands 23368 * off handling to the corresponding method in this delegate. The default 23369 * implementation the delegate methods behaves exactly as the corresponding 23370 * method in View for the case of no accessibility delegate been set. Hence, 23371 * to customize the behavior of a View method, clients can override only the 23372 * corresponding delegate method without altering the behavior of the rest 23373 * accessibility related methods of the host view. 23374 * </p> 23375 * <p> 23376 * <strong>Note:</strong> On platform versions prior to 23377 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 23378 * views in the {@code android.widget.*} package are called <i>before</i> 23379 * host methods. This prevents certain properties such as class name from 23380 * being modified by overriding 23381 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 23382 * as any changes will be overwritten by the host class. 23383 * <p> 23384 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 23385 * methods are called <i>after</i> host methods, which all properties to be 23386 * modified without being overwritten by the host class. 23387 */ 23388 public static class AccessibilityDelegate { 23389 23390 /** 23391 * Sends an accessibility event of the given type. If accessibility is not 23392 * enabled this method has no effect. 23393 * <p> 23394 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 23395 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 23396 * been set. 23397 * </p> 23398 * 23399 * @param host The View hosting the delegate. 23400 * @param eventType The type of the event to send. 23401 * 23402 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 23403 */ sendAccessibilityEvent(View host, int eventType)23404 public void sendAccessibilityEvent(View host, int eventType) { 23405 host.sendAccessibilityEventInternal(eventType); 23406 } 23407 23408 /** 23409 * Performs the specified accessibility action on the view. For 23410 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 23411 * <p> 23412 * The default implementation behaves as 23413 * {@link View#performAccessibilityAction(int, Bundle) 23414 * View#performAccessibilityAction(int, Bundle)} for the case of 23415 * no accessibility delegate been set. 23416 * </p> 23417 * 23418 * @param action The action to perform. 23419 * @return Whether the action was performed. 23420 * 23421 * @see View#performAccessibilityAction(int, Bundle) 23422 * View#performAccessibilityAction(int, Bundle) 23423 */ performAccessibilityAction(View host, int action, Bundle args)23424 public boolean performAccessibilityAction(View host, int action, Bundle args) { 23425 return host.performAccessibilityActionInternal(action, args); 23426 } 23427 23428 /** 23429 * Sends an accessibility event. This method behaves exactly as 23430 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 23431 * empty {@link AccessibilityEvent} and does not perform a check whether 23432 * accessibility is enabled. 23433 * <p> 23434 * The default implementation behaves as 23435 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23436 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 23437 * the case of no accessibility delegate been set. 23438 * </p> 23439 * 23440 * @param host The View hosting the delegate. 23441 * @param event The event to send. 23442 * 23443 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23444 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 23445 */ sendAccessibilityEventUnchecked(View host, AccessibilityEvent event)23446 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 23447 host.sendAccessibilityEventUncheckedInternal(event); 23448 } 23449 23450 /** 23451 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 23452 * to its children for adding their text content to the event. 23453 * <p> 23454 * The default implementation behaves as 23455 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23456 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 23457 * the case of no accessibility delegate been set. 23458 * </p> 23459 * 23460 * @param host The View hosting the delegate. 23461 * @param event The event. 23462 * @return True if the event population was completed. 23463 * 23464 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23465 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 23466 */ dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event)23467 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 23468 return host.dispatchPopulateAccessibilityEventInternal(event); 23469 } 23470 23471 /** 23472 * Gives a chance to the host View to populate the accessibility event with its 23473 * text content. 23474 * <p> 23475 * The default implementation behaves as 23476 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 23477 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 23478 * the case of no accessibility delegate been set. 23479 * </p> 23480 * 23481 * @param host The View hosting the delegate. 23482 * @param event The accessibility event which to populate. 23483 * 23484 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 23485 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 23486 */ onPopulateAccessibilityEvent(View host, AccessibilityEvent event)23487 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 23488 host.onPopulateAccessibilityEventInternal(event); 23489 } 23490 23491 /** 23492 * Initializes an {@link AccessibilityEvent} with information about the 23493 * the host View which is the event source. 23494 * <p> 23495 * The default implementation behaves as 23496 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 23497 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 23498 * the case of no accessibility delegate been set. 23499 * </p> 23500 * 23501 * @param host The View hosting the delegate. 23502 * @param event The event to initialize. 23503 * 23504 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 23505 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 23506 */ onInitializeAccessibilityEvent(View host, AccessibilityEvent event)23507 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 23508 host.onInitializeAccessibilityEventInternal(event); 23509 } 23510 23511 /** 23512 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 23513 * <p> 23514 * The default implementation behaves as 23515 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23516 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 23517 * the case of no accessibility delegate been set. 23518 * </p> 23519 * 23520 * @param host The View hosting the delegate. 23521 * @param info The instance to initialize. 23522 * 23523 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23524 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 23525 */ onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)23526 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 23527 host.onInitializeAccessibilityNodeInfoInternal(info); 23528 } 23529 23530 /** 23531 * Called when a child of the host View has requested sending an 23532 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 23533 * to augment the event. 23534 * <p> 23535 * The default implementation behaves as 23536 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23537 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 23538 * the case of no accessibility delegate been set. 23539 * </p> 23540 * 23541 * @param host The View hosting the delegate. 23542 * @param child The child which requests sending the event. 23543 * @param event The event to be sent. 23544 * @return True if the event should be sent 23545 * 23546 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23547 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 23548 */ onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event)23549 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 23550 AccessibilityEvent event) { 23551 return host.onRequestSendAccessibilityEventInternal(child, event); 23552 } 23553 23554 /** 23555 * Gets the provider for managing a virtual view hierarchy rooted at this View 23556 * and reported to {@link android.accessibilityservice.AccessibilityService}s 23557 * that explore the window content. 23558 * <p> 23559 * The default implementation behaves as 23560 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 23561 * the case of no accessibility delegate been set. 23562 * </p> 23563 * 23564 * @return The provider. 23565 * 23566 * @see AccessibilityNodeProvider 23567 */ getAccessibilityNodeProvider(View host)23568 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 23569 return null; 23570 } 23571 23572 /** 23573 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 23574 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 23575 * This method is responsible for obtaining an accessibility node info from a 23576 * pool of reusable instances and calling 23577 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 23578 * view to initialize the former. 23579 * <p> 23580 * <strong>Note:</strong> The client is responsible for recycling the obtained 23581 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 23582 * creation. 23583 * </p> 23584 * <p> 23585 * The default implementation behaves as 23586 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 23587 * the case of no accessibility delegate been set. 23588 * </p> 23589 * @return A populated {@link AccessibilityNodeInfo}. 23590 * 23591 * @see AccessibilityNodeInfo 23592 * 23593 * @hide 23594 */ createAccessibilityNodeInfo(View host)23595 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 23596 return host.createAccessibilityNodeInfoInternal(); 23597 } 23598 } 23599 23600 private class MatchIdPredicate implements Predicate<View> { 23601 public int mId; 23602 23603 @Override apply(View view)23604 public boolean apply(View view) { 23605 return (view.mID == mId); 23606 } 23607 } 23608 23609 private class MatchLabelForPredicate implements Predicate<View> { 23610 private int mLabeledId; 23611 23612 @Override apply(View view)23613 public boolean apply(View view) { 23614 return (view.mLabelForId == mLabeledId); 23615 } 23616 } 23617 23618 private class SendViewStateChangedAccessibilityEvent implements Runnable { 23619 private int mChangeTypes = 0; 23620 private boolean mPosted; 23621 private boolean mPostedWithDelay; 23622 private long mLastEventTimeMillis; 23623 23624 @Override run()23625 public void run() { 23626 mPosted = false; 23627 mPostedWithDelay = false; 23628 mLastEventTimeMillis = SystemClock.uptimeMillis(); 23629 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 23630 final AccessibilityEvent event = AccessibilityEvent.obtain(); 23631 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 23632 event.setContentChangeTypes(mChangeTypes); 23633 sendAccessibilityEventUnchecked(event); 23634 } 23635 mChangeTypes = 0; 23636 } 23637 runOrPost(int changeType)23638 public void runOrPost(int changeType) { 23639 mChangeTypes |= changeType; 23640 23641 // If this is a live region or the child of a live region, collect 23642 // all events from this frame and send them on the next frame. 23643 if (inLiveRegion()) { 23644 // If we're already posted with a delay, remove that. 23645 if (mPostedWithDelay) { 23646 removeCallbacks(this); 23647 mPostedWithDelay = false; 23648 } 23649 // Only post if we're not already posted. 23650 if (!mPosted) { 23651 post(this); 23652 mPosted = true; 23653 } 23654 return; 23655 } 23656 23657 if (mPosted) { 23658 return; 23659 } 23660 23661 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; 23662 final long minEventIntevalMillis = 23663 ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); 23664 if (timeSinceLastMillis >= minEventIntevalMillis) { 23665 removeCallbacks(this); 23666 run(); 23667 } else { 23668 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); 23669 mPostedWithDelay = true; 23670 } 23671 } 23672 } 23673 inLiveRegion()23674 private boolean inLiveRegion() { 23675 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) { 23676 return true; 23677 } 23678 23679 ViewParent parent = getParent(); 23680 while (parent instanceof View) { 23681 if (((View) parent).getAccessibilityLiveRegion() 23682 != View.ACCESSIBILITY_LIVE_REGION_NONE) { 23683 return true; 23684 } 23685 parent = parent.getParent(); 23686 } 23687 23688 return false; 23689 } 23690 23691 /** 23692 * Dump all private flags in readable format, useful for documentation and 23693 * sanity checking. 23694 */ dumpFlags()23695 private static void dumpFlags() { 23696 final HashMap<String, String> found = Maps.newHashMap(); 23697 try { 23698 for (Field field : View.class.getDeclaredFields()) { 23699 final int modifiers = field.getModifiers(); 23700 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 23701 if (field.getType().equals(int.class)) { 23702 final int value = field.getInt(null); 23703 dumpFlag(found, field.getName(), value); 23704 } else if (field.getType().equals(int[].class)) { 23705 final int[] values = (int[]) field.get(null); 23706 for (int i = 0; i < values.length; i++) { 23707 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 23708 } 23709 } 23710 } 23711 } 23712 } catch (IllegalAccessException e) { 23713 throw new RuntimeException(e); 23714 } 23715 23716 final ArrayList<String> keys = Lists.newArrayList(); 23717 keys.addAll(found.keySet()); 23718 Collections.sort(keys); 23719 for (String key : keys) { 23720 Log.d(VIEW_LOG_TAG, found.get(key)); 23721 } 23722 } 23723 dumpFlag(HashMap<String, String> found, String name, int value)23724 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 23725 // Sort flags by prefix, then by bits, always keeping unique keys 23726 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 23727 final int prefix = name.indexOf('_'); 23728 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 23729 final String output = bits + " " + name; 23730 found.put(key, output); 23731 } 23732 23733 /** {@hide} */ encode(@onNull ViewHierarchyEncoder stream)23734 public void encode(@NonNull ViewHierarchyEncoder stream) { 23735 stream.beginObject(this); 23736 encodeProperties(stream); 23737 stream.endObject(); 23738 } 23739 23740 /** {@hide} */ 23741 @CallSuper encodeProperties(@onNull ViewHierarchyEncoder stream)23742 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 23743 Object resolveId = ViewDebug.resolveId(getContext(), mID); 23744 if (resolveId instanceof String) { 23745 stream.addProperty("id", (String) resolveId); 23746 } else { 23747 stream.addProperty("id", mID); 23748 } 23749 23750 stream.addProperty("misc:transformation.alpha", 23751 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); 23752 stream.addProperty("misc:transitionName", getTransitionName()); 23753 23754 // layout 23755 stream.addProperty("layout:left", mLeft); 23756 stream.addProperty("layout:right", mRight); 23757 stream.addProperty("layout:top", mTop); 23758 stream.addProperty("layout:bottom", mBottom); 23759 stream.addProperty("layout:width", getWidth()); 23760 stream.addProperty("layout:height", getHeight()); 23761 stream.addProperty("layout:layoutDirection", getLayoutDirection()); 23762 stream.addProperty("layout:layoutRtl", isLayoutRtl()); 23763 stream.addProperty("layout:hasTransientState", hasTransientState()); 23764 stream.addProperty("layout:baseline", getBaseline()); 23765 23766 // layout params 23767 ViewGroup.LayoutParams layoutParams = getLayoutParams(); 23768 if (layoutParams != null) { 23769 stream.addPropertyKey("layoutParams"); 23770 layoutParams.encode(stream); 23771 } 23772 23773 // scrolling 23774 stream.addProperty("scrolling:scrollX", mScrollX); 23775 stream.addProperty("scrolling:scrollY", mScrollY); 23776 23777 // padding 23778 stream.addProperty("padding:paddingLeft", mPaddingLeft); 23779 stream.addProperty("padding:paddingRight", mPaddingRight); 23780 stream.addProperty("padding:paddingTop", mPaddingTop); 23781 stream.addProperty("padding:paddingBottom", mPaddingBottom); 23782 stream.addProperty("padding:userPaddingRight", mUserPaddingRight); 23783 stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); 23784 stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); 23785 stream.addProperty("padding:userPaddingStart", mUserPaddingStart); 23786 stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); 23787 23788 // measurement 23789 stream.addProperty("measurement:minHeight", mMinHeight); 23790 stream.addProperty("measurement:minWidth", mMinWidth); 23791 stream.addProperty("measurement:measuredWidth", mMeasuredWidth); 23792 stream.addProperty("measurement:measuredHeight", mMeasuredHeight); 23793 23794 // drawing 23795 stream.addProperty("drawing:elevation", getElevation()); 23796 stream.addProperty("drawing:translationX", getTranslationX()); 23797 stream.addProperty("drawing:translationY", getTranslationY()); 23798 stream.addProperty("drawing:translationZ", getTranslationZ()); 23799 stream.addProperty("drawing:rotation", getRotation()); 23800 stream.addProperty("drawing:rotationX", getRotationX()); 23801 stream.addProperty("drawing:rotationY", getRotationY()); 23802 stream.addProperty("drawing:scaleX", getScaleX()); 23803 stream.addProperty("drawing:scaleY", getScaleY()); 23804 stream.addProperty("drawing:pivotX", getPivotX()); 23805 stream.addProperty("drawing:pivotY", getPivotY()); 23806 stream.addProperty("drawing:opaque", isOpaque()); 23807 stream.addProperty("drawing:alpha", getAlpha()); 23808 stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); 23809 stream.addProperty("drawing:shadow", hasShadow()); 23810 stream.addProperty("drawing:solidColor", getSolidColor()); 23811 stream.addProperty("drawing:layerType", mLayerType); 23812 stream.addProperty("drawing:willNotDraw", willNotDraw()); 23813 stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); 23814 stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); 23815 stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); 23816 stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); 23817 23818 // focus 23819 stream.addProperty("focus:hasFocus", hasFocus()); 23820 stream.addProperty("focus:isFocused", isFocused()); 23821 stream.addProperty("focus:isFocusable", isFocusable()); 23822 stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); 23823 23824 stream.addProperty("misc:clickable", isClickable()); 23825 stream.addProperty("misc:pressed", isPressed()); 23826 stream.addProperty("misc:selected", isSelected()); 23827 stream.addProperty("misc:touchMode", isInTouchMode()); 23828 stream.addProperty("misc:hovered", isHovered()); 23829 stream.addProperty("misc:activated", isActivated()); 23830 23831 stream.addProperty("misc:visibility", getVisibility()); 23832 stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); 23833 stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); 23834 23835 stream.addProperty("misc:enabled", isEnabled()); 23836 stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); 23837 stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); 23838 23839 // theme attributes 23840 Resources.Theme theme = getContext().getTheme(); 23841 if (theme != null) { 23842 stream.addPropertyKey("theme"); 23843 theme.encode(stream); 23844 } 23845 23846 // view attribute information 23847 int n = mAttributes != null ? mAttributes.length : 0; 23848 stream.addProperty("meta:__attrCount__", n/2); 23849 for (int i = 0; i < n; i += 2) { 23850 stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); 23851 } 23852 23853 stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); 23854 23855 // text 23856 stream.addProperty("text:textDirection", getTextDirection()); 23857 stream.addProperty("text:textAlignment", getTextAlignment()); 23858 23859 // accessibility 23860 CharSequence contentDescription = getContentDescription(); 23861 stream.addProperty("accessibility:contentDescription", 23862 contentDescription == null ? "" : contentDescription.toString()); 23863 stream.addProperty("accessibility:labelFor", getLabelFor()); 23864 stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); 23865 } 23866 23867 /** 23868 * Determine if this view is rendered on a round wearable device and is the main view 23869 * on the screen. 23870 */ shouldDrawRoundScrollbar()23871 private boolean shouldDrawRoundScrollbar() { 23872 if (!mResources.getConfiguration().isScreenRound()) { 23873 return false; 23874 } 23875 23876 final View rootView = getRootView(); 23877 final WindowInsets insets = getRootWindowInsets(); 23878 23879 int height = getHeight(); 23880 int width = getWidth(); 23881 int displayHeight = rootView.getHeight(); 23882 int displayWidth = rootView.getWidth(); 23883 23884 if (height != displayHeight || width != displayWidth) { 23885 return false; 23886 } 23887 23888 getLocationOnScreen(mAttachInfo.mTmpLocation); 23889 return mAttachInfo.mTmpLocation[0] == insets.getStableInsetLeft() 23890 && mAttachInfo.mTmpLocation[1] == insets.getStableInsetTop(); 23891 } 23892 } 23893