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.content.ClipData; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.content.res.Resources; 23 import android.content.res.TypedArray; 24 import android.graphics.Bitmap; 25 import android.graphics.Camera; 26 import android.graphics.Canvas; 27 import android.graphics.Insets; 28 import android.graphics.Interpolator; 29 import android.graphics.LinearGradient; 30 import android.graphics.Matrix; 31 import android.graphics.Paint; 32 import android.graphics.PixelFormat; 33 import android.graphics.Point; 34 import android.graphics.PorterDuff; 35 import android.graphics.PorterDuffXfermode; 36 import android.graphics.Rect; 37 import android.graphics.RectF; 38 import android.graphics.Region; 39 import android.graphics.Shader; 40 import android.graphics.drawable.ColorDrawable; 41 import android.graphics.drawable.Drawable; 42 import android.hardware.display.DisplayManagerGlobal; 43 import android.os.Bundle; 44 import android.os.Handler; 45 import android.os.IBinder; 46 import android.os.Parcel; 47 import android.os.Parcelable; 48 import android.os.RemoteException; 49 import android.os.SystemClock; 50 import android.os.SystemProperties; 51 import android.text.TextUtils; 52 import android.util.AttributeSet; 53 import android.util.FloatProperty; 54 import android.util.LayoutDirection; 55 import android.util.Log; 56 import android.util.LongSparseLongArray; 57 import android.util.Pools.SynchronizedPool; 58 import android.util.Property; 59 import android.util.SparseArray; 60 import android.util.SuperNotCalledException; 61 import android.util.TypedValue; 62 import android.view.ContextMenu.ContextMenuInfo; 63 import android.view.AccessibilityIterators.TextSegmentIterator; 64 import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 65 import android.view.AccessibilityIterators.WordTextSegmentIterator; 66 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 67 import android.view.accessibility.AccessibilityEvent; 68 import android.view.accessibility.AccessibilityEventSource; 69 import android.view.accessibility.AccessibilityManager; 70 import android.view.accessibility.AccessibilityNodeInfo; 71 import android.view.accessibility.AccessibilityNodeProvider; 72 import android.view.animation.Animation; 73 import android.view.animation.AnimationUtils; 74 import android.view.animation.Transformation; 75 import android.view.inputmethod.EditorInfo; 76 import android.view.inputmethod.InputConnection; 77 import android.view.inputmethod.InputMethodManager; 78 import android.widget.ScrollBarDrawable; 79 80 import static android.os.Build.VERSION_CODES.*; 81 import static java.lang.Math.max; 82 83 import com.android.internal.R; 84 import com.android.internal.util.Predicate; 85 import com.android.internal.view.menu.MenuBuilder; 86 import com.google.android.collect.Lists; 87 import com.google.android.collect.Maps; 88 89 import java.lang.ref.WeakReference; 90 import java.lang.reflect.Field; 91 import java.lang.reflect.InvocationTargetException; 92 import java.lang.reflect.Method; 93 import java.lang.reflect.Modifier; 94 import java.util.ArrayList; 95 import java.util.Arrays; 96 import java.util.Collections; 97 import java.util.HashMap; 98 import java.util.Locale; 99 import java.util.concurrent.CopyOnWriteArrayList; 100 import java.util.concurrent.atomic.AtomicInteger; 101 102 /** 103 * <p> 104 * This class represents the basic building block for user interface components. A View 105 * occupies a rectangular area on the screen and is responsible for drawing and 106 * event handling. View is the base class for <em>widgets</em>, which are 107 * used to create interactive UI components (buttons, text fields, etc.). The 108 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 109 * are invisible containers that hold other Views (or other ViewGroups) and define 110 * their layout properties. 111 * </p> 112 * 113 * <div class="special reference"> 114 * <h3>Developer Guides</h3> 115 * <p>For information about using this class to develop your application's user interface, 116 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 117 * </div> 118 * 119 * <a name="Using"></a> 120 * <h3>Using Views</h3> 121 * <p> 122 * All of the views in a window are arranged in a single tree. You can add views 123 * either from code or by specifying a tree of views in one or more XML layout 124 * files. There are many specialized subclasses of views that act as controls or 125 * are capable of displaying text, images, or other content. 126 * </p> 127 * <p> 128 * Once you have created a tree of views, there are typically a few types of 129 * common operations you may wish to perform: 130 * <ul> 131 * <li><strong>Set properties:</strong> for example setting the text of a 132 * {@link android.widget.TextView}. The available properties and the methods 133 * that set them will vary among the different subclasses of views. Note that 134 * properties that are known at build time can be set in the XML layout 135 * files.</li> 136 * <li><strong>Set focus:</strong> The framework will handled moving focus in 137 * response to user input. To force focus to a specific view, call 138 * {@link #requestFocus}.</li> 139 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 140 * that will be notified when something interesting happens to the view. For 141 * example, all views will let you set a listener to be notified when the view 142 * gains or loses focus. You can register such a listener using 143 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 144 * Other view subclasses offer more specialized listeners. For example, a Button 145 * exposes a listener to notify clients when the button is clicked.</li> 146 * <li><strong>Set visibility:</strong> You can hide or show views using 147 * {@link #setVisibility(int)}.</li> 148 * </ul> 149 * </p> 150 * <p><em> 151 * Note: The Android framework is responsible for measuring, laying out and 152 * drawing views. You should not call methods that perform these actions on 153 * views yourself unless you are actually implementing a 154 * {@link android.view.ViewGroup}. 155 * </em></p> 156 * 157 * <a name="Lifecycle"></a> 158 * <h3>Implementing a Custom View</h3> 159 * 160 * <p> 161 * To implement a custom view, you will usually begin by providing overrides for 162 * some of the standard methods that the framework calls on all views. You do 163 * not need to override all of these methods. In fact, you can start by just 164 * overriding {@link #onDraw(android.graphics.Canvas)}. 165 * <table border="2" width="85%" align="center" cellpadding="5"> 166 * <thead> 167 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 168 * </thead> 169 * 170 * <tbody> 171 * <tr> 172 * <td rowspan="2">Creation</td> 173 * <td>Constructors</td> 174 * <td>There is a form of the constructor that are called when the view 175 * is created from code and a form that is called when the view is 176 * inflated from a layout file. The second form should parse and apply 177 * any attributes defined in the layout file. 178 * </td> 179 * </tr> 180 * <tr> 181 * <td><code>{@link #onFinishInflate()}</code></td> 182 * <td>Called after a view and all of its children has been inflated 183 * from XML.</td> 184 * </tr> 185 * 186 * <tr> 187 * <td rowspan="3">Layout</td> 188 * <td><code>{@link #onMeasure(int, int)}</code></td> 189 * <td>Called to determine the size requirements for this view and all 190 * of its children. 191 * </td> 192 * </tr> 193 * <tr> 194 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 195 * <td>Called when this view should assign a size and position to all 196 * of its children. 197 * </td> 198 * </tr> 199 * <tr> 200 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 201 * <td>Called when the size of this view has changed. 202 * </td> 203 * </tr> 204 * 205 * <tr> 206 * <td>Drawing</td> 207 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 208 * <td>Called when the view should render its content. 209 * </td> 210 * </tr> 211 * 212 * <tr> 213 * <td rowspan="4">Event processing</td> 214 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 215 * <td>Called when a new hardware key event occurs. 216 * </td> 217 * </tr> 218 * <tr> 219 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 220 * <td>Called when a hardware key up event occurs. 221 * </td> 222 * </tr> 223 * <tr> 224 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 225 * <td>Called when a trackball motion event occurs. 226 * </td> 227 * </tr> 228 * <tr> 229 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 230 * <td>Called when a touch screen motion event occurs. 231 * </td> 232 * </tr> 233 * 234 * <tr> 235 * <td rowspan="2">Focus</td> 236 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 237 * <td>Called when the view gains or loses focus. 238 * </td> 239 * </tr> 240 * 241 * <tr> 242 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 243 * <td>Called when the window containing the view gains or loses focus. 244 * </td> 245 * </tr> 246 * 247 * <tr> 248 * <td rowspan="3">Attaching</td> 249 * <td><code>{@link #onAttachedToWindow()}</code></td> 250 * <td>Called when the view is attached to a window. 251 * </td> 252 * </tr> 253 * 254 * <tr> 255 * <td><code>{@link #onDetachedFromWindow}</code></td> 256 * <td>Called when the view is detached from its window. 257 * </td> 258 * </tr> 259 * 260 * <tr> 261 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 262 * <td>Called when the visibility of the window containing the view 263 * has changed. 264 * </td> 265 * </tr> 266 * </tbody> 267 * 268 * </table> 269 * </p> 270 * 271 * <a name="IDs"></a> 272 * <h3>IDs</h3> 273 * Views may have an integer id associated with them. These ids are typically 274 * assigned in the layout XML files, and are used to find specific views within 275 * the view tree. A common pattern is to: 276 * <ul> 277 * <li>Define a Button in the layout file and assign it a unique ID. 278 * <pre> 279 * <Button 280 * android:id="@+id/my_button" 281 * android:layout_width="wrap_content" 282 * android:layout_height="wrap_content" 283 * android:text="@string/my_button_text"/> 284 * </pre></li> 285 * <li>From the onCreate method of an Activity, find the Button 286 * <pre class="prettyprint"> 287 * Button myButton = (Button) findViewById(R.id.my_button); 288 * </pre></li> 289 * </ul> 290 * <p> 291 * View IDs need not be unique throughout the tree, but it is good practice to 292 * ensure that they are at least unique within the part of the tree you are 293 * searching. 294 * </p> 295 * 296 * <a name="Position"></a> 297 * <h3>Position</h3> 298 * <p> 299 * The geometry of a view is that of a rectangle. A view has a location, 300 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 301 * two dimensions, expressed as a width and a height. The unit for location 302 * and dimensions is the pixel. 303 * </p> 304 * 305 * <p> 306 * It is possible to retrieve the location of a view by invoking the methods 307 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 308 * coordinate of the rectangle representing the view. The latter returns the 309 * top, or Y, coordinate of the rectangle representing the view. These methods 310 * both return the location of the view relative to its parent. For instance, 311 * when getLeft() returns 20, that means the view is located 20 pixels to the 312 * right of the left edge of its direct parent. 313 * </p> 314 * 315 * <p> 316 * In addition, several convenience methods are offered to avoid unnecessary 317 * computations, namely {@link #getRight()} and {@link #getBottom()}. 318 * These methods return the coordinates of the right and bottom edges of the 319 * rectangle representing the view. For instance, calling {@link #getRight()} 320 * is similar to the following computation: <code>getLeft() + getWidth()</code> 321 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 322 * </p> 323 * 324 * <a name="SizePaddingMargins"></a> 325 * <h3>Size, padding and margins</h3> 326 * <p> 327 * The size of a view is expressed with a width and a height. A view actually 328 * possess two pairs of width and height values. 329 * </p> 330 * 331 * <p> 332 * The first pair is known as <em>measured width</em> and 333 * <em>measured height</em>. These dimensions define how big a view wants to be 334 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 335 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 336 * and {@link #getMeasuredHeight()}. 337 * </p> 338 * 339 * <p> 340 * The second pair is simply known as <em>width</em> and <em>height</em>, or 341 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 342 * dimensions define the actual size of the view on screen, at drawing time and 343 * after layout. These values may, but do not have to, be different from the 344 * measured width and height. The width and height can be obtained by calling 345 * {@link #getWidth()} and {@link #getHeight()}. 346 * </p> 347 * 348 * <p> 349 * To measure its dimensions, a view takes into account its padding. The padding 350 * is expressed in pixels for the left, top, right and bottom parts of the view. 351 * Padding can be used to offset the content of the view by a specific amount of 352 * pixels. For instance, a left padding of 2 will push the view's content by 353 * 2 pixels to the right of the left edge. Padding can be set using the 354 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 355 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 356 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 357 * {@link #getPaddingEnd()}. 358 * </p> 359 * 360 * <p> 361 * Even though a view can define a padding, it does not provide any support for 362 * margins. However, view groups provide such a support. Refer to 363 * {@link android.view.ViewGroup} and 364 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 365 * </p> 366 * 367 * <a name="Layout"></a> 368 * <h3>Layout</h3> 369 * <p> 370 * Layout is a two pass process: a measure pass and a layout pass. The measuring 371 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 372 * of the view tree. Each view pushes dimension specifications down the tree 373 * during the recursion. At the end of the measure pass, every view has stored 374 * its measurements. The second pass happens in 375 * {@link #layout(int,int,int,int)} and is also top-down. During 376 * this pass each parent is responsible for positioning all of its children 377 * using the sizes computed in the measure pass. 378 * </p> 379 * 380 * <p> 381 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 382 * {@link #getMeasuredHeight()} values must be set, along with those for all of 383 * that view's descendants. A view's measured width and measured height values 384 * must respect the constraints imposed by the view's parents. This guarantees 385 * that at the end of the measure pass, all parents accept all of their 386 * children's measurements. A parent view may call measure() more than once on 387 * its children. For example, the parent may measure each child once with 388 * unspecified dimensions to find out how big they want to be, then call 389 * measure() on them again with actual numbers if the sum of all the children's 390 * unconstrained sizes is too big or too small. 391 * </p> 392 * 393 * <p> 394 * The measure pass uses two classes to communicate dimensions. The 395 * {@link MeasureSpec} class is used by views to tell their parents how they 396 * want to be measured and positioned. The base LayoutParams class just 397 * describes how big the view wants to be for both width and height. For each 398 * dimension, it can specify one of: 399 * <ul> 400 * <li> an exact number 401 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 402 * (minus padding) 403 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 404 * enclose its content (plus padding). 405 * </ul> 406 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 407 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 408 * an X and Y value. 409 * </p> 410 * 411 * <p> 412 * MeasureSpecs are used to push requirements down the tree from parent to 413 * child. A MeasureSpec can be in one of three modes: 414 * <ul> 415 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 416 * of a child view. For example, a LinearLayout may call measure() on its child 417 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 418 * tall the child view wants to be given a width of 240 pixels. 419 * <li>EXACTLY: This is used by the parent to impose an exact size on the 420 * child. The child must use this size, and guarantee that all of its 421 * descendants will fit within this size. 422 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 423 * child. The child must gurantee that it and all of its descendants will fit 424 * within this size. 425 * </ul> 426 * </p> 427 * 428 * <p> 429 * To intiate a layout, call {@link #requestLayout}. This method is typically 430 * called by a view on itself when it believes that is can no longer fit within 431 * its current bounds. 432 * </p> 433 * 434 * <a name="Drawing"></a> 435 * <h3>Drawing</h3> 436 * <p> 437 * Drawing is handled by walking the tree and rendering each view that 438 * intersects the invalid region. Because the tree is traversed in-order, 439 * this means that parents will draw before (i.e., behind) their children, with 440 * siblings drawn in the order they appear in the tree. 441 * If you set a background drawable for a View, then the View will draw it for you 442 * before calling back to its <code>onDraw()</code> method. 443 * </p> 444 * 445 * <p> 446 * Note that the framework will not draw views that are not in the invalid region. 447 * </p> 448 * 449 * <p> 450 * To force a view to draw, call {@link #invalidate()}. 451 * </p> 452 * 453 * <a name="EventHandlingThreading"></a> 454 * <h3>Event Handling and Threading</h3> 455 * <p> 456 * The basic cycle of a view is as follows: 457 * <ol> 458 * <li>An event comes in and is dispatched to the appropriate view. The view 459 * handles the event and notifies any listeners.</li> 460 * <li>If in the course of processing the event, the view's bounds may need 461 * to be changed, the view will call {@link #requestLayout()}.</li> 462 * <li>Similarly, if in the course of processing the event the view's appearance 463 * may need to be changed, the view will call {@link #invalidate()}.</li> 464 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 465 * the framework will take care of measuring, laying out, and drawing the tree 466 * as appropriate.</li> 467 * </ol> 468 * </p> 469 * 470 * <p><em>Note: The entire view tree is single threaded. You must always be on 471 * the UI thread when calling any method on any view.</em> 472 * If you are doing work on other threads and want to update the state of a view 473 * from that thread, you should use a {@link Handler}. 474 * </p> 475 * 476 * <a name="FocusHandling"></a> 477 * <h3>Focus Handling</h3> 478 * <p> 479 * The framework will handle routine focus movement in response to user input. 480 * This includes changing the focus as views are removed or hidden, or as new 481 * views become available. Views indicate their willingness to take focus 482 * through the {@link #isFocusable} method. To change whether a view can take 483 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 484 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 485 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 486 * </p> 487 * <p> 488 * Focus movement is based on an algorithm which finds the nearest neighbor in a 489 * given direction. In rare cases, the default algorithm may not match the 490 * intended behavior of the developer. In these situations, you can provide 491 * explicit overrides by using these XML attributes in the layout file: 492 * <pre> 493 * nextFocusDown 494 * nextFocusLeft 495 * nextFocusRight 496 * nextFocusUp 497 * </pre> 498 * </p> 499 * 500 * 501 * <p> 502 * To get a particular view to take focus, call {@link #requestFocus()}. 503 * </p> 504 * 505 * <a name="TouchMode"></a> 506 * <h3>Touch Mode</h3> 507 * <p> 508 * When a user is navigating a user interface via directional keys such as a D-pad, it is 509 * necessary to give focus to actionable items such as buttons so the user can see 510 * what will take input. If the device has touch capabilities, however, and the user 511 * begins interacting with the interface by touching it, it is no longer necessary to 512 * always highlight, or give focus to, a particular view. This motivates a mode 513 * for interaction named 'touch mode'. 514 * </p> 515 * <p> 516 * For a touch capable device, once the user touches the screen, the device 517 * will enter touch mode. From this point onward, only views for which 518 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 519 * Other views that are touchable, like buttons, will not take focus when touched; they will 520 * only fire the on click listeners. 521 * </p> 522 * <p> 523 * Any time a user hits a directional key, such as a D-pad direction, the view device will 524 * exit touch mode, and find a view to take focus, so that the user may resume interacting 525 * with the user interface without touching the screen again. 526 * </p> 527 * <p> 528 * The touch mode state is maintained across {@link android.app.Activity}s. Call 529 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 530 * </p> 531 * 532 * <a name="Scrolling"></a> 533 * <h3>Scrolling</h3> 534 * <p> 535 * The framework provides basic support for views that wish to internally 536 * scroll their content. This includes keeping track of the X and Y scroll 537 * offset as well as mechanisms for drawing scrollbars. See 538 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 539 * {@link #awakenScrollBars()} for more details. 540 * </p> 541 * 542 * <a name="Tags"></a> 543 * <h3>Tags</h3> 544 * <p> 545 * Unlike IDs, tags are not used to identify views. Tags are essentially an 546 * extra piece of information that can be associated with a view. They are most 547 * often used as a convenience to store data related to views in the views 548 * themselves rather than by putting them in a separate structure. 549 * </p> 550 * 551 * <a name="Properties"></a> 552 * <h3>Properties</h3> 553 * <p> 554 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 555 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 556 * available both in the {@link Property} form as well as in similarly-named setter/getter 557 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 558 * be used to set persistent state associated with these rendering-related properties on the view. 559 * The properties and methods can also be used in conjunction with 560 * {@link android.animation.Animator Animator}-based animations, described more in the 561 * <a href="#Animation">Animation</a> section. 562 * </p> 563 * 564 * <a name="Animation"></a> 565 * <h3>Animation</h3> 566 * <p> 567 * Starting with Android 3.0, the preferred way of animating views is to use the 568 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 569 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 570 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 571 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 572 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 573 * makes animating these View properties particularly easy and efficient. 574 * </p> 575 * <p> 576 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 577 * You can attach an {@link Animation} object to a view using 578 * {@link #setAnimation(Animation)} or 579 * {@link #startAnimation(Animation)}. The animation can alter the scale, 580 * rotation, translation and alpha of a view over time. If the animation is 581 * attached to a view that has children, the animation will affect the entire 582 * subtree rooted by that node. When an animation is started, the framework will 583 * take care of redrawing the appropriate views until the animation completes. 584 * </p> 585 * 586 * <a name="Security"></a> 587 * <h3>Security</h3> 588 * <p> 589 * Sometimes it is essential that an application be able to verify that an action 590 * is being performed with the full knowledge and consent of the user, such as 591 * granting a permission request, making a purchase or clicking on an advertisement. 592 * Unfortunately, a malicious application could try to spoof the user into 593 * performing these actions, unaware, by concealing the intended purpose of the view. 594 * As a remedy, the framework offers a touch filtering mechanism that can be used to 595 * improve the security of views that provide access to sensitive functionality. 596 * </p><p> 597 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 598 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 599 * will discard touches that are received whenever the view's window is obscured by 600 * another visible window. As a result, the view will not receive touches whenever a 601 * toast, dialog or other window appears above the view's window. 602 * </p><p> 603 * For more fine-grained control over security, consider overriding the 604 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 605 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 606 * </p> 607 * 608 * @attr ref android.R.styleable#View_alpha 609 * @attr ref android.R.styleable#View_background 610 * @attr ref android.R.styleable#View_clickable 611 * @attr ref android.R.styleable#View_contentDescription 612 * @attr ref android.R.styleable#View_drawingCacheQuality 613 * @attr ref android.R.styleable#View_duplicateParentState 614 * @attr ref android.R.styleable#View_id 615 * @attr ref android.R.styleable#View_requiresFadingEdge 616 * @attr ref android.R.styleable#View_fadeScrollbars 617 * @attr ref android.R.styleable#View_fadingEdgeLength 618 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 619 * @attr ref android.R.styleable#View_fitsSystemWindows 620 * @attr ref android.R.styleable#View_isScrollContainer 621 * @attr ref android.R.styleable#View_focusable 622 * @attr ref android.R.styleable#View_focusableInTouchMode 623 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 624 * @attr ref android.R.styleable#View_keepScreenOn 625 * @attr ref android.R.styleable#View_layerType 626 * @attr ref android.R.styleable#View_layoutDirection 627 * @attr ref android.R.styleable#View_longClickable 628 * @attr ref android.R.styleable#View_minHeight 629 * @attr ref android.R.styleable#View_minWidth 630 * @attr ref android.R.styleable#View_nextFocusDown 631 * @attr ref android.R.styleable#View_nextFocusLeft 632 * @attr ref android.R.styleable#View_nextFocusRight 633 * @attr ref android.R.styleable#View_nextFocusUp 634 * @attr ref android.R.styleable#View_onClick 635 * @attr ref android.R.styleable#View_padding 636 * @attr ref android.R.styleable#View_paddingBottom 637 * @attr ref android.R.styleable#View_paddingLeft 638 * @attr ref android.R.styleable#View_paddingRight 639 * @attr ref android.R.styleable#View_paddingTop 640 * @attr ref android.R.styleable#View_paddingStart 641 * @attr ref android.R.styleable#View_paddingEnd 642 * @attr ref android.R.styleable#View_saveEnabled 643 * @attr ref android.R.styleable#View_rotation 644 * @attr ref android.R.styleable#View_rotationX 645 * @attr ref android.R.styleable#View_rotationY 646 * @attr ref android.R.styleable#View_scaleX 647 * @attr ref android.R.styleable#View_scaleY 648 * @attr ref android.R.styleable#View_scrollX 649 * @attr ref android.R.styleable#View_scrollY 650 * @attr ref android.R.styleable#View_scrollbarSize 651 * @attr ref android.R.styleable#View_scrollbarStyle 652 * @attr ref android.R.styleable#View_scrollbars 653 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 654 * @attr ref android.R.styleable#View_scrollbarFadeDuration 655 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 656 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 657 * @attr ref android.R.styleable#View_scrollbarThumbVertical 658 * @attr ref android.R.styleable#View_scrollbarTrackVertical 659 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 660 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 661 * @attr ref android.R.styleable#View_soundEffectsEnabled 662 * @attr ref android.R.styleable#View_tag 663 * @attr ref android.R.styleable#View_textAlignment 664 * @attr ref android.R.styleable#View_textDirection 665 * @attr ref android.R.styleable#View_transformPivotX 666 * @attr ref android.R.styleable#View_transformPivotY 667 * @attr ref android.R.styleable#View_translationX 668 * @attr ref android.R.styleable#View_translationY 669 * @attr ref android.R.styleable#View_visibility 670 * 671 * @see android.view.ViewGroup 672 */ 673 public class View implements Drawable.Callback, KeyEvent.Callback, 674 AccessibilityEventSource { 675 private static final boolean DBG = false; 676 677 /** 678 * The logging tag used by this class with android.util.Log. 679 */ 680 protected static final String VIEW_LOG_TAG = "View"; 681 682 /** 683 * When set to true, apps will draw debugging information about their layouts. 684 * 685 * @hide 686 */ 687 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 688 689 /** 690 * Used to mark a View that has no ID. 691 */ 692 public static final int NO_ID = -1; 693 694 /** 695 * Signals that compatibility booleans have been initialized according to 696 * target SDK versions. 697 */ 698 private static boolean sCompatibilityDone = false; 699 700 /** 701 * Use the old (broken) way of building MeasureSpecs. 702 */ 703 private static boolean sUseBrokenMakeMeasureSpec = false; 704 705 /** 706 * Ignore any optimizations using the measure cache. 707 */ 708 private static boolean sIgnoreMeasureCache = false; 709 710 /** 711 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 712 * calling setFlags. 713 */ 714 private static final int NOT_FOCUSABLE = 0x00000000; 715 716 /** 717 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 718 * setFlags. 719 */ 720 private static final int FOCUSABLE = 0x00000001; 721 722 /** 723 * Mask for use with setFlags indicating bits used for focus. 724 */ 725 private static final int FOCUSABLE_MASK = 0x00000001; 726 727 /** 728 * This view will adjust its padding to fit sytem windows (e.g. status bar) 729 */ 730 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 731 732 /** 733 * This view is visible. 734 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 735 * android:visibility}. 736 */ 737 public static final int VISIBLE = 0x00000000; 738 739 /** 740 * This view is invisible, but it still takes up space for layout purposes. 741 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 742 * android:visibility}. 743 */ 744 public static final int INVISIBLE = 0x00000004; 745 746 /** 747 * This view is invisible, and it doesn't take any space for layout 748 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 749 * android:visibility}. 750 */ 751 public static final int GONE = 0x00000008; 752 753 /** 754 * Mask for use with setFlags indicating bits used for visibility. 755 * {@hide} 756 */ 757 static final int VISIBILITY_MASK = 0x0000000C; 758 759 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 760 761 /** 762 * This view is enabled. Interpretation varies by subclass. 763 * Use with ENABLED_MASK when calling setFlags. 764 * {@hide} 765 */ 766 static final int ENABLED = 0x00000000; 767 768 /** 769 * This view is disabled. Interpretation varies by subclass. 770 * Use with ENABLED_MASK when calling setFlags. 771 * {@hide} 772 */ 773 static final int DISABLED = 0x00000020; 774 775 /** 776 * Mask for use with setFlags indicating bits used for indicating whether 777 * this view is enabled 778 * {@hide} 779 */ 780 static final int ENABLED_MASK = 0x00000020; 781 782 /** 783 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 784 * called and further optimizations will be performed. It is okay to have 785 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 786 * {@hide} 787 */ 788 static final int WILL_NOT_DRAW = 0x00000080; 789 790 /** 791 * Mask for use with setFlags indicating bits used for indicating whether 792 * this view is will draw 793 * {@hide} 794 */ 795 static final int DRAW_MASK = 0x00000080; 796 797 /** 798 * <p>This view doesn't show scrollbars.</p> 799 * {@hide} 800 */ 801 static final int SCROLLBARS_NONE = 0x00000000; 802 803 /** 804 * <p>This view shows horizontal scrollbars.</p> 805 * {@hide} 806 */ 807 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 808 809 /** 810 * <p>This view shows vertical scrollbars.</p> 811 * {@hide} 812 */ 813 static final int SCROLLBARS_VERTICAL = 0x00000200; 814 815 /** 816 * <p>Mask for use with setFlags indicating bits used for indicating which 817 * scrollbars are enabled.</p> 818 * {@hide} 819 */ 820 static final int SCROLLBARS_MASK = 0x00000300; 821 822 /** 823 * Indicates that the view should filter touches when its window is obscured. 824 * Refer to the class comments for more information about this security feature. 825 * {@hide} 826 */ 827 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 828 829 /** 830 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 831 * that they are optional and should be skipped if the window has 832 * requested system UI flags that ignore those insets for layout. 833 */ 834 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 835 836 /** 837 * <p>This view doesn't show fading edges.</p> 838 * {@hide} 839 */ 840 static final int FADING_EDGE_NONE = 0x00000000; 841 842 /** 843 * <p>This view shows horizontal fading edges.</p> 844 * {@hide} 845 */ 846 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 847 848 /** 849 * <p>This view shows vertical fading edges.</p> 850 * {@hide} 851 */ 852 static final int FADING_EDGE_VERTICAL = 0x00002000; 853 854 /** 855 * <p>Mask for use with setFlags indicating bits used for indicating which 856 * fading edges are enabled.</p> 857 * {@hide} 858 */ 859 static final int FADING_EDGE_MASK = 0x00003000; 860 861 /** 862 * <p>Indicates this view can be clicked. When clickable, a View reacts 863 * to clicks by notifying the OnClickListener.<p> 864 * {@hide} 865 */ 866 static final int CLICKABLE = 0x00004000; 867 868 /** 869 * <p>Indicates this view is caching its drawing into a bitmap.</p> 870 * {@hide} 871 */ 872 static final int DRAWING_CACHE_ENABLED = 0x00008000; 873 874 /** 875 * <p>Indicates that no icicle should be saved for this view.<p> 876 * {@hide} 877 */ 878 static final int SAVE_DISABLED = 0x000010000; 879 880 /** 881 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 882 * property.</p> 883 * {@hide} 884 */ 885 static final int SAVE_DISABLED_MASK = 0x000010000; 886 887 /** 888 * <p>Indicates that no drawing cache should ever be created for this view.<p> 889 * {@hide} 890 */ 891 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 892 893 /** 894 * <p>Indicates this view can take / keep focus when int touch mode.</p> 895 * {@hide} 896 */ 897 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 898 899 /** 900 * <p>Enables low quality mode for the drawing cache.</p> 901 */ 902 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 903 904 /** 905 * <p>Enables high quality mode for the drawing cache.</p> 906 */ 907 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 908 909 /** 910 * <p>Enables automatic quality mode for the drawing cache.</p> 911 */ 912 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 913 914 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 915 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 916 }; 917 918 /** 919 * <p>Mask for use with setFlags indicating bits used for the cache 920 * quality property.</p> 921 * {@hide} 922 */ 923 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 924 925 /** 926 * <p> 927 * Indicates this view can be long clicked. When long clickable, a View 928 * reacts to long clicks by notifying the OnLongClickListener or showing a 929 * context menu. 930 * </p> 931 * {@hide} 932 */ 933 static final int LONG_CLICKABLE = 0x00200000; 934 935 /** 936 * <p>Indicates that this view gets its drawable states from its direct parent 937 * and ignores its original internal states.</p> 938 * 939 * @hide 940 */ 941 static final int DUPLICATE_PARENT_STATE = 0x00400000; 942 943 /** 944 * The scrollbar style to display the scrollbars inside the content area, 945 * without increasing the padding. The scrollbars will be overlaid with 946 * translucency on the view's content. 947 */ 948 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 949 950 /** 951 * The scrollbar style to display the scrollbars inside the padded area, 952 * increasing the padding of the view. The scrollbars will not overlap the 953 * content area of the view. 954 */ 955 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 956 957 /** 958 * The scrollbar style to display the scrollbars at the edge of the view, 959 * without increasing the padding. The scrollbars will be overlaid with 960 * translucency. 961 */ 962 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 963 964 /** 965 * The scrollbar style to display the scrollbars at the edge of the view, 966 * increasing the padding of the view. The scrollbars will only overlap the 967 * background, if any. 968 */ 969 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 970 971 /** 972 * Mask to check if the scrollbar style is overlay or inset. 973 * {@hide} 974 */ 975 static final int SCROLLBARS_INSET_MASK = 0x01000000; 976 977 /** 978 * Mask to check if the scrollbar style is inside or outside. 979 * {@hide} 980 */ 981 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 982 983 /** 984 * Mask for scrollbar style. 985 * {@hide} 986 */ 987 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 988 989 /** 990 * View flag indicating that the screen should remain on while the 991 * window containing this view is visible to the user. This effectively 992 * takes care of automatically setting the WindowManager's 993 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 994 */ 995 public static final int KEEP_SCREEN_ON = 0x04000000; 996 997 /** 998 * View flag indicating whether this view should have sound effects enabled 999 * for events such as clicking and touching. 1000 */ 1001 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1002 1003 /** 1004 * View flag indicating whether this view should have haptic feedback 1005 * enabled for events such as long presses. 1006 */ 1007 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1008 1009 /** 1010 * <p>Indicates that the view hierarchy should stop saving state when 1011 * it reaches this view. If state saving is initiated immediately at 1012 * the view, it will be allowed. 1013 * {@hide} 1014 */ 1015 static final int PARENT_SAVE_DISABLED = 0x20000000; 1016 1017 /** 1018 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1019 * {@hide} 1020 */ 1021 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1022 1023 /** 1024 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1025 * should add all focusable Views regardless if they are focusable in touch mode. 1026 */ 1027 public static final int FOCUSABLES_ALL = 0x00000000; 1028 1029 /** 1030 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1031 * should add only Views focusable in touch mode. 1032 */ 1033 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1034 1035 /** 1036 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1037 * item. 1038 */ 1039 public static final int FOCUS_BACKWARD = 0x00000001; 1040 1041 /** 1042 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1043 * item. 1044 */ 1045 public static final int FOCUS_FORWARD = 0x00000002; 1046 1047 /** 1048 * Use with {@link #focusSearch(int)}. Move focus to the left. 1049 */ 1050 public static final int FOCUS_LEFT = 0x00000011; 1051 1052 /** 1053 * Use with {@link #focusSearch(int)}. Move focus up. 1054 */ 1055 public static final int FOCUS_UP = 0x00000021; 1056 1057 /** 1058 * Use with {@link #focusSearch(int)}. Move focus to the right. 1059 */ 1060 public static final int FOCUS_RIGHT = 0x00000042; 1061 1062 /** 1063 * Use with {@link #focusSearch(int)}. Move focus down. 1064 */ 1065 public static final int FOCUS_DOWN = 0x00000082; 1066 1067 /** 1068 * Bits of {@link #getMeasuredWidthAndState()} and 1069 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1070 */ 1071 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1072 1073 /** 1074 * Bits of {@link #getMeasuredWidthAndState()} and 1075 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1076 */ 1077 public static final int MEASURED_STATE_MASK = 0xff000000; 1078 1079 /** 1080 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1081 * for functions that combine both width and height into a single int, 1082 * such as {@link #getMeasuredState()} and the childState argument of 1083 * {@link #resolveSizeAndState(int, int, int)}. 1084 */ 1085 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1086 1087 /** 1088 * Bit of {@link #getMeasuredWidthAndState()} and 1089 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1090 * is smaller that the space the view would like to have. 1091 */ 1092 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1093 1094 /** 1095 * Base View state sets 1096 */ 1097 // Singles 1098 /** 1099 * Indicates the view has no states set. States are used with 1100 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1101 * view depending on its state. 1102 * 1103 * @see android.graphics.drawable.Drawable 1104 * @see #getDrawableState() 1105 */ 1106 protected static final int[] EMPTY_STATE_SET; 1107 /** 1108 * Indicates the view is enabled. States are used with 1109 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1110 * view depending on its state. 1111 * 1112 * @see android.graphics.drawable.Drawable 1113 * @see #getDrawableState() 1114 */ 1115 protected static final int[] ENABLED_STATE_SET; 1116 /** 1117 * Indicates the view is focused. States are used with 1118 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1119 * view depending on its state. 1120 * 1121 * @see android.graphics.drawable.Drawable 1122 * @see #getDrawableState() 1123 */ 1124 protected static final int[] FOCUSED_STATE_SET; 1125 /** 1126 * Indicates the view is selected. States are used with 1127 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1128 * view depending on its state. 1129 * 1130 * @see android.graphics.drawable.Drawable 1131 * @see #getDrawableState() 1132 */ 1133 protected static final int[] SELECTED_STATE_SET; 1134 /** 1135 * Indicates the view is pressed. States are used with 1136 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1137 * view depending on its state. 1138 * 1139 * @see android.graphics.drawable.Drawable 1140 * @see #getDrawableState() 1141 */ 1142 protected static final int[] PRESSED_STATE_SET; 1143 /** 1144 * Indicates the view's window has focus. States are used with 1145 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1146 * view depending on its state. 1147 * 1148 * @see android.graphics.drawable.Drawable 1149 * @see #getDrawableState() 1150 */ 1151 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1152 // Doubles 1153 /** 1154 * Indicates the view is enabled and has the focus. 1155 * 1156 * @see #ENABLED_STATE_SET 1157 * @see #FOCUSED_STATE_SET 1158 */ 1159 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1160 /** 1161 * Indicates the view is enabled and selected. 1162 * 1163 * @see #ENABLED_STATE_SET 1164 * @see #SELECTED_STATE_SET 1165 */ 1166 protected static final int[] ENABLED_SELECTED_STATE_SET; 1167 /** 1168 * Indicates the view is enabled and that its window has focus. 1169 * 1170 * @see #ENABLED_STATE_SET 1171 * @see #WINDOW_FOCUSED_STATE_SET 1172 */ 1173 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1174 /** 1175 * Indicates the view is focused and selected. 1176 * 1177 * @see #FOCUSED_STATE_SET 1178 * @see #SELECTED_STATE_SET 1179 */ 1180 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1181 /** 1182 * Indicates the view has the focus and that its window has the focus. 1183 * 1184 * @see #FOCUSED_STATE_SET 1185 * @see #WINDOW_FOCUSED_STATE_SET 1186 */ 1187 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1188 /** 1189 * Indicates the view is selected and that its window has the focus. 1190 * 1191 * @see #SELECTED_STATE_SET 1192 * @see #WINDOW_FOCUSED_STATE_SET 1193 */ 1194 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1195 // Triples 1196 /** 1197 * Indicates the view is enabled, focused and selected. 1198 * 1199 * @see #ENABLED_STATE_SET 1200 * @see #FOCUSED_STATE_SET 1201 * @see #SELECTED_STATE_SET 1202 */ 1203 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1204 /** 1205 * Indicates the view is enabled, focused and its window has the focus. 1206 * 1207 * @see #ENABLED_STATE_SET 1208 * @see #FOCUSED_STATE_SET 1209 * @see #WINDOW_FOCUSED_STATE_SET 1210 */ 1211 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1212 /** 1213 * Indicates the view is enabled, selected and its window has the focus. 1214 * 1215 * @see #ENABLED_STATE_SET 1216 * @see #SELECTED_STATE_SET 1217 * @see #WINDOW_FOCUSED_STATE_SET 1218 */ 1219 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1220 /** 1221 * Indicates the view is focused, selected and its window has the focus. 1222 * 1223 * @see #FOCUSED_STATE_SET 1224 * @see #SELECTED_STATE_SET 1225 * @see #WINDOW_FOCUSED_STATE_SET 1226 */ 1227 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1228 /** 1229 * Indicates the view is enabled, focused, selected and its window 1230 * has the focus. 1231 * 1232 * @see #ENABLED_STATE_SET 1233 * @see #FOCUSED_STATE_SET 1234 * @see #SELECTED_STATE_SET 1235 * @see #WINDOW_FOCUSED_STATE_SET 1236 */ 1237 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1238 /** 1239 * Indicates the view is pressed and its window has the focus. 1240 * 1241 * @see #PRESSED_STATE_SET 1242 * @see #WINDOW_FOCUSED_STATE_SET 1243 */ 1244 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1245 /** 1246 * Indicates the view is pressed and selected. 1247 * 1248 * @see #PRESSED_STATE_SET 1249 * @see #SELECTED_STATE_SET 1250 */ 1251 protected static final int[] PRESSED_SELECTED_STATE_SET; 1252 /** 1253 * Indicates the view is pressed, selected and its window has the focus. 1254 * 1255 * @see #PRESSED_STATE_SET 1256 * @see #SELECTED_STATE_SET 1257 * @see #WINDOW_FOCUSED_STATE_SET 1258 */ 1259 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1260 /** 1261 * Indicates the view is pressed and focused. 1262 * 1263 * @see #PRESSED_STATE_SET 1264 * @see #FOCUSED_STATE_SET 1265 */ 1266 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1267 /** 1268 * Indicates the view is pressed, focused and its window has the focus. 1269 * 1270 * @see #PRESSED_STATE_SET 1271 * @see #FOCUSED_STATE_SET 1272 * @see #WINDOW_FOCUSED_STATE_SET 1273 */ 1274 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1275 /** 1276 * Indicates the view is pressed, focused and selected. 1277 * 1278 * @see #PRESSED_STATE_SET 1279 * @see #SELECTED_STATE_SET 1280 * @see #FOCUSED_STATE_SET 1281 */ 1282 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1283 /** 1284 * Indicates the view is pressed, focused, selected and its window has the focus. 1285 * 1286 * @see #PRESSED_STATE_SET 1287 * @see #FOCUSED_STATE_SET 1288 * @see #SELECTED_STATE_SET 1289 * @see #WINDOW_FOCUSED_STATE_SET 1290 */ 1291 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1292 /** 1293 * Indicates the view is pressed and enabled. 1294 * 1295 * @see #PRESSED_STATE_SET 1296 * @see #ENABLED_STATE_SET 1297 */ 1298 protected static final int[] PRESSED_ENABLED_STATE_SET; 1299 /** 1300 * Indicates the view is pressed, enabled and its window has the focus. 1301 * 1302 * @see #PRESSED_STATE_SET 1303 * @see #ENABLED_STATE_SET 1304 * @see #WINDOW_FOCUSED_STATE_SET 1305 */ 1306 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1307 /** 1308 * Indicates the view is pressed, enabled and selected. 1309 * 1310 * @see #PRESSED_STATE_SET 1311 * @see #ENABLED_STATE_SET 1312 * @see #SELECTED_STATE_SET 1313 */ 1314 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1315 /** 1316 * Indicates the view is pressed, enabled, selected and its window has the 1317 * focus. 1318 * 1319 * @see #PRESSED_STATE_SET 1320 * @see #ENABLED_STATE_SET 1321 * @see #SELECTED_STATE_SET 1322 * @see #WINDOW_FOCUSED_STATE_SET 1323 */ 1324 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1325 /** 1326 * Indicates the view is pressed, enabled and focused. 1327 * 1328 * @see #PRESSED_STATE_SET 1329 * @see #ENABLED_STATE_SET 1330 * @see #FOCUSED_STATE_SET 1331 */ 1332 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1333 /** 1334 * Indicates the view is pressed, enabled, focused and its window has the 1335 * focus. 1336 * 1337 * @see #PRESSED_STATE_SET 1338 * @see #ENABLED_STATE_SET 1339 * @see #FOCUSED_STATE_SET 1340 * @see #WINDOW_FOCUSED_STATE_SET 1341 */ 1342 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1343 /** 1344 * Indicates the view is pressed, enabled, focused and selected. 1345 * 1346 * @see #PRESSED_STATE_SET 1347 * @see #ENABLED_STATE_SET 1348 * @see #SELECTED_STATE_SET 1349 * @see #FOCUSED_STATE_SET 1350 */ 1351 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1352 /** 1353 * Indicates the view is pressed, enabled, focused, selected and its window 1354 * has the focus. 1355 * 1356 * @see #PRESSED_STATE_SET 1357 * @see #ENABLED_STATE_SET 1358 * @see #SELECTED_STATE_SET 1359 * @see #FOCUSED_STATE_SET 1360 * @see #WINDOW_FOCUSED_STATE_SET 1361 */ 1362 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1363 1364 /** 1365 * The order here is very important to {@link #getDrawableState()} 1366 */ 1367 private static final int[][] VIEW_STATE_SETS; 1368 1369 static final int VIEW_STATE_WINDOW_FOCUSED = 1; 1370 static final int VIEW_STATE_SELECTED = 1 << 1; 1371 static final int VIEW_STATE_FOCUSED = 1 << 2; 1372 static final int VIEW_STATE_ENABLED = 1 << 3; 1373 static final int VIEW_STATE_PRESSED = 1 << 4; 1374 static final int VIEW_STATE_ACTIVATED = 1 << 5; 1375 static final int VIEW_STATE_ACCELERATED = 1 << 6; 1376 static final int VIEW_STATE_HOVERED = 1 << 7; 1377 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8; 1378 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9; 1379 1380 static final int[] VIEW_STATE_IDS = new int[] { 1381 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED, 1382 R.attr.state_selected, VIEW_STATE_SELECTED, 1383 R.attr.state_focused, VIEW_STATE_FOCUSED, 1384 R.attr.state_enabled, VIEW_STATE_ENABLED, 1385 R.attr.state_pressed, VIEW_STATE_PRESSED, 1386 R.attr.state_activated, VIEW_STATE_ACTIVATED, 1387 R.attr.state_accelerated, VIEW_STATE_ACCELERATED, 1388 R.attr.state_hovered, VIEW_STATE_HOVERED, 1389 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT, 1390 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED 1391 }; 1392 1393 static { 1394 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) { 1395 throw new IllegalStateException( 1396 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array"); 1397 } 1398 int[] orderedIds = new int[VIEW_STATE_IDS.length]; 1399 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) { 1400 int viewState = R.styleable.ViewDrawableStates[i]; 1401 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) { 1402 if (VIEW_STATE_IDS[j] == viewState) { 1403 orderedIds[i * 2] = viewState; 1404 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1]; 1405 } 1406 } 1407 } 1408 final int NUM_BITS = VIEW_STATE_IDS.length / 2; 1409 VIEW_STATE_SETS = new int[1 << NUM_BITS][]; 1410 for (int i = 0; i < VIEW_STATE_SETS.length; i++) { 1411 int numBits = Integer.bitCount(i); 1412 int[] set = new int[numBits]; 1413 int pos = 0; 1414 for (int j = 0; j < orderedIds.length; j += 2) { 1415 if ((i & orderedIds[j+1]) != 0) { 1416 set[pos++] = orderedIds[j]; 1417 } 1418 } 1419 VIEW_STATE_SETS[i] = set; 1420 } 1421 1422 EMPTY_STATE_SET = VIEW_STATE_SETS[0]; 1423 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED]; 1424 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED]; 1425 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1426 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED]; 1427 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED]; 1428 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1429 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED]; 1430 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1431 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED]; 1432 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1433 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1434 | VIEW_STATE_FOCUSED]; 1435 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED]; 1436 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1437 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED]; 1438 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1439 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED]; 1440 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1441 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1442 | VIEW_STATE_ENABLED]; 1443 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1444 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED]; 1445 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1446 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1447 | VIEW_STATE_ENABLED]; 1448 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1449 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1450 | VIEW_STATE_ENABLED]; 1451 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1452 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1453 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED]; 1454 1455 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED]; 1456 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1457 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED]; 1458 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1459 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED]; 1460 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1461 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1462 | VIEW_STATE_PRESSED]; 1463 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1464 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1465 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1466 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1467 | VIEW_STATE_PRESSED]; 1468 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1469 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1470 | VIEW_STATE_PRESSED]; 1471 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1472 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1473 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1474 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[ 1475 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1476 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1477 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED 1478 | VIEW_STATE_PRESSED]; 1479 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1480 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED 1481 | VIEW_STATE_PRESSED]; 1482 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1483 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1484 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1485 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1486 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED 1487 | VIEW_STATE_PRESSED]; 1488 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1489 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1490 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1491 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1492 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1493 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1494 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1495 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1496 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED 1497 | VIEW_STATE_PRESSED]; 1498 } 1499 1500 /** 1501 * Accessibility event types that are dispatched for text population. 1502 */ 1503 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1504 AccessibilityEvent.TYPE_VIEW_CLICKED 1505 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1506 | AccessibilityEvent.TYPE_VIEW_SELECTED 1507 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1508 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1509 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1510 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 1511 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 1512 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 1513 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 1514 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 1515 1516 /** 1517 * Temporary Rect currently for use in setBackground(). This will probably 1518 * be extended in the future to hold our own class with more than just 1519 * a Rect. :) 1520 */ 1521 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1522 1523 /** 1524 * Map used to store views' tags. 1525 */ 1526 private SparseArray<Object> mKeyedTags; 1527 1528 /** 1529 * The next available accessibility id. 1530 */ 1531 private static int sNextAccessibilityViewId; 1532 1533 /** 1534 * The animation currently associated with this view. 1535 * @hide 1536 */ 1537 protected Animation mCurrentAnimation = null; 1538 1539 /** 1540 * Width as measured during measure pass. 1541 * {@hide} 1542 */ 1543 @ViewDebug.ExportedProperty(category = "measurement") 1544 int mMeasuredWidth; 1545 1546 /** 1547 * Height as measured during measure pass. 1548 * {@hide} 1549 */ 1550 @ViewDebug.ExportedProperty(category = "measurement") 1551 int mMeasuredHeight; 1552 1553 /** 1554 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1555 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1556 * its display list. This flag, used only when hw accelerated, allows us to clear the 1557 * flag while retaining this information until it's needed (at getDisplayList() time and 1558 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1559 * 1560 * {@hide} 1561 */ 1562 boolean mRecreateDisplayList = false; 1563 1564 /** 1565 * The view's identifier. 1566 * {@hide} 1567 * 1568 * @see #setId(int) 1569 * @see #getId() 1570 */ 1571 @ViewDebug.ExportedProperty(resolveId = true) 1572 int mID = NO_ID; 1573 1574 /** 1575 * The stable ID of this view for accessibility purposes. 1576 */ 1577 int mAccessibilityViewId = NO_ID; 1578 1579 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 1580 1581 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent; 1582 1583 /** 1584 * The view's tag. 1585 * {@hide} 1586 * 1587 * @see #setTag(Object) 1588 * @see #getTag() 1589 */ 1590 protected Object mTag; 1591 1592 // for mPrivateFlags: 1593 /** {@hide} */ 1594 static final int PFLAG_WANTS_FOCUS = 0x00000001; 1595 /** {@hide} */ 1596 static final int PFLAG_FOCUSED = 0x00000002; 1597 /** {@hide} */ 1598 static final int PFLAG_SELECTED = 0x00000004; 1599 /** {@hide} */ 1600 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 1601 /** {@hide} */ 1602 static final int PFLAG_HAS_BOUNDS = 0x00000010; 1603 /** {@hide} */ 1604 static final int PFLAG_DRAWN = 0x00000020; 1605 /** 1606 * When this flag is set, this view is running an animation on behalf of its 1607 * children and should therefore not cancel invalidate requests, even if they 1608 * lie outside of this view's bounds. 1609 * 1610 * {@hide} 1611 */ 1612 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 1613 /** {@hide} */ 1614 static final int PFLAG_SKIP_DRAW = 0x00000080; 1615 /** {@hide} */ 1616 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100; 1617 /** {@hide} */ 1618 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1619 /** {@hide} */ 1620 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 1621 /** {@hide} */ 1622 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 1623 /** {@hide} */ 1624 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 1625 /** {@hide} */ 1626 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 1627 1628 private static final int PFLAG_PRESSED = 0x00004000; 1629 1630 /** {@hide} */ 1631 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 1632 /** 1633 * Flag used to indicate that this view should be drawn once more (and only once 1634 * more) after its animation has completed. 1635 * {@hide} 1636 */ 1637 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 1638 1639 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 1640 1641 /** 1642 * Indicates that the View returned true when onSetAlpha() was called and that 1643 * the alpha must be restored. 1644 * {@hide} 1645 */ 1646 static final int PFLAG_ALPHA_SET = 0x00040000; 1647 1648 /** 1649 * Set by {@link #setScrollContainer(boolean)}. 1650 */ 1651 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 1652 1653 /** 1654 * Set by {@link #setScrollContainer(boolean)}. 1655 */ 1656 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 1657 1658 /** 1659 * View flag indicating whether this view was invalidated (fully or partially.) 1660 * 1661 * @hide 1662 */ 1663 static final int PFLAG_DIRTY = 0x00200000; 1664 1665 /** 1666 * View flag indicating whether this view was invalidated by an opaque 1667 * invalidate request. 1668 * 1669 * @hide 1670 */ 1671 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 1672 1673 /** 1674 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 1675 * 1676 * @hide 1677 */ 1678 static final int PFLAG_DIRTY_MASK = 0x00600000; 1679 1680 /** 1681 * Indicates whether the background is opaque. 1682 * 1683 * @hide 1684 */ 1685 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 1686 1687 /** 1688 * Indicates whether the scrollbars are opaque. 1689 * 1690 * @hide 1691 */ 1692 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 1693 1694 /** 1695 * Indicates whether the view is opaque. 1696 * 1697 * @hide 1698 */ 1699 static final int PFLAG_OPAQUE_MASK = 0x01800000; 1700 1701 /** 1702 * Indicates a prepressed state; 1703 * the short time between ACTION_DOWN and recognizing 1704 * a 'real' press. Prepressed is used to recognize quick taps 1705 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1706 * 1707 * @hide 1708 */ 1709 private static final int PFLAG_PREPRESSED = 0x02000000; 1710 1711 /** 1712 * Indicates whether the view is temporarily detached. 1713 * 1714 * @hide 1715 */ 1716 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 1717 1718 /** 1719 * Indicates that we should awaken scroll bars once attached 1720 * 1721 * @hide 1722 */ 1723 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1724 1725 /** 1726 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1727 * @hide 1728 */ 1729 private static final int PFLAG_HOVERED = 0x10000000; 1730 1731 /** 1732 * Indicates that pivotX or pivotY were explicitly set and we should not assume the center 1733 * for transform operations 1734 * 1735 * @hide 1736 */ 1737 private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000; 1738 1739 /** {@hide} */ 1740 static final int PFLAG_ACTIVATED = 0x40000000; 1741 1742 /** 1743 * Indicates that this view was specifically invalidated, not just dirtied because some 1744 * child view was invalidated. The flag is used to determine when we need to recreate 1745 * a view's display list (as opposed to just returning a reference to its existing 1746 * display list). 1747 * 1748 * @hide 1749 */ 1750 static final int PFLAG_INVALIDATED = 0x80000000; 1751 1752 /** 1753 * Masks for mPrivateFlags2, as generated by dumpFlags(): 1754 * 1755 * |-------|-------|-------|-------| 1756 * 1 PFLAG2_DRAG_CAN_ACCEPT 1757 * 1 PFLAG2_DRAG_HOVERED 1758 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 1759 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 1760 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 1761 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 1762 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 1763 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 1764 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 1765 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 1766 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 1767 * 111 PFLAG2_TEXT_DIRECTION_MASK 1768 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 1769 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 1770 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 1771 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 1772 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 1773 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 1774 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 1775 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 1776 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 1777 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 1778 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 1779 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 1780 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 1781 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 1782 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 1783 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 1784 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 1785 * 1 PFLAG2_VIEW_QUICK_REJECTED 1786 * 1 PFLAG2_PADDING_RESOLVED 1787 * 1 PFLAG2_DRAWABLE_RESOLVED 1788 * 1 PFLAG2_HAS_TRANSIENT_STATE 1789 * |-------|-------|-------|-------| 1790 */ 1791 1792 /** 1793 * Indicates that this view has reported that it can accept the current drag's content. 1794 * Cleared when the drag operation concludes. 1795 * @hide 1796 */ 1797 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 1798 1799 /** 1800 * Indicates that this view is currently directly under the drag location in a 1801 * drag-and-drop operation involving content that it can accept. Cleared when 1802 * the drag exits the view, or when the drag operation concludes. 1803 * @hide 1804 */ 1805 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 1806 1807 /** 1808 * Horizontal layout direction of this view is from Left to Right. 1809 * Use with {@link #setLayoutDirection}. 1810 */ 1811 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 1812 1813 /** 1814 * Horizontal layout direction of this view is from Right to Left. 1815 * Use with {@link #setLayoutDirection}. 1816 */ 1817 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 1818 1819 /** 1820 * Horizontal layout direction of this view is inherited from its parent. 1821 * Use with {@link #setLayoutDirection}. 1822 */ 1823 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 1824 1825 /** 1826 * Horizontal layout direction of this view is from deduced from the default language 1827 * script for the locale. Use with {@link #setLayoutDirection}. 1828 */ 1829 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 1830 1831 /** 1832 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1833 * @hide 1834 */ 1835 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 1836 1837 /** 1838 * Mask for use with private flags indicating bits used for horizontal layout direction. 1839 * @hide 1840 */ 1841 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1842 1843 /** 1844 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 1845 * right-to-left direction. 1846 * @hide 1847 */ 1848 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1849 1850 /** 1851 * Indicates whether the view horizontal layout direction has been resolved. 1852 * @hide 1853 */ 1854 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1855 1856 /** 1857 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 1858 * @hide 1859 */ 1860 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 1861 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1862 1863 /* 1864 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 1865 * flag value. 1866 * @hide 1867 */ 1868 private static final int[] LAYOUT_DIRECTION_FLAGS = { 1869 LAYOUT_DIRECTION_LTR, 1870 LAYOUT_DIRECTION_RTL, 1871 LAYOUT_DIRECTION_INHERIT, 1872 LAYOUT_DIRECTION_LOCALE 1873 }; 1874 1875 /** 1876 * Default horizontal layout direction. 1877 */ 1878 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 1879 1880 /** 1881 * Default horizontal layout direction. 1882 * @hide 1883 */ 1884 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 1885 1886 /** 1887 * Text direction is inherited thru {@link ViewGroup} 1888 */ 1889 public static final int TEXT_DIRECTION_INHERIT = 0; 1890 1891 /** 1892 * Text direction is using "first strong algorithm". The first strong directional character 1893 * determines the paragraph direction. If there is no strong directional character, the 1894 * paragraph direction is the view's resolved layout direction. 1895 */ 1896 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 1897 1898 /** 1899 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 1900 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 1901 * If there are neither, the paragraph direction is the view's resolved layout direction. 1902 */ 1903 public static final int TEXT_DIRECTION_ANY_RTL = 2; 1904 1905 /** 1906 * Text direction is forced to LTR. 1907 */ 1908 public static final int TEXT_DIRECTION_LTR = 3; 1909 1910 /** 1911 * Text direction is forced to RTL. 1912 */ 1913 public static final int TEXT_DIRECTION_RTL = 4; 1914 1915 /** 1916 * Text direction is coming from the system Locale. 1917 */ 1918 public static final int TEXT_DIRECTION_LOCALE = 5; 1919 1920 /** 1921 * Default text direction is inherited 1922 */ 1923 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 1924 1925 /** 1926 * Default resolved text direction 1927 * @hide 1928 */ 1929 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 1930 1931 /** 1932 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 1933 * @hide 1934 */ 1935 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 1936 1937 /** 1938 * Mask for use with private flags indicating bits used for text direction. 1939 * @hide 1940 */ 1941 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 1942 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 1943 1944 /** 1945 * Array of text direction flags for mapping attribute "textDirection" to correct 1946 * flag value. 1947 * @hide 1948 */ 1949 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 1950 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 1951 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 1952 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 1953 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 1954 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 1955 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 1956 }; 1957 1958 /** 1959 * Indicates whether the view text direction has been resolved. 1960 * @hide 1961 */ 1962 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 1963 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 1964 1965 /** 1966 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1967 * @hide 1968 */ 1969 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 1970 1971 /** 1972 * Mask for use with private flags indicating bits used for resolved text direction. 1973 * @hide 1974 */ 1975 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 1976 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 1977 1978 /** 1979 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 1980 * @hide 1981 */ 1982 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 1983 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 1984 1985 /* 1986 * Default text alignment. The text alignment of this View is inherited from its parent. 1987 * Use with {@link #setTextAlignment(int)} 1988 */ 1989 public static final int TEXT_ALIGNMENT_INHERIT = 0; 1990 1991 /** 1992 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 1993 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraphs text direction. 1994 * 1995 * Use with {@link #setTextAlignment(int)} 1996 */ 1997 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 1998 1999 /** 2000 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2001 * 2002 * Use with {@link #setTextAlignment(int)} 2003 */ 2004 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2005 2006 /** 2007 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2008 * 2009 * Use with {@link #setTextAlignment(int)} 2010 */ 2011 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2012 2013 /** 2014 * Center the paragraph, e.g. ALIGN_CENTER. 2015 * 2016 * Use with {@link #setTextAlignment(int)} 2017 */ 2018 public static final int TEXT_ALIGNMENT_CENTER = 4; 2019 2020 /** 2021 * Align to the start of the view, which is ALIGN_LEFT if the views resolved 2022 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2023 * 2024 * Use with {@link #setTextAlignment(int)} 2025 */ 2026 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2027 2028 /** 2029 * Align to the end of the view, which is ALIGN_RIGHT if the views resolved 2030 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2031 * 2032 * Use with {@link #setTextAlignment(int)} 2033 */ 2034 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2035 2036 /** 2037 * Default text alignment is inherited 2038 */ 2039 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2040 2041 /** 2042 * Default resolved text alignment 2043 * @hide 2044 */ 2045 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2046 2047 /** 2048 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2049 * @hide 2050 */ 2051 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2052 2053 /** 2054 * Mask for use with private flags indicating bits used for text alignment. 2055 * @hide 2056 */ 2057 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2058 2059 /** 2060 * Array of text direction flags for mapping attribute "textAlignment" to correct 2061 * flag value. 2062 * @hide 2063 */ 2064 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2065 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2066 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2067 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2068 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2069 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2070 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2071 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2072 }; 2073 2074 /** 2075 * Indicates whether the view text alignment has been resolved. 2076 * @hide 2077 */ 2078 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2079 2080 /** 2081 * Bit shift to get the resolved text alignment. 2082 * @hide 2083 */ 2084 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2085 2086 /** 2087 * Mask for use with private flags indicating bits used for text alignment. 2088 * @hide 2089 */ 2090 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2091 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2092 2093 /** 2094 * Indicates whether if the view text alignment has been resolved to gravity 2095 */ 2096 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2097 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2098 2099 // Accessiblity constants for mPrivateFlags2 2100 2101 /** 2102 * Shift for the bits in {@link #mPrivateFlags2} related to the 2103 * "importantForAccessibility" attribute. 2104 */ 2105 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2106 2107 /** 2108 * Automatically determine whether a view is important for accessibility. 2109 */ 2110 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2111 2112 /** 2113 * The view is important for accessibility. 2114 */ 2115 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2116 2117 /** 2118 * The view is not important for accessibility. 2119 */ 2120 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2121 2122 /** 2123 * The view is not important for accessibility, nor are any of its 2124 * descendant views. 2125 */ 2126 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2127 2128 /** 2129 * The default whether the view is important for accessibility. 2130 */ 2131 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2132 2133 /** 2134 * Mask for obtainig the bits which specify how to determine 2135 * whether a view is important for accessibility. 2136 */ 2137 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2138 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2139 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2140 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2141 2142 /** 2143 * Shift for the bits in {@link #mPrivateFlags2} related to the 2144 * "accessibilityLiveRegion" attribute. 2145 */ 2146 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2147 2148 /** 2149 * Live region mode specifying that accessibility services should not 2150 * automatically announce changes to this view. This is the default live 2151 * region mode for most views. 2152 * <p> 2153 * Use with {@link #setAccessibilityLiveRegion(int)}. 2154 */ 2155 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2156 2157 /** 2158 * Live region mode specifying that accessibility services should announce 2159 * changes to this view. 2160 * <p> 2161 * Use with {@link #setAccessibilityLiveRegion(int)}. 2162 */ 2163 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2164 2165 /** 2166 * Live region mode specifying that accessibility services should interrupt 2167 * ongoing speech to immediately announce changes to this view. 2168 * <p> 2169 * Use with {@link #setAccessibilityLiveRegion(int)}. 2170 */ 2171 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2172 2173 /** 2174 * The default whether the view is important for accessibility. 2175 */ 2176 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2177 2178 /** 2179 * Mask for obtaining the bits which specify a view's accessibility live 2180 * region mode. 2181 */ 2182 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2183 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2184 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2185 2186 /** 2187 * Flag indicating whether a view has accessibility focus. 2188 */ 2189 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2190 2191 /** 2192 * Flag whether the accessibility state of the subtree rooted at this view changed. 2193 */ 2194 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2195 2196 /** 2197 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2198 * is used to check whether later changes to the view's transform should invalidate the 2199 * view to force the quickReject test to run again. 2200 */ 2201 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2202 2203 /** 2204 * Flag indicating that start/end padding has been resolved into left/right padding 2205 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2206 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2207 * during measurement. In some special cases this is required such as when an adapter-based 2208 * view measures prospective children without attaching them to a window. 2209 */ 2210 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2211 2212 /** 2213 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2214 */ 2215 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2216 2217 /** 2218 * Indicates that the view is tracking some sort of transient state 2219 * that the app should not need to be aware of, but that the framework 2220 * should take special care to preserve. 2221 */ 2222 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2223 2224 /** 2225 * Group of bits indicating that RTL properties resolution is done. 2226 */ 2227 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2228 PFLAG2_TEXT_DIRECTION_RESOLVED | 2229 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2230 PFLAG2_PADDING_RESOLVED | 2231 PFLAG2_DRAWABLE_RESOLVED; 2232 2233 // There are a couple of flags left in mPrivateFlags2 2234 2235 /* End of masks for mPrivateFlags2 */ 2236 2237 /* Masks for mPrivateFlags3 */ 2238 2239 /** 2240 * Flag indicating that view has a transform animation set on it. This is used to track whether 2241 * an animation is cleared between successive frames, in order to tell the associated 2242 * DisplayList to clear its animation matrix. 2243 */ 2244 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2245 2246 /** 2247 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2248 * animation is cleared between successive frames, in order to tell the associated 2249 * DisplayList to restore its alpha value. 2250 */ 2251 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2252 2253 /** 2254 * Flag indicating that the view has been through at least one layout since it 2255 * was last attached to a window. 2256 */ 2257 static final int PFLAG3_IS_LAID_OUT = 0x4; 2258 2259 /** 2260 * Flag indicating that a call to measure() was skipped and should be done 2261 * instead when layout() is invoked. 2262 */ 2263 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2264 2265 /** 2266 * Flag indicating that an overridden method correctly called down to 2267 * the superclass implementation as required by the API spec. 2268 */ 2269 static final int PFLAG3_CALLED_SUPER = 0x10; 2270 2271 2272 /* End of masks for mPrivateFlags3 */ 2273 2274 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 2275 2276 /** 2277 * Always allow a user to over-scroll this view, provided it is a 2278 * view that can scroll. 2279 * 2280 * @see #getOverScrollMode() 2281 * @see #setOverScrollMode(int) 2282 */ 2283 public static final int OVER_SCROLL_ALWAYS = 0; 2284 2285 /** 2286 * Allow a user to over-scroll this view only if the content is large 2287 * enough to meaningfully scroll, provided it is a view that can scroll. 2288 * 2289 * @see #getOverScrollMode() 2290 * @see #setOverScrollMode(int) 2291 */ 2292 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 2293 2294 /** 2295 * Never allow a user to over-scroll this view. 2296 * 2297 * @see #getOverScrollMode() 2298 * @see #setOverScrollMode(int) 2299 */ 2300 public static final int OVER_SCROLL_NEVER = 2; 2301 2302 /** 2303 * Special constant for {@link #setSystemUiVisibility(int)}: View has 2304 * requested the system UI (status bar) to be visible (the default). 2305 * 2306 * @see #setSystemUiVisibility(int) 2307 */ 2308 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 2309 2310 /** 2311 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 2312 * system UI to enter an unobtrusive "low profile" mode. 2313 * 2314 * <p>This is for use in games, book readers, video players, or any other 2315 * "immersive" application where the usual system chrome is deemed too distracting. 2316 * 2317 * <p>In low profile mode, the status bar and/or navigation icons may dim. 2318 * 2319 * @see #setSystemUiVisibility(int) 2320 */ 2321 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 2322 2323 /** 2324 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 2325 * system navigation be temporarily hidden. 2326 * 2327 * <p>This is an even less obtrusive state than that called for by 2328 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 2329 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 2330 * those to disappear. This is useful (in conjunction with the 2331 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 2332 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 2333 * window flags) for displaying content using every last pixel on the display. 2334 * 2335 * <p>There is a limitation: because navigation controls are so important, the least user 2336 * interaction will cause them to reappear immediately. When this happens, both 2337 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 2338 * so that both elements reappear at the same time. 2339 * 2340 * @see #setSystemUiVisibility(int) 2341 */ 2342 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 2343 2344 /** 2345 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 2346 * into the normal fullscreen mode so that its content can take over the screen 2347 * while still allowing the user to interact with the application. 2348 * 2349 * <p>This has the same visual effect as 2350 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 2351 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 2352 * meaning that non-critical screen decorations (such as the status bar) will be 2353 * hidden while the user is in the View's window, focusing the experience on 2354 * that content. Unlike the window flag, if you are using ActionBar in 2355 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2356 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 2357 * hide the action bar. 2358 * 2359 * <p>This approach to going fullscreen is best used over the window flag when 2360 * it is a transient state -- that is, the application does this at certain 2361 * points in its user interaction where it wants to allow the user to focus 2362 * on content, but not as a continuous state. For situations where the application 2363 * would like to simply stay full screen the entire time (such as a game that 2364 * wants to take over the screen), the 2365 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 2366 * is usually a better approach. The state set here will be removed by the system 2367 * in various situations (such as the user moving to another application) like 2368 * the other system UI states. 2369 * 2370 * <p>When using this flag, the application should provide some easy facility 2371 * for the user to go out of it. A common example would be in an e-book 2372 * reader, where tapping on the screen brings back whatever screen and UI 2373 * decorations that had been hidden while the user was immersed in reading 2374 * the book. 2375 * 2376 * @see #setSystemUiVisibility(int) 2377 */ 2378 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 2379 2380 /** 2381 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 2382 * flags, we would like a stable view of the content insets given to 2383 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 2384 * will always represent the worst case that the application can expect 2385 * as a continuous state. In the stock Android UI this is the space for 2386 * the system bar, nav bar, and status bar, but not more transient elements 2387 * such as an input method. 2388 * 2389 * The stable layout your UI sees is based on the system UI modes you can 2390 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 2391 * then you will get a stable layout for changes of the 2392 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 2393 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 2394 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 2395 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 2396 * with a stable layout. (Note that you should avoid using 2397 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 2398 * 2399 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 2400 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 2401 * then a hidden status bar will be considered a "stable" state for purposes 2402 * here. This allows your UI to continually hide the status bar, while still 2403 * using the system UI flags to hide the action bar while still retaining 2404 * a stable layout. Note that changing the window fullscreen flag will never 2405 * provide a stable layout for a clean transition. 2406 * 2407 * <p>If you are using ActionBar in 2408 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2409 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 2410 * insets it adds to those given to the application. 2411 */ 2412 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 2413 2414 /** 2415 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2416 * to be layed out as if it has requested 2417 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 2418 * allows it to avoid artifacts when switching in and out of that mode, at 2419 * the expense that some of its user interface may be covered by screen 2420 * decorations when they are shown. You can perform layout of your inner 2421 * UI elements to account for the navigation system UI through the 2422 * {@link #fitSystemWindows(Rect)} method. 2423 */ 2424 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 2425 2426 /** 2427 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2428 * to be layed out as if it has requested 2429 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 2430 * allows it to avoid artifacts when switching in and out of that mode, at 2431 * the expense that some of its user interface may be covered by screen 2432 * decorations when they are shown. You can perform layout of your inner 2433 * UI elements to account for non-fullscreen system UI through the 2434 * {@link #fitSystemWindows(Rect)} method. 2435 */ 2436 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 2437 2438 /** 2439 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2440 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 2441 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 2442 * user interaction. 2443 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 2444 * has an effect when used in combination with that flag.</p> 2445 */ 2446 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 2447 2448 /** 2449 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2450 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 2451 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 2452 * experience while also hiding the system bars. If this flag is not set, 2453 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 2454 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 2455 * if the user swipes from the top of the screen. 2456 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 2457 * system gestures, such as swiping from the top of the screen. These transient system bars 2458 * will overlay apps content, may have some degree of transparency, and will automatically 2459 * hide after a short timeout. 2460 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 2461 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 2462 * with one or both of those flags.</p> 2463 */ 2464 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 2465 2466 /** 2467 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 2468 */ 2469 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 2470 2471 /** 2472 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 2473 */ 2474 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 2475 2476 /** 2477 * @hide 2478 * 2479 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2480 * out of the public fields to keep the undefined bits out of the developer's way. 2481 * 2482 * Flag to make the status bar not expandable. Unless you also 2483 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 2484 */ 2485 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 2486 2487 /** 2488 * @hide 2489 * 2490 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2491 * out of the public fields to keep the undefined bits out of the developer's way. 2492 * 2493 * Flag to hide notification icons and scrolling ticker text. 2494 */ 2495 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 2496 2497 /** 2498 * @hide 2499 * 2500 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2501 * out of the public fields to keep the undefined bits out of the developer's way. 2502 * 2503 * Flag to disable incoming notification alerts. This will not block 2504 * icons, but it will block sound, vibrating and other visual or aural notifications. 2505 */ 2506 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 2507 2508 /** 2509 * @hide 2510 * 2511 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2512 * out of the public fields to keep the undefined bits out of the developer's way. 2513 * 2514 * Flag to hide only the scrolling ticker. Note that 2515 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 2516 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 2517 */ 2518 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 2519 2520 /** 2521 * @hide 2522 * 2523 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2524 * out of the public fields to keep the undefined bits out of the developer's way. 2525 * 2526 * Flag to hide the center system info area. 2527 */ 2528 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 2529 2530 /** 2531 * @hide 2532 * 2533 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2534 * out of the public fields to keep the undefined bits out of the developer's way. 2535 * 2536 * Flag to hide only the home button. Don't use this 2537 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2538 */ 2539 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 2540 2541 /** 2542 * @hide 2543 * 2544 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2545 * out of the public fields to keep the undefined bits out of the developer's way. 2546 * 2547 * Flag to hide only the back button. Don't use this 2548 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2549 */ 2550 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 2551 2552 /** 2553 * @hide 2554 * 2555 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2556 * out of the public fields to keep the undefined bits out of the developer's way. 2557 * 2558 * Flag to hide only the clock. You might use this if your activity has 2559 * its own clock making the status bar's clock redundant. 2560 */ 2561 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 2562 2563 /** 2564 * @hide 2565 * 2566 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2567 * out of the public fields to keep the undefined bits out of the developer's way. 2568 * 2569 * Flag to hide only the recent apps button. Don't use this 2570 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2571 */ 2572 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 2573 2574 /** 2575 * @hide 2576 * 2577 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2578 * out of the public fields to keep the undefined bits out of the developer's way. 2579 * 2580 * Flag to disable the global search gesture. Don't use this 2581 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2582 */ 2583 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 2584 2585 /** 2586 * @hide 2587 * 2588 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2589 * out of the public fields to keep the undefined bits out of the developer's way. 2590 * 2591 * Flag to specify that the status bar is displayed in transient mode. 2592 */ 2593 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 2594 2595 /** 2596 * @hide 2597 * 2598 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2599 * out of the public fields to keep the undefined bits out of the developer's way. 2600 * 2601 * Flag to specify that the navigation bar is displayed in transient mode. 2602 */ 2603 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 2604 2605 /** 2606 * @hide 2607 * 2608 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2609 * out of the public fields to keep the undefined bits out of the developer's way. 2610 * 2611 * Flag to specify that the hidden status bar would like to be shown. 2612 */ 2613 public static final int STATUS_BAR_UNHIDE = 0x10000000; 2614 2615 /** 2616 * @hide 2617 * 2618 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2619 * out of the public fields to keep the undefined bits out of the developer's way. 2620 * 2621 * Flag to specify that the hidden navigation bar would like to be shown. 2622 */ 2623 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 2624 2625 /** 2626 * @hide 2627 * 2628 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2629 * out of the public fields to keep the undefined bits out of the developer's way. 2630 * 2631 * Flag to specify that the status bar is displayed in translucent mode. 2632 */ 2633 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 2634 2635 /** 2636 * @hide 2637 * 2638 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2639 * out of the public fields to keep the undefined bits out of the developer's way. 2640 * 2641 * Flag to specify that the navigation bar is displayed in translucent mode. 2642 */ 2643 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 2644 2645 /** 2646 * @hide 2647 */ 2648 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF; 2649 2650 /** 2651 * These are the system UI flags that can be cleared by events outside 2652 * of an application. Currently this is just the ability to tap on the 2653 * screen while hiding the navigation bar to have it return. 2654 * @hide 2655 */ 2656 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 2657 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 2658 | SYSTEM_UI_FLAG_FULLSCREEN; 2659 2660 /** 2661 * Flags that can impact the layout in relation to system UI. 2662 */ 2663 public static final int SYSTEM_UI_LAYOUT_FLAGS = 2664 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 2665 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 2666 2667 /** 2668 * Find views that render the specified text. 2669 * 2670 * @see #findViewsWithText(ArrayList, CharSequence, int) 2671 */ 2672 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 2673 2674 /** 2675 * Find find views that contain the specified content description. 2676 * 2677 * @see #findViewsWithText(ArrayList, CharSequence, int) 2678 */ 2679 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 2680 2681 /** 2682 * Find views that contain {@link AccessibilityNodeProvider}. Such 2683 * a View is a root of virtual view hierarchy and may contain the searched 2684 * text. If this flag is set Views with providers are automatically 2685 * added and it is a responsibility of the client to call the APIs of 2686 * the provider to determine whether the virtual tree rooted at this View 2687 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 2688 * represeting the virtual views with this text. 2689 * 2690 * @see #findViewsWithText(ArrayList, CharSequence, int) 2691 * 2692 * @hide 2693 */ 2694 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 2695 2696 /** 2697 * The undefined cursor position. 2698 * 2699 * @hide 2700 */ 2701 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 2702 2703 /** 2704 * Indicates that the screen has changed state and is now off. 2705 * 2706 * @see #onScreenStateChanged(int) 2707 */ 2708 public static final int SCREEN_STATE_OFF = 0x0; 2709 2710 /** 2711 * Indicates that the screen has changed state and is now on. 2712 * 2713 * @see #onScreenStateChanged(int) 2714 */ 2715 public static final int SCREEN_STATE_ON = 0x1; 2716 2717 /** 2718 * Controls the over-scroll mode for this view. 2719 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 2720 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 2721 * and {@link #OVER_SCROLL_NEVER}. 2722 */ 2723 private int mOverScrollMode; 2724 2725 /** 2726 * The parent this view is attached to. 2727 * {@hide} 2728 * 2729 * @see #getParent() 2730 */ 2731 protected ViewParent mParent; 2732 2733 /** 2734 * {@hide} 2735 */ 2736 AttachInfo mAttachInfo; 2737 2738 /** 2739 * {@hide} 2740 */ 2741 @ViewDebug.ExportedProperty(flagMapping = { 2742 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 2743 name = "FORCE_LAYOUT"), 2744 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 2745 name = "LAYOUT_REQUIRED"), 2746 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 2747 name = "DRAWING_CACHE_INVALID", outputIf = false), 2748 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 2749 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 2750 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 2751 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 2752 }) 2753 int mPrivateFlags; 2754 int mPrivateFlags2; 2755 int mPrivateFlags3; 2756 2757 /** 2758 * This view's request for the visibility of the status bar. 2759 * @hide 2760 */ 2761 @ViewDebug.ExportedProperty(flagMapping = { 2762 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 2763 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 2764 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 2765 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 2766 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 2767 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 2768 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 2769 equals = SYSTEM_UI_FLAG_VISIBLE, 2770 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 2771 }) 2772 int mSystemUiVisibility; 2773 2774 /** 2775 * Reference count for transient state. 2776 * @see #setHasTransientState(boolean) 2777 */ 2778 int mTransientStateCount = 0; 2779 2780 /** 2781 * Count of how many windows this view has been attached to. 2782 */ 2783 int mWindowAttachCount; 2784 2785 /** 2786 * The layout parameters associated with this view and used by the parent 2787 * {@link android.view.ViewGroup} to determine how this view should be 2788 * laid out. 2789 * {@hide} 2790 */ 2791 protected ViewGroup.LayoutParams mLayoutParams; 2792 2793 /** 2794 * The view flags hold various views states. 2795 * {@hide} 2796 */ 2797 @ViewDebug.ExportedProperty 2798 int mViewFlags; 2799 2800 static class TransformationInfo { 2801 /** 2802 * The transform matrix for the View. This transform is calculated internally 2803 * based on the rotation, scaleX, and scaleY properties. The identity matrix 2804 * is used by default. Do *not* use this variable directly; instead call 2805 * getMatrix(), which will automatically recalculate the matrix if necessary 2806 * to get the correct matrix based on the latest rotation and scale properties. 2807 */ 2808 private final Matrix mMatrix = new Matrix(); 2809 2810 /** 2811 * The transform matrix for the View. This transform is calculated internally 2812 * based on the rotation, scaleX, and scaleY properties. The identity matrix 2813 * is used by default. Do *not* use this variable directly; instead call 2814 * getInverseMatrix(), which will automatically recalculate the matrix if necessary 2815 * to get the correct matrix based on the latest rotation and scale properties. 2816 */ 2817 private Matrix mInverseMatrix; 2818 2819 /** 2820 * An internal variable that tracks whether we need to recalculate the 2821 * transform matrix, based on whether the rotation or scaleX/Y properties 2822 * have changed since the matrix was last calculated. 2823 */ 2824 boolean mMatrixDirty = false; 2825 2826 /** 2827 * An internal variable that tracks whether we need to recalculate the 2828 * transform matrix, based on whether the rotation or scaleX/Y properties 2829 * have changed since the matrix was last calculated. 2830 */ 2831 private boolean mInverseMatrixDirty = true; 2832 2833 /** 2834 * A variable that tracks whether we need to recalculate the 2835 * transform matrix, based on whether the rotation or scaleX/Y properties 2836 * have changed since the matrix was last calculated. This variable 2837 * is only valid after a call to updateMatrix() or to a function that 2838 * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix(). 2839 */ 2840 private boolean mMatrixIsIdentity = true; 2841 2842 /** 2843 * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set. 2844 */ 2845 private Camera mCamera = null; 2846 2847 /** 2848 * This matrix is used when computing the matrix for 3D rotations. 2849 */ 2850 private Matrix matrix3D = null; 2851 2852 /** 2853 * These prev values are used to recalculate a centered pivot point when necessary. The 2854 * pivot point is only used in matrix operations (when rotation, scale, or translation are 2855 * set), so thes values are only used then as well. 2856 */ 2857 private int mPrevWidth = -1; 2858 private int mPrevHeight = -1; 2859 2860 /** 2861 * The degrees rotation around the vertical axis through the pivot point. 2862 */ 2863 @ViewDebug.ExportedProperty 2864 float mRotationY = 0f; 2865 2866 /** 2867 * The degrees rotation around the horizontal axis through the pivot point. 2868 */ 2869 @ViewDebug.ExportedProperty 2870 float mRotationX = 0f; 2871 2872 /** 2873 * The degrees rotation around the pivot point. 2874 */ 2875 @ViewDebug.ExportedProperty 2876 float mRotation = 0f; 2877 2878 /** 2879 * The amount of translation of the object away from its left property (post-layout). 2880 */ 2881 @ViewDebug.ExportedProperty 2882 float mTranslationX = 0f; 2883 2884 /** 2885 * The amount of translation of the object away from its top property (post-layout). 2886 */ 2887 @ViewDebug.ExportedProperty 2888 float mTranslationY = 0f; 2889 2890 /** 2891 * The amount of scale in the x direction around the pivot point. A 2892 * value of 1 means no scaling is applied. 2893 */ 2894 @ViewDebug.ExportedProperty 2895 float mScaleX = 1f; 2896 2897 /** 2898 * The amount of scale in the y direction around the pivot point. A 2899 * value of 1 means no scaling is applied. 2900 */ 2901 @ViewDebug.ExportedProperty 2902 float mScaleY = 1f; 2903 2904 /** 2905 * The x location of the point around which the view is rotated and scaled. 2906 */ 2907 @ViewDebug.ExportedProperty 2908 float mPivotX = 0f; 2909 2910 /** 2911 * The y location of the point around which the view is rotated and scaled. 2912 */ 2913 @ViewDebug.ExportedProperty 2914 float mPivotY = 0f; 2915 2916 /** 2917 * The opacity of the View. This is a value from 0 to 1, where 0 means 2918 * completely transparent and 1 means completely opaque. 2919 */ 2920 @ViewDebug.ExportedProperty 2921 float mAlpha = 1f; 2922 2923 /** 2924 * The opacity of the view as manipulated by the Fade transition. This is a hidden 2925 * property only used by transitions, which is composited with the other alpha 2926 * values to calculate the final visual alpha value. 2927 */ 2928 float mTransitionAlpha = 1f; 2929 } 2930 2931 TransformationInfo mTransformationInfo; 2932 2933 /** 2934 * Current clip bounds. to which all drawing of this view are constrained. 2935 */ 2936 private Rect mClipBounds = null; 2937 2938 private boolean mLastIsOpaque; 2939 2940 /** 2941 * Convenience value to check for float values that are close enough to zero to be considered 2942 * zero. 2943 */ 2944 private static final float NONZERO_EPSILON = .001f; 2945 2946 /** 2947 * The distance in pixels from the left edge of this view's parent 2948 * to the left edge of this view. 2949 * {@hide} 2950 */ 2951 @ViewDebug.ExportedProperty(category = "layout") 2952 protected int mLeft; 2953 /** 2954 * The distance in pixels from the left edge of this view's parent 2955 * to the right edge of this view. 2956 * {@hide} 2957 */ 2958 @ViewDebug.ExportedProperty(category = "layout") 2959 protected int mRight; 2960 /** 2961 * The distance in pixels from the top edge of this view's parent 2962 * to the top edge of this view. 2963 * {@hide} 2964 */ 2965 @ViewDebug.ExportedProperty(category = "layout") 2966 protected int mTop; 2967 /** 2968 * The distance in pixels from the top edge of this view's parent 2969 * to the bottom edge of this view. 2970 * {@hide} 2971 */ 2972 @ViewDebug.ExportedProperty(category = "layout") 2973 protected int mBottom; 2974 2975 /** 2976 * The offset, in pixels, by which the content of this view is scrolled 2977 * horizontally. 2978 * {@hide} 2979 */ 2980 @ViewDebug.ExportedProperty(category = "scrolling") 2981 protected int mScrollX; 2982 /** 2983 * The offset, in pixels, by which the content of this view is scrolled 2984 * vertically. 2985 * {@hide} 2986 */ 2987 @ViewDebug.ExportedProperty(category = "scrolling") 2988 protected int mScrollY; 2989 2990 /** 2991 * The left padding in pixels, that is the distance in pixels between the 2992 * left edge of this view and the left edge of its content. 2993 * {@hide} 2994 */ 2995 @ViewDebug.ExportedProperty(category = "padding") 2996 protected int mPaddingLeft = 0; 2997 /** 2998 * The right padding in pixels, that is the distance in pixels between the 2999 * right edge of this view and the right edge of its content. 3000 * {@hide} 3001 */ 3002 @ViewDebug.ExportedProperty(category = "padding") 3003 protected int mPaddingRight = 0; 3004 /** 3005 * The top padding in pixels, that is the distance in pixels between the 3006 * top edge of this view and the top edge of its content. 3007 * {@hide} 3008 */ 3009 @ViewDebug.ExportedProperty(category = "padding") 3010 protected int mPaddingTop; 3011 /** 3012 * The bottom padding in pixels, that is the distance in pixels between the 3013 * bottom edge of this view and the bottom edge of its content. 3014 * {@hide} 3015 */ 3016 @ViewDebug.ExportedProperty(category = "padding") 3017 protected int mPaddingBottom; 3018 3019 /** 3020 * The layout insets in pixels, that is the distance in pixels between the 3021 * visible edges of this view its bounds. 3022 */ 3023 private Insets mLayoutInsets; 3024 3025 /** 3026 * Briefly describes the view and is primarily used for accessibility support. 3027 */ 3028 private CharSequence mContentDescription; 3029 3030 /** 3031 * Specifies the id of a view for which this view serves as a label for 3032 * accessibility purposes. 3033 */ 3034 private int mLabelForId = View.NO_ID; 3035 3036 /** 3037 * Predicate for matching labeled view id with its label for 3038 * accessibility purposes. 3039 */ 3040 private MatchLabelForPredicate mMatchLabelForPredicate; 3041 3042 /** 3043 * Predicate for matching a view by its id. 3044 */ 3045 private MatchIdPredicate mMatchIdPredicate; 3046 3047 /** 3048 * Cache the paddingRight set by the user to append to the scrollbar's size. 3049 * 3050 * @hide 3051 */ 3052 @ViewDebug.ExportedProperty(category = "padding") 3053 protected int mUserPaddingRight; 3054 3055 /** 3056 * Cache the paddingBottom set by the user to append to the scrollbar's size. 3057 * 3058 * @hide 3059 */ 3060 @ViewDebug.ExportedProperty(category = "padding") 3061 protected int mUserPaddingBottom; 3062 3063 /** 3064 * Cache the paddingLeft set by the user to append to the scrollbar's size. 3065 * 3066 * @hide 3067 */ 3068 @ViewDebug.ExportedProperty(category = "padding") 3069 protected int mUserPaddingLeft; 3070 3071 /** 3072 * Cache the paddingStart set by the user to append to the scrollbar's size. 3073 * 3074 */ 3075 @ViewDebug.ExportedProperty(category = "padding") 3076 int mUserPaddingStart; 3077 3078 /** 3079 * Cache the paddingEnd set by the user to append to the scrollbar's size. 3080 * 3081 */ 3082 @ViewDebug.ExportedProperty(category = "padding") 3083 int mUserPaddingEnd; 3084 3085 /** 3086 * Cache initial left padding. 3087 * 3088 * @hide 3089 */ 3090 int mUserPaddingLeftInitial; 3091 3092 /** 3093 * Cache initial right padding. 3094 * 3095 * @hide 3096 */ 3097 int mUserPaddingRightInitial; 3098 3099 /** 3100 * Default undefined padding 3101 */ 3102 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 3103 3104 /** 3105 * Cache if a left padding has been defined 3106 */ 3107 private boolean mLeftPaddingDefined = false; 3108 3109 /** 3110 * Cache if a right padding has been defined 3111 */ 3112 private boolean mRightPaddingDefined = false; 3113 3114 /** 3115 * @hide 3116 */ 3117 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 3118 /** 3119 * @hide 3120 */ 3121 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 3122 3123 private LongSparseLongArray mMeasureCache; 3124 3125 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 3126 private Drawable mBackground; 3127 3128 private int mBackgroundResource; 3129 private boolean mBackgroundSizeChanged; 3130 3131 static class ListenerInfo { 3132 /** 3133 * Listener used to dispatch focus change events. 3134 * This field should be made private, so it is hidden from the SDK. 3135 * {@hide} 3136 */ 3137 protected OnFocusChangeListener mOnFocusChangeListener; 3138 3139 /** 3140 * Listeners for layout change events. 3141 */ 3142 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 3143 3144 /** 3145 * Listeners for attach events. 3146 */ 3147 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 3148 3149 /** 3150 * Listener used to dispatch click events. 3151 * This field should be made private, so it is hidden from the SDK. 3152 * {@hide} 3153 */ 3154 public OnClickListener mOnClickListener; 3155 3156 /** 3157 * Listener used to dispatch long click events. 3158 * This field should be made private, so it is hidden from the SDK. 3159 * {@hide} 3160 */ 3161 protected OnLongClickListener mOnLongClickListener; 3162 3163 /** 3164 * Listener used to build the context menu. 3165 * This field should be made private, so it is hidden from the SDK. 3166 * {@hide} 3167 */ 3168 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 3169 3170 private OnKeyListener mOnKeyListener; 3171 3172 private OnTouchListener mOnTouchListener; 3173 3174 private OnHoverListener mOnHoverListener; 3175 3176 private OnGenericMotionListener mOnGenericMotionListener; 3177 3178 private OnDragListener mOnDragListener; 3179 3180 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 3181 } 3182 3183 ListenerInfo mListenerInfo; 3184 3185 /** 3186 * The application environment this view lives in. 3187 * This field should be made private, so it is hidden from the SDK. 3188 * {@hide} 3189 */ 3190 protected Context mContext; 3191 3192 private final Resources mResources; 3193 3194 private ScrollabilityCache mScrollCache; 3195 3196 private int[] mDrawableState = null; 3197 3198 /** 3199 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 3200 * the user may specify which view to go to next. 3201 */ 3202 private int mNextFocusLeftId = View.NO_ID; 3203 3204 /** 3205 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 3206 * the user may specify which view to go to next. 3207 */ 3208 private int mNextFocusRightId = View.NO_ID; 3209 3210 /** 3211 * When this view has focus and the next focus is {@link #FOCUS_UP}, 3212 * the user may specify which view to go to next. 3213 */ 3214 private int mNextFocusUpId = View.NO_ID; 3215 3216 /** 3217 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 3218 * the user may specify which view to go to next. 3219 */ 3220 private int mNextFocusDownId = View.NO_ID; 3221 3222 /** 3223 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 3224 * the user may specify which view to go to next. 3225 */ 3226 int mNextFocusForwardId = View.NO_ID; 3227 3228 private CheckForLongPress mPendingCheckForLongPress; 3229 private CheckForTap mPendingCheckForTap = null; 3230 private PerformClick mPerformClick; 3231 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 3232 3233 private UnsetPressedState mUnsetPressedState; 3234 3235 /** 3236 * Whether the long press's action has been invoked. The tap's action is invoked on the 3237 * up event while a long press is invoked as soon as the long press duration is reached, so 3238 * a long press could be performed before the tap is checked, in which case the tap's action 3239 * should not be invoked. 3240 */ 3241 private boolean mHasPerformedLongPress; 3242 3243 /** 3244 * The minimum height of the view. We'll try our best to have the height 3245 * of this view to at least this amount. 3246 */ 3247 @ViewDebug.ExportedProperty(category = "measurement") 3248 private int mMinHeight; 3249 3250 /** 3251 * The minimum width of the view. We'll try our best to have the width 3252 * of this view to at least this amount. 3253 */ 3254 @ViewDebug.ExportedProperty(category = "measurement") 3255 private int mMinWidth; 3256 3257 /** 3258 * The delegate to handle touch events that are physically in this view 3259 * but should be handled by another view. 3260 */ 3261 private TouchDelegate mTouchDelegate = null; 3262 3263 /** 3264 * Solid color to use as a background when creating the drawing cache. Enables 3265 * the cache to use 16 bit bitmaps instead of 32 bit. 3266 */ 3267 private int mDrawingCacheBackgroundColor = 0; 3268 3269 /** 3270 * Special tree observer used when mAttachInfo is null. 3271 */ 3272 private ViewTreeObserver mFloatingTreeObserver; 3273 3274 /** 3275 * Cache the touch slop from the context that created the view. 3276 */ 3277 private int mTouchSlop; 3278 3279 /** 3280 * Object that handles automatic animation of view properties. 3281 */ 3282 private ViewPropertyAnimator mAnimator = null; 3283 3284 /** 3285 * Flag indicating that a drag can cross window boundaries. When 3286 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called 3287 * with this flag set, all visible applications will be able to participate 3288 * in the drag operation and receive the dragged content. 3289 * 3290 * @hide 3291 */ 3292 public static final int DRAG_FLAG_GLOBAL = 1; 3293 3294 /** 3295 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 3296 */ 3297 private float mVerticalScrollFactor; 3298 3299 /** 3300 * Position of the vertical scroll bar. 3301 */ 3302 private int mVerticalScrollbarPosition; 3303 3304 /** 3305 * Position the scroll bar at the default position as determined by the system. 3306 */ 3307 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 3308 3309 /** 3310 * Position the scroll bar along the left edge. 3311 */ 3312 public static final int SCROLLBAR_POSITION_LEFT = 1; 3313 3314 /** 3315 * Position the scroll bar along the right edge. 3316 */ 3317 public static final int SCROLLBAR_POSITION_RIGHT = 2; 3318 3319 /** 3320 * Indicates that the view does not have a layer. 3321 * 3322 * @see #getLayerType() 3323 * @see #setLayerType(int, android.graphics.Paint) 3324 * @see #LAYER_TYPE_SOFTWARE 3325 * @see #LAYER_TYPE_HARDWARE 3326 */ 3327 public static final int LAYER_TYPE_NONE = 0; 3328 3329 /** 3330 * <p>Indicates that the view has a software layer. A software layer is backed 3331 * by a bitmap and causes the view to be rendered using Android's software 3332 * rendering pipeline, even if hardware acceleration is enabled.</p> 3333 * 3334 * <p>Software layers have various usages:</p> 3335 * <p>When the application is not using hardware acceleration, a software layer 3336 * is useful to apply a specific color filter and/or blending mode and/or 3337 * translucency to a view and all its children.</p> 3338 * <p>When the application is using hardware acceleration, a software layer 3339 * is useful to render drawing primitives not supported by the hardware 3340 * accelerated pipeline. It can also be used to cache a complex view tree 3341 * into a texture and reduce the complexity of drawing operations. For instance, 3342 * when animating a complex view tree with a translation, a software layer can 3343 * be used to render the view tree only once.</p> 3344 * <p>Software layers should be avoided when the affected view tree updates 3345 * often. Every update will require to re-render the software layer, which can 3346 * potentially be slow (particularly when hardware acceleration is turned on 3347 * since the layer will have to be uploaded into a hardware texture after every 3348 * update.)</p> 3349 * 3350 * @see #getLayerType() 3351 * @see #setLayerType(int, android.graphics.Paint) 3352 * @see #LAYER_TYPE_NONE 3353 * @see #LAYER_TYPE_HARDWARE 3354 */ 3355 public static final int LAYER_TYPE_SOFTWARE = 1; 3356 3357 /** 3358 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 3359 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 3360 * OpenGL hardware) and causes the view to be rendered using Android's hardware 3361 * rendering pipeline, but only if hardware acceleration is turned on for the 3362 * view hierarchy. When hardware acceleration is turned off, hardware layers 3363 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 3364 * 3365 * <p>A hardware layer is useful to apply a specific color filter and/or 3366 * blending mode and/or translucency to a view and all its children.</p> 3367 * <p>A hardware layer can be used to cache a complex view tree into a 3368 * texture and reduce the complexity of drawing operations. For instance, 3369 * when animating a complex view tree with a translation, a hardware layer can 3370 * be used to render the view tree only once.</p> 3371 * <p>A hardware layer can also be used to increase the rendering quality when 3372 * rotation transformations are applied on a view. It can also be used to 3373 * prevent potential clipping issues when applying 3D transforms on a view.</p> 3374 * 3375 * @see #getLayerType() 3376 * @see #setLayerType(int, android.graphics.Paint) 3377 * @see #LAYER_TYPE_NONE 3378 * @see #LAYER_TYPE_SOFTWARE 3379 */ 3380 public static final int LAYER_TYPE_HARDWARE = 2; 3381 3382 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 3383 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 3384 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 3385 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 3386 }) 3387 int mLayerType = LAYER_TYPE_NONE; 3388 Paint mLayerPaint; 3389 Rect mLocalDirtyRect; 3390 private HardwareLayer mHardwareLayer; 3391 3392 /** 3393 * Set to true when drawing cache is enabled and cannot be created. 3394 * 3395 * @hide 3396 */ 3397 public boolean mCachingFailed; 3398 private Bitmap mDrawingCache; 3399 private Bitmap mUnscaledDrawingCache; 3400 3401 DisplayList mDisplayList; 3402 3403 /** 3404 * Set to true when the view is sending hover accessibility events because it 3405 * is the innermost hovered view. 3406 */ 3407 private boolean mSendingHoverAccessibilityEvents; 3408 3409 /** 3410 * Delegate for injecting accessibility functionality. 3411 */ 3412 AccessibilityDelegate mAccessibilityDelegate; 3413 3414 /** 3415 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 3416 * and add/remove objects to/from the overlay directly through the Overlay methods. 3417 */ 3418 ViewOverlay mOverlay; 3419 3420 /** 3421 * Consistency verifier for debugging purposes. 3422 * @hide 3423 */ 3424 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 3425 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 3426 new InputEventConsistencyVerifier(this, 0) : null; 3427 3428 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 3429 3430 /** 3431 * Simple constructor to use when creating a view from code. 3432 * 3433 * @param context The Context the view is running in, through which it can 3434 * access the current theme, resources, etc. 3435 */ 3436 public View(Context context) { 3437 mContext = context; 3438 mResources = context != null ? context.getResources() : null; 3439 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; 3440 // Set some flags defaults 3441 mPrivateFlags2 = 3442 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 3443 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 3444 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 3445 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 3446 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 3447 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 3448 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 3449 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 3450 mUserPaddingStart = UNDEFINED_PADDING; 3451 mUserPaddingEnd = UNDEFINED_PADDING; 3452 3453 if (!sCompatibilityDone && context != null) { 3454 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 3455 3456 // Older apps may need this compatibility hack for measurement. 3457 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1; 3458 3459 // Older apps expect onMeasure() to always be called on a layout pass, regardless 3460 // of whether a layout was requested on that View. 3461 sIgnoreMeasureCache = targetSdkVersion < KITKAT; 3462 3463 sCompatibilityDone = true; 3464 } 3465 } 3466 3467 /** 3468 * Constructor that is called when inflating a view from XML. This is called 3469 * when a view is being constructed from an XML file, supplying attributes 3470 * that were specified in the XML file. This version uses a default style of 3471 * 0, so the only attribute values applied are those in the Context's Theme 3472 * and the given AttributeSet. 3473 * 3474 * <p> 3475 * The method onFinishInflate() will be called after all children have been 3476 * added. 3477 * 3478 * @param context The Context the view is running in, through which it can 3479 * access the current theme, resources, etc. 3480 * @param attrs The attributes of the XML tag that is inflating the view. 3481 * @see #View(Context, AttributeSet, int) 3482 */ 3483 public View(Context context, AttributeSet attrs) { 3484 this(context, attrs, 0); 3485 } 3486 3487 /** 3488 * Perform inflation from XML and apply a class-specific base style. This 3489 * constructor of View allows subclasses to use their own base style when 3490 * they are inflating. For example, a Button class's constructor would call 3491 * this version of the super class constructor and supply 3492 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows 3493 * the theme's button style to modify all of the base view attributes (in 3494 * particular its background) as well as the Button class's attributes. 3495 * 3496 * @param context The Context the view is running in, through which it can 3497 * access the current theme, resources, etc. 3498 * @param attrs The attributes of the XML tag that is inflating the view. 3499 * @param defStyleAttr An attribute in the current theme that contains a 3500 * reference to a style resource to apply to this view. If 0, no 3501 * default style will be applied. 3502 * @see #View(Context, AttributeSet) 3503 */ 3504 public View(Context context, AttributeSet attrs, int defStyleAttr) { 3505 this(context); 3506 3507 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, 3508 defStyleAttr, 0); 3509 3510 Drawable background = null; 3511 3512 int leftPadding = -1; 3513 int topPadding = -1; 3514 int rightPadding = -1; 3515 int bottomPadding = -1; 3516 int startPadding = UNDEFINED_PADDING; 3517 int endPadding = UNDEFINED_PADDING; 3518 3519 int padding = -1; 3520 3521 int viewFlagValues = 0; 3522 int viewFlagMasks = 0; 3523 3524 boolean setScrollContainer = false; 3525 3526 int x = 0; 3527 int y = 0; 3528 3529 float tx = 0; 3530 float ty = 0; 3531 float rotation = 0; 3532 float rotationX = 0; 3533 float rotationY = 0; 3534 float sx = 1f; 3535 float sy = 1f; 3536 boolean transformSet = false; 3537 3538 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 3539 int overScrollMode = mOverScrollMode; 3540 boolean initializeScrollbars = false; 3541 3542 boolean startPaddingDefined = false; 3543 boolean endPaddingDefined = false; 3544 boolean leftPaddingDefined = false; 3545 boolean rightPaddingDefined = false; 3546 3547 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 3548 3549 final int N = a.getIndexCount(); 3550 for (int i = 0; i < N; i++) { 3551 int attr = a.getIndex(i); 3552 switch (attr) { 3553 case com.android.internal.R.styleable.View_background: 3554 background = a.getDrawable(attr); 3555 break; 3556 case com.android.internal.R.styleable.View_padding: 3557 padding = a.getDimensionPixelSize(attr, -1); 3558 mUserPaddingLeftInitial = padding; 3559 mUserPaddingRightInitial = padding; 3560 leftPaddingDefined = true; 3561 rightPaddingDefined = true; 3562 break; 3563 case com.android.internal.R.styleable.View_paddingLeft: 3564 leftPadding = a.getDimensionPixelSize(attr, -1); 3565 mUserPaddingLeftInitial = leftPadding; 3566 leftPaddingDefined = true; 3567 break; 3568 case com.android.internal.R.styleable.View_paddingTop: 3569 topPadding = a.getDimensionPixelSize(attr, -1); 3570 break; 3571 case com.android.internal.R.styleable.View_paddingRight: 3572 rightPadding = a.getDimensionPixelSize(attr, -1); 3573 mUserPaddingRightInitial = rightPadding; 3574 rightPaddingDefined = true; 3575 break; 3576 case com.android.internal.R.styleable.View_paddingBottom: 3577 bottomPadding = a.getDimensionPixelSize(attr, -1); 3578 break; 3579 case com.android.internal.R.styleable.View_paddingStart: 3580 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 3581 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 3582 break; 3583 case com.android.internal.R.styleable.View_paddingEnd: 3584 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 3585 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 3586 break; 3587 case com.android.internal.R.styleable.View_scrollX: 3588 x = a.getDimensionPixelOffset(attr, 0); 3589 break; 3590 case com.android.internal.R.styleable.View_scrollY: 3591 y = a.getDimensionPixelOffset(attr, 0); 3592 break; 3593 case com.android.internal.R.styleable.View_alpha: 3594 setAlpha(a.getFloat(attr, 1f)); 3595 break; 3596 case com.android.internal.R.styleable.View_transformPivotX: 3597 setPivotX(a.getDimensionPixelOffset(attr, 0)); 3598 break; 3599 case com.android.internal.R.styleable.View_transformPivotY: 3600 setPivotY(a.getDimensionPixelOffset(attr, 0)); 3601 break; 3602 case com.android.internal.R.styleable.View_translationX: 3603 tx = a.getDimensionPixelOffset(attr, 0); 3604 transformSet = true; 3605 break; 3606 case com.android.internal.R.styleable.View_translationY: 3607 ty = a.getDimensionPixelOffset(attr, 0); 3608 transformSet = true; 3609 break; 3610 case com.android.internal.R.styleable.View_rotation: 3611 rotation = a.getFloat(attr, 0); 3612 transformSet = true; 3613 break; 3614 case com.android.internal.R.styleable.View_rotationX: 3615 rotationX = a.getFloat(attr, 0); 3616 transformSet = true; 3617 break; 3618 case com.android.internal.R.styleable.View_rotationY: 3619 rotationY = a.getFloat(attr, 0); 3620 transformSet = true; 3621 break; 3622 case com.android.internal.R.styleable.View_scaleX: 3623 sx = a.getFloat(attr, 1f); 3624 transformSet = true; 3625 break; 3626 case com.android.internal.R.styleable.View_scaleY: 3627 sy = a.getFloat(attr, 1f); 3628 transformSet = true; 3629 break; 3630 case com.android.internal.R.styleable.View_id: 3631 mID = a.getResourceId(attr, NO_ID); 3632 break; 3633 case com.android.internal.R.styleable.View_tag: 3634 mTag = a.getText(attr); 3635 break; 3636 case com.android.internal.R.styleable.View_fitsSystemWindows: 3637 if (a.getBoolean(attr, false)) { 3638 viewFlagValues |= FITS_SYSTEM_WINDOWS; 3639 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 3640 } 3641 break; 3642 case com.android.internal.R.styleable.View_focusable: 3643 if (a.getBoolean(attr, false)) { 3644 viewFlagValues |= FOCUSABLE; 3645 viewFlagMasks |= FOCUSABLE_MASK; 3646 } 3647 break; 3648 case com.android.internal.R.styleable.View_focusableInTouchMode: 3649 if (a.getBoolean(attr, false)) { 3650 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 3651 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 3652 } 3653 break; 3654 case com.android.internal.R.styleable.View_clickable: 3655 if (a.getBoolean(attr, false)) { 3656 viewFlagValues |= CLICKABLE; 3657 viewFlagMasks |= CLICKABLE; 3658 } 3659 break; 3660 case com.android.internal.R.styleable.View_longClickable: 3661 if (a.getBoolean(attr, false)) { 3662 viewFlagValues |= LONG_CLICKABLE; 3663 viewFlagMasks |= LONG_CLICKABLE; 3664 } 3665 break; 3666 case com.android.internal.R.styleable.View_saveEnabled: 3667 if (!a.getBoolean(attr, true)) { 3668 viewFlagValues |= SAVE_DISABLED; 3669 viewFlagMasks |= SAVE_DISABLED_MASK; 3670 } 3671 break; 3672 case com.android.internal.R.styleable.View_duplicateParentState: 3673 if (a.getBoolean(attr, false)) { 3674 viewFlagValues |= DUPLICATE_PARENT_STATE; 3675 viewFlagMasks |= DUPLICATE_PARENT_STATE; 3676 } 3677 break; 3678 case com.android.internal.R.styleable.View_visibility: 3679 final int visibility = a.getInt(attr, 0); 3680 if (visibility != 0) { 3681 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 3682 viewFlagMasks |= VISIBILITY_MASK; 3683 } 3684 break; 3685 case com.android.internal.R.styleable.View_layoutDirection: 3686 // Clear any layout direction flags (included resolved bits) already set 3687 mPrivateFlags2 &= 3688 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 3689 // Set the layout direction flags depending on the value of the attribute 3690 final int layoutDirection = a.getInt(attr, -1); 3691 final int value = (layoutDirection != -1) ? 3692 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 3693 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 3694 break; 3695 case com.android.internal.R.styleable.View_drawingCacheQuality: 3696 final int cacheQuality = a.getInt(attr, 0); 3697 if (cacheQuality != 0) { 3698 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 3699 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 3700 } 3701 break; 3702 case com.android.internal.R.styleable.View_contentDescription: 3703 setContentDescription(a.getString(attr)); 3704 break; 3705 case com.android.internal.R.styleable.View_labelFor: 3706 setLabelFor(a.getResourceId(attr, NO_ID)); 3707 break; 3708 case com.android.internal.R.styleable.View_soundEffectsEnabled: 3709 if (!a.getBoolean(attr, true)) { 3710 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 3711 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 3712 } 3713 break; 3714 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 3715 if (!a.getBoolean(attr, true)) { 3716 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 3717 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 3718 } 3719 break; 3720 case R.styleable.View_scrollbars: 3721 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 3722 if (scrollbars != SCROLLBARS_NONE) { 3723 viewFlagValues |= scrollbars; 3724 viewFlagMasks |= SCROLLBARS_MASK; 3725 initializeScrollbars = true; 3726 } 3727 break; 3728 //noinspection deprecation 3729 case R.styleable.View_fadingEdge: 3730 if (targetSdkVersion >= ICE_CREAM_SANDWICH) { 3731 // Ignore the attribute starting with ICS 3732 break; 3733 } 3734 // With builds < ICS, fall through and apply fading edges 3735 case R.styleable.View_requiresFadingEdge: 3736 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 3737 if (fadingEdge != FADING_EDGE_NONE) { 3738 viewFlagValues |= fadingEdge; 3739 viewFlagMasks |= FADING_EDGE_MASK; 3740 initializeFadingEdge(a); 3741 } 3742 break; 3743 case R.styleable.View_scrollbarStyle: 3744 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 3745 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 3746 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 3747 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 3748 } 3749 break; 3750 case R.styleable.View_isScrollContainer: 3751 setScrollContainer = true; 3752 if (a.getBoolean(attr, false)) { 3753 setScrollContainer(true); 3754 } 3755 break; 3756 case com.android.internal.R.styleable.View_keepScreenOn: 3757 if (a.getBoolean(attr, false)) { 3758 viewFlagValues |= KEEP_SCREEN_ON; 3759 viewFlagMasks |= KEEP_SCREEN_ON; 3760 } 3761 break; 3762 case R.styleable.View_filterTouchesWhenObscured: 3763 if (a.getBoolean(attr, false)) { 3764 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 3765 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 3766 } 3767 break; 3768 case R.styleable.View_nextFocusLeft: 3769 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 3770 break; 3771 case R.styleable.View_nextFocusRight: 3772 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 3773 break; 3774 case R.styleable.View_nextFocusUp: 3775 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 3776 break; 3777 case R.styleable.View_nextFocusDown: 3778 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 3779 break; 3780 case R.styleable.View_nextFocusForward: 3781 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 3782 break; 3783 case R.styleable.View_minWidth: 3784 mMinWidth = a.getDimensionPixelSize(attr, 0); 3785 break; 3786 case R.styleable.View_minHeight: 3787 mMinHeight = a.getDimensionPixelSize(attr, 0); 3788 break; 3789 case R.styleable.View_onClick: 3790 if (context.isRestricted()) { 3791 throw new IllegalStateException("The android:onClick attribute cannot " 3792 + "be used within a restricted context"); 3793 } 3794 3795 final String handlerName = a.getString(attr); 3796 if (handlerName != null) { 3797 setOnClickListener(new OnClickListener() { 3798 private Method mHandler; 3799 3800 public void onClick(View v) { 3801 if (mHandler == null) { 3802 try { 3803 mHandler = getContext().getClass().getMethod(handlerName, 3804 View.class); 3805 } catch (NoSuchMethodException e) { 3806 int id = getId(); 3807 String idText = id == NO_ID ? "" : " with id '" 3808 + getContext().getResources().getResourceEntryName( 3809 id) + "'"; 3810 throw new IllegalStateException("Could not find a method " + 3811 handlerName + "(View) in the activity " 3812 + getContext().getClass() + " for onClick handler" 3813 + " on view " + View.this.getClass() + idText, e); 3814 } 3815 } 3816 3817 try { 3818 mHandler.invoke(getContext(), View.this); 3819 } catch (IllegalAccessException e) { 3820 throw new IllegalStateException("Could not execute non " 3821 + "public method of the activity", e); 3822 } catch (InvocationTargetException e) { 3823 throw new IllegalStateException("Could not execute " 3824 + "method of the activity", e); 3825 } 3826 } 3827 }); 3828 } 3829 break; 3830 case R.styleable.View_overScrollMode: 3831 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 3832 break; 3833 case R.styleable.View_verticalScrollbarPosition: 3834 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 3835 break; 3836 case R.styleable.View_layerType: 3837 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 3838 break; 3839 case R.styleable.View_textDirection: 3840 // Clear any text direction flag already set 3841 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 3842 // Set the text direction flags depending on the value of the attribute 3843 final int textDirection = a.getInt(attr, -1); 3844 if (textDirection != -1) { 3845 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 3846 } 3847 break; 3848 case R.styleable.View_textAlignment: 3849 // Clear any text alignment flag already set 3850 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 3851 // Set the text alignment flag depending on the value of the attribute 3852 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 3853 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 3854 break; 3855 case R.styleable.View_importantForAccessibility: 3856 setImportantForAccessibility(a.getInt(attr, 3857 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 3858 break; 3859 case R.styleable.View_accessibilityLiveRegion: 3860 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 3861 break; 3862 } 3863 } 3864 3865 setOverScrollMode(overScrollMode); 3866 3867 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 3868 // the resolved layout direction). Those cached values will be used later during padding 3869 // resolution. 3870 mUserPaddingStart = startPadding; 3871 mUserPaddingEnd = endPadding; 3872 3873 if (background != null) { 3874 setBackground(background); 3875 } 3876 3877 // setBackground above will record that padding is currently provided by the background. 3878 // If we have padding specified via xml, record that here instead and use it. 3879 mLeftPaddingDefined = leftPaddingDefined; 3880 mRightPaddingDefined = rightPaddingDefined; 3881 3882 if (padding >= 0) { 3883 leftPadding = padding; 3884 topPadding = padding; 3885 rightPadding = padding; 3886 bottomPadding = padding; 3887 mUserPaddingLeftInitial = padding; 3888 mUserPaddingRightInitial = padding; 3889 } 3890 3891 if (isRtlCompatibilityMode()) { 3892 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 3893 // left / right padding are used if defined (meaning here nothing to do). If they are not 3894 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 3895 // start / end and resolve them as left / right (layout direction is not taken into account). 3896 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 3897 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 3898 // defined. 3899 if (!mLeftPaddingDefined && startPaddingDefined) { 3900 leftPadding = startPadding; 3901 } 3902 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 3903 if (!mRightPaddingDefined && endPaddingDefined) { 3904 rightPadding = endPadding; 3905 } 3906 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 3907 } else { 3908 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 3909 // values defined. Otherwise, left /right values are used. 3910 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 3911 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 3912 // defined. 3913 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 3914 3915 if (mLeftPaddingDefined && !hasRelativePadding) { 3916 mUserPaddingLeftInitial = leftPadding; 3917 } 3918 if (mRightPaddingDefined && !hasRelativePadding) { 3919 mUserPaddingRightInitial = rightPadding; 3920 } 3921 } 3922 3923 internalSetPadding( 3924 mUserPaddingLeftInitial, 3925 topPadding >= 0 ? topPadding : mPaddingTop, 3926 mUserPaddingRightInitial, 3927 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 3928 3929 if (viewFlagMasks != 0) { 3930 setFlags(viewFlagValues, viewFlagMasks); 3931 } 3932 3933 if (initializeScrollbars) { 3934 initializeScrollbars(a); 3935 } 3936 3937 a.recycle(); 3938 3939 // Needs to be called after mViewFlags is set 3940 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 3941 recomputePadding(); 3942 } 3943 3944 if (x != 0 || y != 0) { 3945 scrollTo(x, y); 3946 } 3947 3948 if (transformSet) { 3949 setTranslationX(tx); 3950 setTranslationY(ty); 3951 setRotation(rotation); 3952 setRotationX(rotationX); 3953 setRotationY(rotationY); 3954 setScaleX(sx); 3955 setScaleY(sy); 3956 } 3957 3958 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 3959 setScrollContainer(true); 3960 } 3961 3962 computeOpaqueFlags(); 3963 } 3964 3965 /** 3966 * Non-public constructor for use in testing 3967 */ 3968 View() { 3969 mResources = null; 3970 } 3971 3972 public String toString() { 3973 StringBuilder out = new StringBuilder(128); 3974 out.append(getClass().getName()); 3975 out.append('{'); 3976 out.append(Integer.toHexString(System.identityHashCode(this))); 3977 out.append(' '); 3978 switch (mViewFlags&VISIBILITY_MASK) { 3979 case VISIBLE: out.append('V'); break; 3980 case INVISIBLE: out.append('I'); break; 3981 case GONE: out.append('G'); break; 3982 default: out.append('.'); break; 3983 } 3984 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.'); 3985 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 3986 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 3987 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 3988 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 3989 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 3990 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 3991 out.append(' '); 3992 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 3993 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 3994 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 3995 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 3996 out.append('p'); 3997 } else { 3998 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 3999 } 4000 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 4001 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 4002 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 4003 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 4004 out.append(' '); 4005 out.append(mLeft); 4006 out.append(','); 4007 out.append(mTop); 4008 out.append('-'); 4009 out.append(mRight); 4010 out.append(','); 4011 out.append(mBottom); 4012 final int id = getId(); 4013 if (id != NO_ID) { 4014 out.append(" #"); 4015 out.append(Integer.toHexString(id)); 4016 final Resources r = mResources; 4017 if (id != 0 && r != null) { 4018 try { 4019 String pkgname; 4020 switch (id&0xff000000) { 4021 case 0x7f000000: 4022 pkgname="app"; 4023 break; 4024 case 0x01000000: 4025 pkgname="android"; 4026 break; 4027 default: 4028 pkgname = r.getResourcePackageName(id); 4029 break; 4030 } 4031 String typename = r.getResourceTypeName(id); 4032 String entryname = r.getResourceEntryName(id); 4033 out.append(" "); 4034 out.append(pkgname); 4035 out.append(":"); 4036 out.append(typename); 4037 out.append("/"); 4038 out.append(entryname); 4039 } catch (Resources.NotFoundException e) { 4040 } 4041 } 4042 } 4043 out.append("}"); 4044 return out.toString(); 4045 } 4046 4047 /** 4048 * <p> 4049 * Initializes the fading edges from a given set of styled attributes. This 4050 * method should be called by subclasses that need fading edges and when an 4051 * instance of these subclasses is created programmatically rather than 4052 * being inflated from XML. This method is automatically called when the XML 4053 * is inflated. 4054 * </p> 4055 * 4056 * @param a the styled attributes set to initialize the fading edges from 4057 */ 4058 protected void initializeFadingEdge(TypedArray a) { 4059 initScrollCache(); 4060 4061 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 4062 R.styleable.View_fadingEdgeLength, 4063 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 4064 } 4065 4066 /** 4067 * Returns the size of the vertical faded edges used to indicate that more 4068 * content in this view is visible. 4069 * 4070 * @return The size in pixels of the vertical faded edge or 0 if vertical 4071 * faded edges are not enabled for this view. 4072 * @attr ref android.R.styleable#View_fadingEdgeLength 4073 */ 4074 public int getVerticalFadingEdgeLength() { 4075 if (isVerticalFadingEdgeEnabled()) { 4076 ScrollabilityCache cache = mScrollCache; 4077 if (cache != null) { 4078 return cache.fadingEdgeLength; 4079 } 4080 } 4081 return 0; 4082 } 4083 4084 /** 4085 * Set the size of the faded edge used to indicate that more content in this 4086 * view is available. Will not change whether the fading edge is enabled; use 4087 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 4088 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 4089 * for the vertical or horizontal fading edges. 4090 * 4091 * @param length The size in pixels of the faded edge used to indicate that more 4092 * content in this view is visible. 4093 */ 4094 public void setFadingEdgeLength(int length) { 4095 initScrollCache(); 4096 mScrollCache.fadingEdgeLength = length; 4097 } 4098 4099 /** 4100 * Returns the size of the horizontal faded edges used to indicate that more 4101 * content in this view is visible. 4102 * 4103 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 4104 * faded edges are not enabled for this view. 4105 * @attr ref android.R.styleable#View_fadingEdgeLength 4106 */ 4107 public int getHorizontalFadingEdgeLength() { 4108 if (isHorizontalFadingEdgeEnabled()) { 4109 ScrollabilityCache cache = mScrollCache; 4110 if (cache != null) { 4111 return cache.fadingEdgeLength; 4112 } 4113 } 4114 return 0; 4115 } 4116 4117 /** 4118 * Returns the width of the vertical scrollbar. 4119 * 4120 * @return The width in pixels of the vertical scrollbar or 0 if there 4121 * is no vertical scrollbar. 4122 */ 4123 public int getVerticalScrollbarWidth() { 4124 ScrollabilityCache cache = mScrollCache; 4125 if (cache != null) { 4126 ScrollBarDrawable scrollBar = cache.scrollBar; 4127 if (scrollBar != null) { 4128 int size = scrollBar.getSize(true); 4129 if (size <= 0) { 4130 size = cache.scrollBarSize; 4131 } 4132 return size; 4133 } 4134 return 0; 4135 } 4136 return 0; 4137 } 4138 4139 /** 4140 * Returns the height of the horizontal scrollbar. 4141 * 4142 * @return The height in pixels of the horizontal scrollbar or 0 if 4143 * there is no horizontal scrollbar. 4144 */ 4145 protected int getHorizontalScrollbarHeight() { 4146 ScrollabilityCache cache = mScrollCache; 4147 if (cache != null) { 4148 ScrollBarDrawable scrollBar = cache.scrollBar; 4149 if (scrollBar != null) { 4150 int size = scrollBar.getSize(false); 4151 if (size <= 0) { 4152 size = cache.scrollBarSize; 4153 } 4154 return size; 4155 } 4156 return 0; 4157 } 4158 return 0; 4159 } 4160 4161 /** 4162 * <p> 4163 * Initializes the scrollbars from a given set of styled attributes. This 4164 * method should be called by subclasses that need scrollbars and when an 4165 * instance of these subclasses is created programmatically rather than 4166 * being inflated from XML. This method is automatically called when the XML 4167 * is inflated. 4168 * </p> 4169 * 4170 * @param a the styled attributes set to initialize the scrollbars from 4171 */ 4172 protected void initializeScrollbars(TypedArray a) { 4173 initScrollCache(); 4174 4175 final ScrollabilityCache scrollabilityCache = mScrollCache; 4176 4177 if (scrollabilityCache.scrollBar == null) { 4178 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 4179 } 4180 4181 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 4182 4183 if (!fadeScrollbars) { 4184 scrollabilityCache.state = ScrollabilityCache.ON; 4185 } 4186 scrollabilityCache.fadeScrollBars = fadeScrollbars; 4187 4188 4189 scrollabilityCache.scrollBarFadeDuration = a.getInt( 4190 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 4191 .getScrollBarFadeDuration()); 4192 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 4193 R.styleable.View_scrollbarDefaultDelayBeforeFade, 4194 ViewConfiguration.getScrollDefaultDelay()); 4195 4196 4197 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 4198 com.android.internal.R.styleable.View_scrollbarSize, 4199 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 4200 4201 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 4202 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 4203 4204 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 4205 if (thumb != null) { 4206 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 4207 } 4208 4209 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 4210 false); 4211 if (alwaysDraw) { 4212 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 4213 } 4214 4215 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 4216 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 4217 4218 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 4219 if (thumb != null) { 4220 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 4221 } 4222 4223 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 4224 false); 4225 if (alwaysDraw) { 4226 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 4227 } 4228 4229 // Apply layout direction to the new Drawables if needed 4230 final int layoutDirection = getLayoutDirection(); 4231 if (track != null) { 4232 track.setLayoutDirection(layoutDirection); 4233 } 4234 if (thumb != null) { 4235 thumb.setLayoutDirection(layoutDirection); 4236 } 4237 4238 // Re-apply user/background padding so that scrollbar(s) get added 4239 resolvePadding(); 4240 } 4241 4242 /** 4243 * <p> 4244 * Initalizes the scrollability cache if necessary. 4245 * </p> 4246 */ 4247 private void initScrollCache() { 4248 if (mScrollCache == null) { 4249 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 4250 } 4251 } 4252 4253 private ScrollabilityCache getScrollCache() { 4254 initScrollCache(); 4255 return mScrollCache; 4256 } 4257 4258 /** 4259 * Set the position of the vertical scroll bar. Should be one of 4260 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 4261 * {@link #SCROLLBAR_POSITION_RIGHT}. 4262 * 4263 * @param position Where the vertical scroll bar should be positioned. 4264 */ 4265 public void setVerticalScrollbarPosition(int position) { 4266 if (mVerticalScrollbarPosition != position) { 4267 mVerticalScrollbarPosition = position; 4268 computeOpaqueFlags(); 4269 resolvePadding(); 4270 } 4271 } 4272 4273 /** 4274 * @return The position where the vertical scroll bar will show, if applicable. 4275 * @see #setVerticalScrollbarPosition(int) 4276 */ 4277 public int getVerticalScrollbarPosition() { 4278 return mVerticalScrollbarPosition; 4279 } 4280 4281 ListenerInfo getListenerInfo() { 4282 if (mListenerInfo != null) { 4283 return mListenerInfo; 4284 } 4285 mListenerInfo = new ListenerInfo(); 4286 return mListenerInfo; 4287 } 4288 4289 /** 4290 * Register a callback to be invoked when focus of this view changed. 4291 * 4292 * @param l The callback that will run. 4293 */ 4294 public void setOnFocusChangeListener(OnFocusChangeListener l) { 4295 getListenerInfo().mOnFocusChangeListener = l; 4296 } 4297 4298 /** 4299 * Add a listener that will be called when the bounds of the view change due to 4300 * layout processing. 4301 * 4302 * @param listener The listener that will be called when layout bounds change. 4303 */ 4304 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 4305 ListenerInfo li = getListenerInfo(); 4306 if (li.mOnLayoutChangeListeners == null) { 4307 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 4308 } 4309 if (!li.mOnLayoutChangeListeners.contains(listener)) { 4310 li.mOnLayoutChangeListeners.add(listener); 4311 } 4312 } 4313 4314 /** 4315 * Remove a listener for layout changes. 4316 * 4317 * @param listener The listener for layout bounds change. 4318 */ 4319 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 4320 ListenerInfo li = mListenerInfo; 4321 if (li == null || li.mOnLayoutChangeListeners == null) { 4322 return; 4323 } 4324 li.mOnLayoutChangeListeners.remove(listener); 4325 } 4326 4327 /** 4328 * Add a listener for attach state changes. 4329 * 4330 * This listener will be called whenever this view is attached or detached 4331 * from a window. Remove the listener using 4332 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 4333 * 4334 * @param listener Listener to attach 4335 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 4336 */ 4337 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 4338 ListenerInfo li = getListenerInfo(); 4339 if (li.mOnAttachStateChangeListeners == null) { 4340 li.mOnAttachStateChangeListeners 4341 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 4342 } 4343 li.mOnAttachStateChangeListeners.add(listener); 4344 } 4345 4346 /** 4347 * Remove a listener for attach state changes. The listener will receive no further 4348 * notification of window attach/detach events. 4349 * 4350 * @param listener Listener to remove 4351 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 4352 */ 4353 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 4354 ListenerInfo li = mListenerInfo; 4355 if (li == null || li.mOnAttachStateChangeListeners == null) { 4356 return; 4357 } 4358 li.mOnAttachStateChangeListeners.remove(listener); 4359 } 4360 4361 /** 4362 * Returns the focus-change callback registered for this view. 4363 * 4364 * @return The callback, or null if one is not registered. 4365 */ 4366 public OnFocusChangeListener getOnFocusChangeListener() { 4367 ListenerInfo li = mListenerInfo; 4368 return li != null ? li.mOnFocusChangeListener : null; 4369 } 4370 4371 /** 4372 * Register a callback to be invoked when this view is clicked. If this view is not 4373 * clickable, it becomes clickable. 4374 * 4375 * @param l The callback that will run 4376 * 4377 * @see #setClickable(boolean) 4378 */ 4379 public void setOnClickListener(OnClickListener l) { 4380 if (!isClickable()) { 4381 setClickable(true); 4382 } 4383 getListenerInfo().mOnClickListener = l; 4384 } 4385 4386 /** 4387 * Return whether this view has an attached OnClickListener. Returns 4388 * true if there is a listener, false if there is none. 4389 */ 4390 public boolean hasOnClickListeners() { 4391 ListenerInfo li = mListenerInfo; 4392 return (li != null && li.mOnClickListener != null); 4393 } 4394 4395 /** 4396 * Register a callback to be invoked when this view is clicked and held. If this view is not 4397 * long clickable, it becomes long clickable. 4398 * 4399 * @param l The callback that will run 4400 * 4401 * @see #setLongClickable(boolean) 4402 */ 4403 public void setOnLongClickListener(OnLongClickListener l) { 4404 if (!isLongClickable()) { 4405 setLongClickable(true); 4406 } 4407 getListenerInfo().mOnLongClickListener = l; 4408 } 4409 4410 /** 4411 * Register a callback to be invoked when the context menu for this view is 4412 * being built. If this view is not long clickable, it becomes long clickable. 4413 * 4414 * @param l The callback that will run 4415 * 4416 */ 4417 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 4418 if (!isLongClickable()) { 4419 setLongClickable(true); 4420 } 4421 getListenerInfo().mOnCreateContextMenuListener = l; 4422 } 4423 4424 /** 4425 * Call this view's OnClickListener, if it is defined. Performs all normal 4426 * actions associated with clicking: reporting accessibility event, playing 4427 * a sound, etc. 4428 * 4429 * @return True there was an assigned OnClickListener that was called, false 4430 * otherwise is returned. 4431 */ 4432 public boolean performClick() { 4433 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 4434 4435 ListenerInfo li = mListenerInfo; 4436 if (li != null && li.mOnClickListener != null) { 4437 playSoundEffect(SoundEffectConstants.CLICK); 4438 li.mOnClickListener.onClick(this); 4439 return true; 4440 } 4441 4442 return false; 4443 } 4444 4445 /** 4446 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 4447 * this only calls the listener, and does not do any associated clicking 4448 * actions like reporting an accessibility event. 4449 * 4450 * @return True there was an assigned OnClickListener that was called, false 4451 * otherwise is returned. 4452 */ 4453 public boolean callOnClick() { 4454 ListenerInfo li = mListenerInfo; 4455 if (li != null && li.mOnClickListener != null) { 4456 li.mOnClickListener.onClick(this); 4457 return true; 4458 } 4459 return false; 4460 } 4461 4462 /** 4463 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the 4464 * OnLongClickListener did not consume the event. 4465 * 4466 * @return True if one of the above receivers consumed the event, false otherwise. 4467 */ 4468 public boolean performLongClick() { 4469 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 4470 4471 boolean handled = false; 4472 ListenerInfo li = mListenerInfo; 4473 if (li != null && li.mOnLongClickListener != null) { 4474 handled = li.mOnLongClickListener.onLongClick(View.this); 4475 } 4476 if (!handled) { 4477 handled = showContextMenu(); 4478 } 4479 if (handled) { 4480 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 4481 } 4482 return handled; 4483 } 4484 4485 /** 4486 * Performs button-related actions during a touch down event. 4487 * 4488 * @param event The event. 4489 * @return True if the down was consumed. 4490 * 4491 * @hide 4492 */ 4493 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 4494 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 4495 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) { 4496 return true; 4497 } 4498 } 4499 return false; 4500 } 4501 4502 /** 4503 * Bring up the context menu for this view. 4504 * 4505 * @return Whether a context menu was displayed. 4506 */ 4507 public boolean showContextMenu() { 4508 return getParent().showContextMenuForChild(this); 4509 } 4510 4511 /** 4512 * Bring up the context menu for this view, referring to the item under the specified point. 4513 * 4514 * @param x The referenced x coordinate. 4515 * @param y The referenced y coordinate. 4516 * @param metaState The keyboard modifiers that were pressed. 4517 * @return Whether a context menu was displayed. 4518 * 4519 * @hide 4520 */ 4521 public boolean showContextMenu(float x, float y, int metaState) { 4522 return showContextMenu(); 4523 } 4524 4525 /** 4526 * Start an action mode. 4527 * 4528 * @param callback Callback that will control the lifecycle of the action mode 4529 * @return The new action mode if it is started, null otherwise 4530 * 4531 * @see ActionMode 4532 */ 4533 public ActionMode startActionMode(ActionMode.Callback callback) { 4534 ViewParent parent = getParent(); 4535 if (parent == null) return null; 4536 return parent.startActionModeForChild(this, callback); 4537 } 4538 4539 /** 4540 * Register a callback to be invoked when a hardware key is pressed in this view. 4541 * Key presses in software input methods will generally not trigger the methods of 4542 * this listener. 4543 * @param l the key listener to attach to this view 4544 */ 4545 public void setOnKeyListener(OnKeyListener l) { 4546 getListenerInfo().mOnKeyListener = l; 4547 } 4548 4549 /** 4550 * Register a callback to be invoked when a touch event is sent to this view. 4551 * @param l the touch listener to attach to this view 4552 */ 4553 public void setOnTouchListener(OnTouchListener l) { 4554 getListenerInfo().mOnTouchListener = l; 4555 } 4556 4557 /** 4558 * Register a callback to be invoked when a generic motion event is sent to this view. 4559 * @param l the generic motion listener to attach to this view 4560 */ 4561 public void setOnGenericMotionListener(OnGenericMotionListener l) { 4562 getListenerInfo().mOnGenericMotionListener = l; 4563 } 4564 4565 /** 4566 * Register a callback to be invoked when a hover event is sent to this view. 4567 * @param l the hover listener to attach to this view 4568 */ 4569 public void setOnHoverListener(OnHoverListener l) { 4570 getListenerInfo().mOnHoverListener = l; 4571 } 4572 4573 /** 4574 * Register a drag event listener callback object for this View. The parameter is 4575 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 4576 * View, the system calls the 4577 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 4578 * @param l An implementation of {@link android.view.View.OnDragListener}. 4579 */ 4580 public void setOnDragListener(OnDragListener l) { 4581 getListenerInfo().mOnDragListener = l; 4582 } 4583 4584 /** 4585 * Give this view focus. This will cause 4586 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 4587 * 4588 * Note: this does not check whether this {@link View} should get focus, it just 4589 * gives it focus no matter what. It should only be called internally by framework 4590 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 4591 * 4592 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 4593 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 4594 * focus moved when requestFocus() is called. It may not always 4595 * apply, in which case use the default View.FOCUS_DOWN. 4596 * @param previouslyFocusedRect The rectangle of the view that had focus 4597 * prior in this View's coordinate system. 4598 */ 4599 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { 4600 if (DBG) { 4601 System.out.println(this + " requestFocus()"); 4602 } 4603 4604 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 4605 mPrivateFlags |= PFLAG_FOCUSED; 4606 4607 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 4608 4609 if (mParent != null) { 4610 mParent.requestChildFocus(this, this); 4611 } 4612 4613 if (mAttachInfo != null) { 4614 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 4615 } 4616 4617 onFocusChanged(true, direction, previouslyFocusedRect); 4618 refreshDrawableState(); 4619 } 4620 } 4621 4622 /** 4623 * Request that a rectangle of this view be visible on the screen, 4624 * scrolling if necessary just enough. 4625 * 4626 * <p>A View should call this if it maintains some notion of which part 4627 * of its content is interesting. For example, a text editing view 4628 * should call this when its cursor moves. 4629 * 4630 * @param rectangle The rectangle. 4631 * @return Whether any parent scrolled. 4632 */ 4633 public boolean requestRectangleOnScreen(Rect rectangle) { 4634 return requestRectangleOnScreen(rectangle, false); 4635 } 4636 4637 /** 4638 * Request that a rectangle of this view be visible on the screen, 4639 * scrolling if necessary just enough. 4640 * 4641 * <p>A View should call this if it maintains some notion of which part 4642 * of its content is interesting. For example, a text editing view 4643 * should call this when its cursor moves. 4644 * 4645 * <p>When <code>immediate</code> is set to true, scrolling will not be 4646 * animated. 4647 * 4648 * @param rectangle The rectangle. 4649 * @param immediate True to forbid animated scrolling, false otherwise 4650 * @return Whether any parent scrolled. 4651 */ 4652 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 4653 if (mParent == null) { 4654 return false; 4655 } 4656 4657 View child = this; 4658 4659 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 4660 position.set(rectangle); 4661 4662 ViewParent parent = mParent; 4663 boolean scrolled = false; 4664 while (parent != null) { 4665 rectangle.set((int) position.left, (int) position.top, 4666 (int) position.right, (int) position.bottom); 4667 4668 scrolled |= parent.requestChildRectangleOnScreen(child, 4669 rectangle, immediate); 4670 4671 if (!child.hasIdentityMatrix()) { 4672 child.getMatrix().mapRect(position); 4673 } 4674 4675 position.offset(child.mLeft, child.mTop); 4676 4677 if (!(parent instanceof View)) { 4678 break; 4679 } 4680 4681 View parentView = (View) parent; 4682 4683 position.offset(-parentView.getScrollX(), -parentView.getScrollY()); 4684 4685 child = parentView; 4686 parent = child.getParent(); 4687 } 4688 4689 return scrolled; 4690 } 4691 4692 /** 4693 * Called when this view wants to give up focus. If focus is cleared 4694 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 4695 * <p> 4696 * <strong>Note:</strong> When a View clears focus the framework is trying 4697 * to give focus to the first focusable View from the top. Hence, if this 4698 * View is the first from the top that can take focus, then all callbacks 4699 * related to clearing focus will be invoked after wich the framework will 4700 * give focus to this view. 4701 * </p> 4702 */ 4703 public void clearFocus() { 4704 if (DBG) { 4705 System.out.println(this + " clearFocus()"); 4706 } 4707 4708 clearFocusInternal(true, true); 4709 } 4710 4711 /** 4712 * Clears focus from the view, optionally propagating the change up through 4713 * the parent hierarchy and requesting that the root view place new focus. 4714 * 4715 * @param propagate whether to propagate the change up through the parent 4716 * hierarchy 4717 * @param refocus when propagate is true, specifies whether to request the 4718 * root view place new focus 4719 */ 4720 void clearFocusInternal(boolean propagate, boolean refocus) { 4721 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 4722 mPrivateFlags &= ~PFLAG_FOCUSED; 4723 4724 if (propagate && mParent != null) { 4725 mParent.clearChildFocus(this); 4726 } 4727 4728 onFocusChanged(false, 0, null); 4729 4730 refreshDrawableState(); 4731 4732 if (propagate && (!refocus || !rootViewRequestFocus())) { 4733 notifyGlobalFocusCleared(this); 4734 } 4735 } 4736 } 4737 4738 void notifyGlobalFocusCleared(View oldFocus) { 4739 if (oldFocus != null && mAttachInfo != null) { 4740 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 4741 } 4742 } 4743 4744 boolean rootViewRequestFocus() { 4745 final View root = getRootView(); 4746 return root != null && root.requestFocus(); 4747 } 4748 4749 /** 4750 * Called internally by the view system when a new view is getting focus. 4751 * This is what clears the old focus. 4752 * <p> 4753 * <b>NOTE:</b> The parent view's focused child must be updated manually 4754 * after calling this method. Otherwise, the view hierarchy may be left in 4755 * an inconstent state. 4756 */ 4757 void unFocus() { 4758 if (DBG) { 4759 System.out.println(this + " unFocus()"); 4760 } 4761 4762 clearFocusInternal(false, false); 4763 } 4764 4765 /** 4766 * Returns true if this view has focus iteself, or is the ancestor of the 4767 * view that has focus. 4768 * 4769 * @return True if this view has or contains focus, false otherwise. 4770 */ 4771 @ViewDebug.ExportedProperty(category = "focus") 4772 public boolean hasFocus() { 4773 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 4774 } 4775 4776 /** 4777 * Returns true if this view is focusable or if it contains a reachable View 4778 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 4779 * is a View whose parents do not block descendants focus. 4780 * 4781 * Only {@link #VISIBLE} views are considered focusable. 4782 * 4783 * @return True if the view is focusable or if the view contains a focusable 4784 * View, false otherwise. 4785 * 4786 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 4787 */ 4788 public boolean hasFocusable() { 4789 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 4790 } 4791 4792 /** 4793 * Called by the view system when the focus state of this view changes. 4794 * When the focus change event is caused by directional navigation, direction 4795 * and previouslyFocusedRect provide insight into where the focus is coming from. 4796 * When overriding, be sure to call up through to the super class so that 4797 * the standard focus handling will occur. 4798 * 4799 * @param gainFocus True if the View has focus; false otherwise. 4800 * @param direction The direction focus has moved when requestFocus() 4801 * is called to give this view focus. Values are 4802 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 4803 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 4804 * It may not always apply, in which case use the default. 4805 * @param previouslyFocusedRect The rectangle, in this view's coordinate 4806 * system, of the previously focused view. If applicable, this will be 4807 * passed in as finer grained information about where the focus is coming 4808 * from (in addition to direction). Will be <code>null</code> otherwise. 4809 */ 4810 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 4811 if (gainFocus) { 4812 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 4813 } else { 4814 notifyViewAccessibilityStateChangedIfNeeded( 4815 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 4816 } 4817 4818 InputMethodManager imm = InputMethodManager.peekInstance(); 4819 if (!gainFocus) { 4820 if (isPressed()) { 4821 setPressed(false); 4822 } 4823 if (imm != null && mAttachInfo != null 4824 && mAttachInfo.mHasWindowFocus) { 4825 imm.focusOut(this); 4826 } 4827 onFocusLost(); 4828 } else if (imm != null && mAttachInfo != null 4829 && mAttachInfo.mHasWindowFocus) { 4830 imm.focusIn(this); 4831 } 4832 4833 invalidate(true); 4834 ListenerInfo li = mListenerInfo; 4835 if (li != null && li.mOnFocusChangeListener != null) { 4836 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 4837 } 4838 4839 if (mAttachInfo != null) { 4840 mAttachInfo.mKeyDispatchState.reset(this); 4841 } 4842 } 4843 4844 /** 4845 * Sends an accessibility event of the given type. If accessibility is 4846 * not enabled this method has no effect. The default implementation calls 4847 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 4848 * to populate information about the event source (this View), then calls 4849 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 4850 * populate the text content of the event source including its descendants, 4851 * and last calls 4852 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 4853 * on its parent to resuest sending of the event to interested parties. 4854 * <p> 4855 * If an {@link AccessibilityDelegate} has been specified via calling 4856 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 4857 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 4858 * responsible for handling this call. 4859 * </p> 4860 * 4861 * @param eventType The type of the event to send, as defined by several types from 4862 * {@link android.view.accessibility.AccessibilityEvent}, such as 4863 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 4864 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 4865 * 4866 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 4867 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 4868 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 4869 * @see AccessibilityDelegate 4870 */ 4871 public void sendAccessibilityEvent(int eventType) { 4872 // Excluded views do not send accessibility events. 4873 if (!includeForAccessibility()) { 4874 return; 4875 } 4876 if (mAccessibilityDelegate != null) { 4877 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 4878 } else { 4879 sendAccessibilityEventInternal(eventType); 4880 } 4881 } 4882 4883 /** 4884 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 4885 * {@link AccessibilityEvent} to make an announcement which is related to some 4886 * sort of a context change for which none of the events representing UI transitions 4887 * is a good fit. For example, announcing a new page in a book. If accessibility 4888 * is not enabled this method does nothing. 4889 * 4890 * @param text The announcement text. 4891 */ 4892 public void announceForAccessibility(CharSequence text) { 4893 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 4894 AccessibilityEvent event = AccessibilityEvent.obtain( 4895 AccessibilityEvent.TYPE_ANNOUNCEMENT); 4896 onInitializeAccessibilityEvent(event); 4897 event.getText().add(text); 4898 event.setContentDescription(null); 4899 mParent.requestSendAccessibilityEvent(this, event); 4900 } 4901 } 4902 4903 /** 4904 * @see #sendAccessibilityEvent(int) 4905 * 4906 * Note: Called from the default {@link AccessibilityDelegate}. 4907 */ 4908 void sendAccessibilityEventInternal(int eventType) { 4909 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 4910 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 4911 } 4912 } 4913 4914 /** 4915 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 4916 * takes as an argument an empty {@link AccessibilityEvent} and does not 4917 * perform a check whether accessibility is enabled. 4918 * <p> 4919 * If an {@link AccessibilityDelegate} has been specified via calling 4920 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 4921 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 4922 * is responsible for handling this call. 4923 * </p> 4924 * 4925 * @param event The event to send. 4926 * 4927 * @see #sendAccessibilityEvent(int) 4928 */ 4929 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 4930 if (mAccessibilityDelegate != null) { 4931 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 4932 } else { 4933 sendAccessibilityEventUncheckedInternal(event); 4934 } 4935 } 4936 4937 /** 4938 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 4939 * 4940 * Note: Called from the default {@link AccessibilityDelegate}. 4941 */ 4942 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 4943 if (!isShown()) { 4944 return; 4945 } 4946 onInitializeAccessibilityEvent(event); 4947 // Only a subset of accessibility events populates text content. 4948 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 4949 dispatchPopulateAccessibilityEvent(event); 4950 } 4951 // In the beginning we called #isShown(), so we know that getParent() is not null. 4952 getParent().requestSendAccessibilityEvent(this, event); 4953 } 4954 4955 /** 4956 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 4957 * to its children for adding their text content to the event. Note that the 4958 * event text is populated in a separate dispatch path since we add to the 4959 * event not only the text of the source but also the text of all its descendants. 4960 * A typical implementation will call 4961 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 4962 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 4963 * on each child. Override this method if custom population of the event text 4964 * content is required. 4965 * <p> 4966 * If an {@link AccessibilityDelegate} has been specified via calling 4967 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 4968 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 4969 * is responsible for handling this call. 4970 * </p> 4971 * <p> 4972 * <em>Note:</em> Accessibility events of certain types are not dispatched for 4973 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 4974 * </p> 4975 * 4976 * @param event The event. 4977 * 4978 * @return True if the event population was completed. 4979 */ 4980 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 4981 if (mAccessibilityDelegate != null) { 4982 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 4983 } else { 4984 return dispatchPopulateAccessibilityEventInternal(event); 4985 } 4986 } 4987 4988 /** 4989 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 4990 * 4991 * Note: Called from the default {@link AccessibilityDelegate}. 4992 */ 4993 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 4994 onPopulateAccessibilityEvent(event); 4995 return false; 4996 } 4997 4998 /** 4999 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 5000 * giving a chance to this View to populate the accessibility event with its 5001 * text content. While this method is free to modify event 5002 * attributes other than text content, doing so should normally be performed in 5003 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 5004 * <p> 5005 * Example: Adding formatted date string to an accessibility event in addition 5006 * to the text added by the super implementation: 5007 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 5008 * super.onPopulateAccessibilityEvent(event); 5009 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 5010 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 5011 * mCurrentDate.getTimeInMillis(), flags); 5012 * event.getText().add(selectedDateUtterance); 5013 * }</pre> 5014 * <p> 5015 * If an {@link AccessibilityDelegate} has been specified via calling 5016 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5017 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 5018 * is responsible for handling this call. 5019 * </p> 5020 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 5021 * information to the event, in case the default implementation has basic information to add. 5022 * </p> 5023 * 5024 * @param event The accessibility event which to populate. 5025 * 5026 * @see #sendAccessibilityEvent(int) 5027 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5028 */ 5029 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 5030 if (mAccessibilityDelegate != null) { 5031 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 5032 } else { 5033 onPopulateAccessibilityEventInternal(event); 5034 } 5035 } 5036 5037 /** 5038 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 5039 * 5040 * Note: Called from the default {@link AccessibilityDelegate}. 5041 */ 5042 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 5043 } 5044 5045 /** 5046 * Initializes an {@link AccessibilityEvent} with information about 5047 * this View which is the event source. In other words, the source of 5048 * an accessibility event is the view whose state change triggered firing 5049 * the event. 5050 * <p> 5051 * Example: Setting the password property of an event in addition 5052 * to properties set by the super implementation: 5053 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 5054 * super.onInitializeAccessibilityEvent(event); 5055 * event.setPassword(true); 5056 * }</pre> 5057 * <p> 5058 * If an {@link AccessibilityDelegate} has been specified via calling 5059 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5060 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 5061 * is responsible for handling this call. 5062 * </p> 5063 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 5064 * information to the event, in case the default implementation has basic information to add. 5065 * </p> 5066 * @param event The event to initialize. 5067 * 5068 * @see #sendAccessibilityEvent(int) 5069 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5070 */ 5071 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 5072 if (mAccessibilityDelegate != null) { 5073 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 5074 } else { 5075 onInitializeAccessibilityEventInternal(event); 5076 } 5077 } 5078 5079 /** 5080 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 5081 * 5082 * Note: Called from the default {@link AccessibilityDelegate}. 5083 */ 5084 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 5085 event.setSource(this); 5086 event.setClassName(View.class.getName()); 5087 event.setPackageName(getContext().getPackageName()); 5088 event.setEnabled(isEnabled()); 5089 event.setContentDescription(mContentDescription); 5090 5091 switch (event.getEventType()) { 5092 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 5093 ArrayList<View> focusablesTempList = (mAttachInfo != null) 5094 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 5095 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 5096 event.setItemCount(focusablesTempList.size()); 5097 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 5098 if (mAttachInfo != null) { 5099 focusablesTempList.clear(); 5100 } 5101 } break; 5102 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 5103 CharSequence text = getIterableTextForAccessibility(); 5104 if (text != null && text.length() > 0) { 5105 event.setFromIndex(getAccessibilitySelectionStart()); 5106 event.setToIndex(getAccessibilitySelectionEnd()); 5107 event.setItemCount(text.length()); 5108 } 5109 } break; 5110 } 5111 } 5112 5113 /** 5114 * Returns an {@link AccessibilityNodeInfo} representing this view from the 5115 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 5116 * This method is responsible for obtaining an accessibility node info from a 5117 * pool of reusable instances and calling 5118 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 5119 * initialize the former. 5120 * <p> 5121 * Note: The client is responsible for recycling the obtained instance by calling 5122 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 5123 * </p> 5124 * 5125 * @return A populated {@link AccessibilityNodeInfo}. 5126 * 5127 * @see AccessibilityNodeInfo 5128 */ 5129 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 5130 if (mAccessibilityDelegate != null) { 5131 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 5132 } else { 5133 return createAccessibilityNodeInfoInternal(); 5134 } 5135 } 5136 5137 /** 5138 * @see #createAccessibilityNodeInfo() 5139 */ 5140 AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 5141 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 5142 if (provider != null) { 5143 return provider.createAccessibilityNodeInfo(View.NO_ID); 5144 } else { 5145 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 5146 onInitializeAccessibilityNodeInfo(info); 5147 return info; 5148 } 5149 } 5150 5151 /** 5152 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 5153 * The base implementation sets: 5154 * <ul> 5155 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 5156 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 5157 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 5158 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 5159 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 5160 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 5161 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 5162 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 5163 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 5164 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 5165 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 5166 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 5167 * </ul> 5168 * <p> 5169 * Subclasses should override this method, call the super implementation, 5170 * and set additional attributes. 5171 * </p> 5172 * <p> 5173 * If an {@link AccessibilityDelegate} has been specified via calling 5174 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5175 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 5176 * is responsible for handling this call. 5177 * </p> 5178 * 5179 * @param info The instance to initialize. 5180 */ 5181 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 5182 if (mAccessibilityDelegate != null) { 5183 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 5184 } else { 5185 onInitializeAccessibilityNodeInfoInternal(info); 5186 } 5187 } 5188 5189 /** 5190 * Gets the location of this view in screen coordintates. 5191 * 5192 * @param outRect The output location 5193 */ 5194 void getBoundsOnScreen(Rect outRect) { 5195 if (mAttachInfo == null) { 5196 return; 5197 } 5198 5199 RectF position = mAttachInfo.mTmpTransformRect; 5200 position.set(0, 0, mRight - mLeft, mBottom - mTop); 5201 5202 if (!hasIdentityMatrix()) { 5203 getMatrix().mapRect(position); 5204 } 5205 5206 position.offset(mLeft, mTop); 5207 5208 ViewParent parent = mParent; 5209 while (parent instanceof View) { 5210 View parentView = (View) parent; 5211 5212 position.offset(-parentView.mScrollX, -parentView.mScrollY); 5213 5214 if (!parentView.hasIdentityMatrix()) { 5215 parentView.getMatrix().mapRect(position); 5216 } 5217 5218 position.offset(parentView.mLeft, parentView.mTop); 5219 5220 parent = parentView.mParent; 5221 } 5222 5223 if (parent instanceof ViewRootImpl) { 5224 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 5225 position.offset(0, -viewRootImpl.mCurScrollY); 5226 } 5227 5228 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 5229 5230 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f), 5231 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f)); 5232 } 5233 5234 /** 5235 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 5236 * 5237 * Note: Called from the default {@link AccessibilityDelegate}. 5238 */ 5239 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 5240 Rect bounds = mAttachInfo.mTmpInvalRect; 5241 5242 getDrawingRect(bounds); 5243 info.setBoundsInParent(bounds); 5244 5245 getBoundsOnScreen(bounds); 5246 info.setBoundsInScreen(bounds); 5247 5248 ViewParent parent = getParentForAccessibility(); 5249 if (parent instanceof View) { 5250 info.setParent((View) parent); 5251 } 5252 5253 if (mID != View.NO_ID) { 5254 View rootView = getRootView(); 5255 if (rootView == null) { 5256 rootView = this; 5257 } 5258 View label = rootView.findLabelForView(this, mID); 5259 if (label != null) { 5260 info.setLabeledBy(label); 5261 } 5262 5263 if ((mAttachInfo.mAccessibilityFetchFlags 5264 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 5265 && Resources.resourceHasPackage(mID)) { 5266 try { 5267 String viewId = getResources().getResourceName(mID); 5268 info.setViewIdResourceName(viewId); 5269 } catch (Resources.NotFoundException nfe) { 5270 /* ignore */ 5271 } 5272 } 5273 } 5274 5275 if (mLabelForId != View.NO_ID) { 5276 View rootView = getRootView(); 5277 if (rootView == null) { 5278 rootView = this; 5279 } 5280 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 5281 if (labeled != null) { 5282 info.setLabelFor(labeled); 5283 } 5284 } 5285 5286 info.setVisibleToUser(isVisibleToUser()); 5287 5288 info.setPackageName(mContext.getPackageName()); 5289 info.setClassName(View.class.getName()); 5290 info.setContentDescription(getContentDescription()); 5291 5292 info.setEnabled(isEnabled()); 5293 info.setClickable(isClickable()); 5294 info.setFocusable(isFocusable()); 5295 info.setFocused(isFocused()); 5296 info.setAccessibilityFocused(isAccessibilityFocused()); 5297 info.setSelected(isSelected()); 5298 info.setLongClickable(isLongClickable()); 5299 info.setLiveRegion(getAccessibilityLiveRegion()); 5300 5301 // TODO: These make sense only if we are in an AdapterView but all 5302 // views can be selected. Maybe from accessibility perspective 5303 // we should report as selectable view in an AdapterView. 5304 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 5305 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 5306 5307 if (isFocusable()) { 5308 if (isFocused()) { 5309 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 5310 } else { 5311 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 5312 } 5313 } 5314 5315 if (!isAccessibilityFocused()) { 5316 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 5317 } else { 5318 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 5319 } 5320 5321 if (isClickable() && isEnabled()) { 5322 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 5323 } 5324 5325 if (isLongClickable() && isEnabled()) { 5326 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 5327 } 5328 5329 CharSequence text = getIterableTextForAccessibility(); 5330 if (text != null && text.length() > 0) { 5331 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 5332 5333 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 5334 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 5335 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 5336 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 5337 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 5338 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 5339 } 5340 } 5341 5342 private View findLabelForView(View view, int labeledId) { 5343 if (mMatchLabelForPredicate == null) { 5344 mMatchLabelForPredicate = new MatchLabelForPredicate(); 5345 } 5346 mMatchLabelForPredicate.mLabeledId = labeledId; 5347 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 5348 } 5349 5350 /** 5351 * Computes whether this view is visible to the user. Such a view is 5352 * attached, visible, all its predecessors are visible, it is not clipped 5353 * entirely by its predecessors, and has an alpha greater than zero. 5354 * 5355 * @return Whether the view is visible on the screen. 5356 * 5357 * @hide 5358 */ 5359 protected boolean isVisibleToUser() { 5360 return isVisibleToUser(null); 5361 } 5362 5363 /** 5364 * Computes whether the given portion of this view is visible to the user. 5365 * Such a view is attached, visible, all its predecessors are visible, 5366 * has an alpha greater than zero, and the specified portion is not 5367 * clipped entirely by its predecessors. 5368 * 5369 * @param boundInView the portion of the view to test; coordinates should be relative; may be 5370 * <code>null</code>, and the entire view will be tested in this case. 5371 * When <code>true</code> is returned by the function, the actual visible 5372 * region will be stored in this parameter; that is, if boundInView is fully 5373 * contained within the view, no modification will be made, otherwise regions 5374 * outside of the visible area of the view will be clipped. 5375 * 5376 * @return Whether the specified portion of the view is visible on the screen. 5377 * 5378 * @hide 5379 */ 5380 protected boolean isVisibleToUser(Rect boundInView) { 5381 if (mAttachInfo != null) { 5382 // Attached to invisible window means this view is not visible. 5383 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 5384 return false; 5385 } 5386 // An invisible predecessor or one with alpha zero means 5387 // that this view is not visible to the user. 5388 Object current = this; 5389 while (current instanceof View) { 5390 View view = (View) current; 5391 // We have attach info so this view is attached and there is no 5392 // need to check whether we reach to ViewRootImpl on the way up. 5393 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 5394 view.getVisibility() != VISIBLE) { 5395 return false; 5396 } 5397 current = view.mParent; 5398 } 5399 // Check if the view is entirely covered by its predecessors. 5400 Rect visibleRect = mAttachInfo.mTmpInvalRect; 5401 Point offset = mAttachInfo.mPoint; 5402 if (!getGlobalVisibleRect(visibleRect, offset)) { 5403 return false; 5404 } 5405 // Check if the visible portion intersects the rectangle of interest. 5406 if (boundInView != null) { 5407 visibleRect.offset(-offset.x, -offset.y); 5408 return boundInView.intersect(visibleRect); 5409 } 5410 return true; 5411 } 5412 return false; 5413 } 5414 5415 /** 5416 * Returns the delegate for implementing accessibility support via 5417 * composition. For more details see {@link AccessibilityDelegate}. 5418 * 5419 * @return The delegate, or null if none set. 5420 * 5421 * @hide 5422 */ 5423 public AccessibilityDelegate getAccessibilityDelegate() { 5424 return mAccessibilityDelegate; 5425 } 5426 5427 /** 5428 * Sets a delegate for implementing accessibility support via composition as 5429 * opposed to inheritance. The delegate's primary use is for implementing 5430 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}. 5431 * 5432 * @param delegate The delegate instance. 5433 * 5434 * @see AccessibilityDelegate 5435 */ 5436 public void setAccessibilityDelegate(AccessibilityDelegate delegate) { 5437 mAccessibilityDelegate = delegate; 5438 } 5439 5440 /** 5441 * Gets the provider for managing a virtual view hierarchy rooted at this View 5442 * and reported to {@link android.accessibilityservice.AccessibilityService}s 5443 * that explore the window content. 5444 * <p> 5445 * If this method returns an instance, this instance is responsible for managing 5446 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 5447 * View including the one representing the View itself. Similarly the returned 5448 * instance is responsible for performing accessibility actions on any virtual 5449 * view or the root view itself. 5450 * </p> 5451 * <p> 5452 * If an {@link AccessibilityDelegate} has been specified via calling 5453 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5454 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 5455 * is responsible for handling this call. 5456 * </p> 5457 * 5458 * @return The provider. 5459 * 5460 * @see AccessibilityNodeProvider 5461 */ 5462 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 5463 if (mAccessibilityDelegate != null) { 5464 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 5465 } else { 5466 return null; 5467 } 5468 } 5469 5470 /** 5471 * Gets the unique identifier of this view on the screen for accessibility purposes. 5472 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 5473 * 5474 * @return The view accessibility id. 5475 * 5476 * @hide 5477 */ 5478 public int getAccessibilityViewId() { 5479 if (mAccessibilityViewId == NO_ID) { 5480 mAccessibilityViewId = sNextAccessibilityViewId++; 5481 } 5482 return mAccessibilityViewId; 5483 } 5484 5485 /** 5486 * Gets the unique identifier of the window in which this View reseides. 5487 * 5488 * @return The window accessibility id. 5489 * 5490 * @hide 5491 */ 5492 public int getAccessibilityWindowId() { 5493 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID; 5494 } 5495 5496 /** 5497 * Gets the {@link View} description. It briefly describes the view and is 5498 * primarily used for accessibility support. Set this property to enable 5499 * better accessibility support for your application. This is especially 5500 * true for views that do not have textual representation (For example, 5501 * ImageButton). 5502 * 5503 * @return The content description. 5504 * 5505 * @attr ref android.R.styleable#View_contentDescription 5506 */ 5507 @ViewDebug.ExportedProperty(category = "accessibility") 5508 public CharSequence getContentDescription() { 5509 return mContentDescription; 5510 } 5511 5512 /** 5513 * Sets the {@link View} description. It briefly describes the view and is 5514 * primarily used for accessibility support. Set this property to enable 5515 * better accessibility support for your application. This is especially 5516 * true for views that do not have textual representation (For example, 5517 * ImageButton). 5518 * 5519 * @param contentDescription The content description. 5520 * 5521 * @attr ref android.R.styleable#View_contentDescription 5522 */ 5523 @RemotableViewMethod 5524 public void setContentDescription(CharSequence contentDescription) { 5525 if (mContentDescription == null) { 5526 if (contentDescription == null) { 5527 return; 5528 } 5529 } else if (mContentDescription.equals(contentDescription)) { 5530 return; 5531 } 5532 mContentDescription = contentDescription; 5533 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 5534 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 5535 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 5536 notifySubtreeAccessibilityStateChangedIfNeeded(); 5537 } else { 5538 notifyViewAccessibilityStateChangedIfNeeded( 5539 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 5540 } 5541 } 5542 5543 /** 5544 * Gets the id of a view for which this view serves as a label for 5545 * accessibility purposes. 5546 * 5547 * @return The labeled view id. 5548 */ 5549 @ViewDebug.ExportedProperty(category = "accessibility") 5550 public int getLabelFor() { 5551 return mLabelForId; 5552 } 5553 5554 /** 5555 * Sets the id of a view for which this view serves as a label for 5556 * accessibility purposes. 5557 * 5558 * @param id The labeled view id. 5559 */ 5560 @RemotableViewMethod 5561 public void setLabelFor(int id) { 5562 mLabelForId = id; 5563 if (mLabelForId != View.NO_ID 5564 && mID == View.NO_ID) { 5565 mID = generateViewId(); 5566 } 5567 } 5568 5569 /** 5570 * Invoked whenever this view loses focus, either by losing window focus or by losing 5571 * focus within its window. This method can be used to clear any state tied to the 5572 * focus. For instance, if a button is held pressed with the trackball and the window 5573 * loses focus, this method can be used to cancel the press. 5574 * 5575 * Subclasses of View overriding this method should always call super.onFocusLost(). 5576 * 5577 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 5578 * @see #onWindowFocusChanged(boolean) 5579 * 5580 * @hide pending API council approval 5581 */ 5582 protected void onFocusLost() { 5583 resetPressedState(); 5584 } 5585 5586 private void resetPressedState() { 5587 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 5588 return; 5589 } 5590 5591 if (isPressed()) { 5592 setPressed(false); 5593 5594 if (!mHasPerformedLongPress) { 5595 removeLongPressCallback(); 5596 } 5597 } 5598 } 5599 5600 /** 5601 * Returns true if this view has focus 5602 * 5603 * @return True if this view has focus, false otherwise. 5604 */ 5605 @ViewDebug.ExportedProperty(category = "focus") 5606 public boolean isFocused() { 5607 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 5608 } 5609 5610 /** 5611 * Find the view in the hierarchy rooted at this view that currently has 5612 * focus. 5613 * 5614 * @return The view that currently has focus, or null if no focused view can 5615 * be found. 5616 */ 5617 public View findFocus() { 5618 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 5619 } 5620 5621 /** 5622 * Indicates whether this view is one of the set of scrollable containers in 5623 * its window. 5624 * 5625 * @return whether this view is one of the set of scrollable containers in 5626 * its window 5627 * 5628 * @attr ref android.R.styleable#View_isScrollContainer 5629 */ 5630 public boolean isScrollContainer() { 5631 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 5632 } 5633 5634 /** 5635 * Change whether this view is one of the set of scrollable containers in 5636 * its window. This will be used to determine whether the window can 5637 * resize or must pan when a soft input area is open -- scrollable 5638 * containers allow the window to use resize mode since the container 5639 * will appropriately shrink. 5640 * 5641 * @attr ref android.R.styleable#View_isScrollContainer 5642 */ 5643 public void setScrollContainer(boolean isScrollContainer) { 5644 if (isScrollContainer) { 5645 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 5646 mAttachInfo.mScrollContainers.add(this); 5647 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 5648 } 5649 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 5650 } else { 5651 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 5652 mAttachInfo.mScrollContainers.remove(this); 5653 } 5654 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 5655 } 5656 } 5657 5658 /** 5659 * Returns the quality of the drawing cache. 5660 * 5661 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 5662 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 5663 * 5664 * @see #setDrawingCacheQuality(int) 5665 * @see #setDrawingCacheEnabled(boolean) 5666 * @see #isDrawingCacheEnabled() 5667 * 5668 * @attr ref android.R.styleable#View_drawingCacheQuality 5669 */ 5670 public int getDrawingCacheQuality() { 5671 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 5672 } 5673 5674 /** 5675 * Set the drawing cache quality of this view. This value is used only when the 5676 * drawing cache is enabled 5677 * 5678 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 5679 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 5680 * 5681 * @see #getDrawingCacheQuality() 5682 * @see #setDrawingCacheEnabled(boolean) 5683 * @see #isDrawingCacheEnabled() 5684 * 5685 * @attr ref android.R.styleable#View_drawingCacheQuality 5686 */ 5687 public void setDrawingCacheQuality(int quality) { 5688 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 5689 } 5690 5691 /** 5692 * Returns whether the screen should remain on, corresponding to the current 5693 * value of {@link #KEEP_SCREEN_ON}. 5694 * 5695 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 5696 * 5697 * @see #setKeepScreenOn(boolean) 5698 * 5699 * @attr ref android.R.styleable#View_keepScreenOn 5700 */ 5701 public boolean getKeepScreenOn() { 5702 return (mViewFlags & KEEP_SCREEN_ON) != 0; 5703 } 5704 5705 /** 5706 * Controls whether the screen should remain on, modifying the 5707 * value of {@link #KEEP_SCREEN_ON}. 5708 * 5709 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 5710 * 5711 * @see #getKeepScreenOn() 5712 * 5713 * @attr ref android.R.styleable#View_keepScreenOn 5714 */ 5715 public void setKeepScreenOn(boolean keepScreenOn) { 5716 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 5717 } 5718 5719 /** 5720 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 5721 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5722 * 5723 * @attr ref android.R.styleable#View_nextFocusLeft 5724 */ 5725 public int getNextFocusLeftId() { 5726 return mNextFocusLeftId; 5727 } 5728 5729 /** 5730 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 5731 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 5732 * decide automatically. 5733 * 5734 * @attr ref android.R.styleable#View_nextFocusLeft 5735 */ 5736 public void setNextFocusLeftId(int nextFocusLeftId) { 5737 mNextFocusLeftId = nextFocusLeftId; 5738 } 5739 5740 /** 5741 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 5742 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5743 * 5744 * @attr ref android.R.styleable#View_nextFocusRight 5745 */ 5746 public int getNextFocusRightId() { 5747 return mNextFocusRightId; 5748 } 5749 5750 /** 5751 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 5752 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 5753 * decide automatically. 5754 * 5755 * @attr ref android.R.styleable#View_nextFocusRight 5756 */ 5757 public void setNextFocusRightId(int nextFocusRightId) { 5758 mNextFocusRightId = nextFocusRightId; 5759 } 5760 5761 /** 5762 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 5763 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5764 * 5765 * @attr ref android.R.styleable#View_nextFocusUp 5766 */ 5767 public int getNextFocusUpId() { 5768 return mNextFocusUpId; 5769 } 5770 5771 /** 5772 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 5773 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 5774 * decide automatically. 5775 * 5776 * @attr ref android.R.styleable#View_nextFocusUp 5777 */ 5778 public void setNextFocusUpId(int nextFocusUpId) { 5779 mNextFocusUpId = nextFocusUpId; 5780 } 5781 5782 /** 5783 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 5784 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5785 * 5786 * @attr ref android.R.styleable#View_nextFocusDown 5787 */ 5788 public int getNextFocusDownId() { 5789 return mNextFocusDownId; 5790 } 5791 5792 /** 5793 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 5794 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 5795 * decide automatically. 5796 * 5797 * @attr ref android.R.styleable#View_nextFocusDown 5798 */ 5799 public void setNextFocusDownId(int nextFocusDownId) { 5800 mNextFocusDownId = nextFocusDownId; 5801 } 5802 5803 /** 5804 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 5805 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5806 * 5807 * @attr ref android.R.styleable#View_nextFocusForward 5808 */ 5809 public int getNextFocusForwardId() { 5810 return mNextFocusForwardId; 5811 } 5812 5813 /** 5814 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 5815 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 5816 * decide automatically. 5817 * 5818 * @attr ref android.R.styleable#View_nextFocusForward 5819 */ 5820 public void setNextFocusForwardId(int nextFocusForwardId) { 5821 mNextFocusForwardId = nextFocusForwardId; 5822 } 5823 5824 /** 5825 * Returns the visibility of this view and all of its ancestors 5826 * 5827 * @return True if this view and all of its ancestors are {@link #VISIBLE} 5828 */ 5829 public boolean isShown() { 5830 View current = this; 5831 //noinspection ConstantConditions 5832 do { 5833 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 5834 return false; 5835 } 5836 ViewParent parent = current.mParent; 5837 if (parent == null) { 5838 return false; // We are not attached to the view root 5839 } 5840 if (!(parent instanceof View)) { 5841 return true; 5842 } 5843 current = (View) parent; 5844 } while (current != null); 5845 5846 return false; 5847 } 5848 5849 /** 5850 * Called by the view hierarchy when the content insets for a window have 5851 * changed, to allow it to adjust its content to fit within those windows. 5852 * The content insets tell you the space that the status bar, input method, 5853 * and other system windows infringe on the application's window. 5854 * 5855 * <p>You do not normally need to deal with this function, since the default 5856 * window decoration given to applications takes care of applying it to the 5857 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 5858 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 5859 * and your content can be placed under those system elements. You can then 5860 * use this method within your view hierarchy if you have parts of your UI 5861 * which you would like to ensure are not being covered. 5862 * 5863 * <p>The default implementation of this method simply applies the content 5864 * insets to the view's padding, consuming that content (modifying the 5865 * insets to be 0), and returning true. This behavior is off by default, but can 5866 * be enabled through {@link #setFitsSystemWindows(boolean)}. 5867 * 5868 * <p>This function's traversal down the hierarchy is depth-first. The same content 5869 * insets object is propagated down the hierarchy, so any changes made to it will 5870 * be seen by all following views (including potentially ones above in 5871 * the hierarchy since this is a depth-first traversal). The first view 5872 * that returns true will abort the entire traversal. 5873 * 5874 * <p>The default implementation works well for a situation where it is 5875 * used with a container that covers the entire window, allowing it to 5876 * apply the appropriate insets to its content on all edges. If you need 5877 * a more complicated layout (such as two different views fitting system 5878 * windows, one on the top of the window, and one on the bottom), 5879 * you can override the method and handle the insets however you would like. 5880 * Note that the insets provided by the framework are always relative to the 5881 * far edges of the window, not accounting for the location of the called view 5882 * within that window. (In fact when this method is called you do not yet know 5883 * where the layout will place the view, as it is done before layout happens.) 5884 * 5885 * <p>Note: unlike many View methods, there is no dispatch phase to this 5886 * call. If you are overriding it in a ViewGroup and want to allow the 5887 * call to continue to your children, you must be sure to call the super 5888 * implementation. 5889 * 5890 * <p>Here is a sample layout that makes use of fitting system windows 5891 * to have controls for a video view placed inside of the window decorations 5892 * that it hides and shows. This can be used with code like the second 5893 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 5894 * 5895 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 5896 * 5897 * @param insets Current content insets of the window. Prior to 5898 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 5899 * the insets or else you and Android will be unhappy. 5900 * 5901 * @return {@code true} if this view applied the insets and it should not 5902 * continue propagating further down the hierarchy, {@code false} otherwise. 5903 * @see #getFitsSystemWindows() 5904 * @see #setFitsSystemWindows(boolean) 5905 * @see #setSystemUiVisibility(int) 5906 */ 5907 protected boolean fitSystemWindows(Rect insets) { 5908 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 5909 mUserPaddingStart = UNDEFINED_PADDING; 5910 mUserPaddingEnd = UNDEFINED_PADDING; 5911 Rect localInsets = sThreadLocal.get(); 5912 if (localInsets == null) { 5913 localInsets = new Rect(); 5914 sThreadLocal.set(localInsets); 5915 } 5916 boolean res = computeFitSystemWindows(insets, localInsets); 5917 mUserPaddingLeftInitial = localInsets.left; 5918 mUserPaddingRightInitial = localInsets.right; 5919 internalSetPadding(localInsets.left, localInsets.top, 5920 localInsets.right, localInsets.bottom); 5921 return res; 5922 } 5923 return false; 5924 } 5925 5926 /** 5927 * @hide Compute the insets that should be consumed by this view and the ones 5928 * that should propagate to those under it. 5929 */ 5930 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 5931 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 5932 || mAttachInfo == null 5933 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 5934 && !mAttachInfo.mOverscanRequested)) { 5935 outLocalInsets.set(inoutInsets); 5936 inoutInsets.set(0, 0, 0, 0); 5937 return true; 5938 } else { 5939 // The application wants to take care of fitting system window for 5940 // the content... however we still need to take care of any overscan here. 5941 final Rect overscan = mAttachInfo.mOverscanInsets; 5942 outLocalInsets.set(overscan); 5943 inoutInsets.left -= overscan.left; 5944 inoutInsets.top -= overscan.top; 5945 inoutInsets.right -= overscan.right; 5946 inoutInsets.bottom -= overscan.bottom; 5947 return false; 5948 } 5949 } 5950 5951 /** 5952 * Sets whether or not this view should account for system screen decorations 5953 * such as the status bar and inset its content; that is, controlling whether 5954 * the default implementation of {@link #fitSystemWindows(Rect)} will be 5955 * executed. See that method for more details. 5956 * 5957 * <p>Note that if you are providing your own implementation of 5958 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 5959 * flag to true -- your implementation will be overriding the default 5960 * implementation that checks this flag. 5961 * 5962 * @param fitSystemWindows If true, then the default implementation of 5963 * {@link #fitSystemWindows(Rect)} will be executed. 5964 * 5965 * @attr ref android.R.styleable#View_fitsSystemWindows 5966 * @see #getFitsSystemWindows() 5967 * @see #fitSystemWindows(Rect) 5968 * @see #setSystemUiVisibility(int) 5969 */ 5970 public void setFitsSystemWindows(boolean fitSystemWindows) { 5971 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 5972 } 5973 5974 /** 5975 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 5976 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 5977 * will be executed. 5978 * 5979 * @return {@code true} if the default implementation of 5980 * {@link #fitSystemWindows(Rect)} will be executed. 5981 * 5982 * @attr ref android.R.styleable#View_fitsSystemWindows 5983 * @see #setFitsSystemWindows(boolean) 5984 * @see #fitSystemWindows(Rect) 5985 * @see #setSystemUiVisibility(int) 5986 */ 5987 public boolean getFitsSystemWindows() { 5988 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 5989 } 5990 5991 /** @hide */ 5992 public boolean fitsSystemWindows() { 5993 return getFitsSystemWindows(); 5994 } 5995 5996 /** 5997 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 5998 */ 5999 public void requestFitSystemWindows() { 6000 if (mParent != null) { 6001 mParent.requestFitSystemWindows(); 6002 } 6003 } 6004 6005 /** 6006 * For use by PhoneWindow to make its own system window fitting optional. 6007 * @hide 6008 */ 6009 public void makeOptionalFitsSystemWindows() { 6010 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 6011 } 6012 6013 /** 6014 * Returns the visibility status for this view. 6015 * 6016 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 6017 * @attr ref android.R.styleable#View_visibility 6018 */ 6019 @ViewDebug.ExportedProperty(mapping = { 6020 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 6021 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 6022 @ViewDebug.IntToString(from = GONE, to = "GONE") 6023 }) 6024 public int getVisibility() { 6025 return mViewFlags & VISIBILITY_MASK; 6026 } 6027 6028 /** 6029 * Set the enabled state of this view. 6030 * 6031 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 6032 * @attr ref android.R.styleable#View_visibility 6033 */ 6034 @RemotableViewMethod 6035 public void setVisibility(int visibility) { 6036 setFlags(visibility, VISIBILITY_MASK); 6037 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false); 6038 } 6039 6040 /** 6041 * Returns the enabled status for this view. The interpretation of the 6042 * enabled state varies by subclass. 6043 * 6044 * @return True if this view is enabled, false otherwise. 6045 */ 6046 @ViewDebug.ExportedProperty 6047 public boolean isEnabled() { 6048 return (mViewFlags & ENABLED_MASK) == ENABLED; 6049 } 6050 6051 /** 6052 * Set the enabled state of this view. The interpretation of the enabled 6053 * state varies by subclass. 6054 * 6055 * @param enabled True if this view is enabled, false otherwise. 6056 */ 6057 @RemotableViewMethod 6058 public void setEnabled(boolean enabled) { 6059 if (enabled == isEnabled()) return; 6060 6061 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 6062 6063 /* 6064 * The View most likely has to change its appearance, so refresh 6065 * the drawable state. 6066 */ 6067 refreshDrawableState(); 6068 6069 // Invalidate too, since the default behavior for views is to be 6070 // be drawn at 50% alpha rather than to change the drawable. 6071 invalidate(true); 6072 6073 if (!enabled) { 6074 cancelPendingInputEvents(); 6075 } 6076 } 6077 6078 /** 6079 * Set whether this view can receive the focus. 6080 * 6081 * Setting this to false will also ensure that this view is not focusable 6082 * in touch mode. 6083 * 6084 * @param focusable If true, this view can receive the focus. 6085 * 6086 * @see #setFocusableInTouchMode(boolean) 6087 * @attr ref android.R.styleable#View_focusable 6088 */ 6089 public void setFocusable(boolean focusable) { 6090 if (!focusable) { 6091 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 6092 } 6093 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 6094 } 6095 6096 /** 6097 * Set whether this view can receive focus while in touch mode. 6098 * 6099 * Setting this to true will also ensure that this view is focusable. 6100 * 6101 * @param focusableInTouchMode If true, this view can receive the focus while 6102 * in touch mode. 6103 * 6104 * @see #setFocusable(boolean) 6105 * @attr ref android.R.styleable#View_focusableInTouchMode 6106 */ 6107 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 6108 // Focusable in touch mode should always be set before the focusable flag 6109 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 6110 // which, in touch mode, will not successfully request focus on this view 6111 // because the focusable in touch mode flag is not set 6112 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 6113 if (focusableInTouchMode) { 6114 setFlags(FOCUSABLE, FOCUSABLE_MASK); 6115 } 6116 } 6117 6118 /** 6119 * Set whether this view should have sound effects enabled for events such as 6120 * clicking and touching. 6121 * 6122 * <p>You may wish to disable sound effects for a view if you already play sounds, 6123 * for instance, a dial key that plays dtmf tones. 6124 * 6125 * @param soundEffectsEnabled whether sound effects are enabled for this view. 6126 * @see #isSoundEffectsEnabled() 6127 * @see #playSoundEffect(int) 6128 * @attr ref android.R.styleable#View_soundEffectsEnabled 6129 */ 6130 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 6131 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 6132 } 6133 6134 /** 6135 * @return whether this view should have sound effects enabled for events such as 6136 * clicking and touching. 6137 * 6138 * @see #setSoundEffectsEnabled(boolean) 6139 * @see #playSoundEffect(int) 6140 * @attr ref android.R.styleable#View_soundEffectsEnabled 6141 */ 6142 @ViewDebug.ExportedProperty 6143 public boolean isSoundEffectsEnabled() { 6144 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 6145 } 6146 6147 /** 6148 * Set whether this view should have haptic feedback for events such as 6149 * long presses. 6150 * 6151 * <p>You may wish to disable haptic feedback if your view already controls 6152 * its own haptic feedback. 6153 * 6154 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 6155 * @see #isHapticFeedbackEnabled() 6156 * @see #performHapticFeedback(int) 6157 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 6158 */ 6159 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 6160 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 6161 } 6162 6163 /** 6164 * @return whether this view should have haptic feedback enabled for events 6165 * long presses. 6166 * 6167 * @see #setHapticFeedbackEnabled(boolean) 6168 * @see #performHapticFeedback(int) 6169 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 6170 */ 6171 @ViewDebug.ExportedProperty 6172 public boolean isHapticFeedbackEnabled() { 6173 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 6174 } 6175 6176 /** 6177 * Returns the layout direction for this view. 6178 * 6179 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 6180 * {@link #LAYOUT_DIRECTION_RTL}, 6181 * {@link #LAYOUT_DIRECTION_INHERIT} or 6182 * {@link #LAYOUT_DIRECTION_LOCALE}. 6183 * 6184 * @attr ref android.R.styleable#View_layoutDirection 6185 * 6186 * @hide 6187 */ 6188 @ViewDebug.ExportedProperty(category = "layout", mapping = { 6189 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 6190 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 6191 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 6192 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 6193 }) 6194 public int getRawLayoutDirection() { 6195 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 6196 } 6197 6198 /** 6199 * Set the layout direction for this view. This will propagate a reset of layout direction 6200 * resolution to the view's children and resolve layout direction for this view. 6201 * 6202 * @param layoutDirection the layout direction to set. Should be one of: 6203 * 6204 * {@link #LAYOUT_DIRECTION_LTR}, 6205 * {@link #LAYOUT_DIRECTION_RTL}, 6206 * {@link #LAYOUT_DIRECTION_INHERIT}, 6207 * {@link #LAYOUT_DIRECTION_LOCALE}. 6208 * 6209 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 6210 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 6211 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 6212 * 6213 * @attr ref android.R.styleable#View_layoutDirection 6214 */ 6215 @RemotableViewMethod 6216 public void setLayoutDirection(int layoutDirection) { 6217 if (getRawLayoutDirection() != layoutDirection) { 6218 // Reset the current layout direction and the resolved one 6219 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 6220 resetRtlProperties(); 6221 // Set the new layout direction (filtered) 6222 mPrivateFlags2 |= 6223 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 6224 // We need to resolve all RTL properties as they all depend on layout direction 6225 resolveRtlPropertiesIfNeeded(); 6226 requestLayout(); 6227 invalidate(true); 6228 } 6229 } 6230 6231 /** 6232 * Returns the resolved layout direction for this view. 6233 * 6234 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 6235 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 6236 * 6237 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 6238 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 6239 * 6240 * @attr ref android.R.styleable#View_layoutDirection 6241 */ 6242 @ViewDebug.ExportedProperty(category = "layout", mapping = { 6243 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 6244 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 6245 }) 6246 public int getLayoutDirection() { 6247 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 6248 if (targetSdkVersion < JELLY_BEAN_MR1) { 6249 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 6250 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 6251 } 6252 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 6253 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 6254 } 6255 6256 /** 6257 * Indicates whether or not this view's layout is right-to-left. This is resolved from 6258 * layout attribute and/or the inherited value from the parent 6259 * 6260 * @return true if the layout is right-to-left. 6261 * 6262 * @hide 6263 */ 6264 @ViewDebug.ExportedProperty(category = "layout") 6265 public boolean isLayoutRtl() { 6266 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 6267 } 6268 6269 /** 6270 * Indicates whether the view is currently tracking transient state that the 6271 * app should not need to concern itself with saving and restoring, but that 6272 * the framework should take special note to preserve when possible. 6273 * 6274 * <p>A view with transient state cannot be trivially rebound from an external 6275 * data source, such as an adapter binding item views in a list. This may be 6276 * because the view is performing an animation, tracking user selection 6277 * of content, or similar.</p> 6278 * 6279 * @return true if the view has transient state 6280 */ 6281 @ViewDebug.ExportedProperty(category = "layout") 6282 public boolean hasTransientState() { 6283 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 6284 } 6285 6286 /** 6287 * Set whether this view is currently tracking transient state that the 6288 * framework should attempt to preserve when possible. This flag is reference counted, 6289 * so every call to setHasTransientState(true) should be paired with a later call 6290 * to setHasTransientState(false). 6291 * 6292 * <p>A view with transient state cannot be trivially rebound from an external 6293 * data source, such as an adapter binding item views in a list. This may be 6294 * because the view is performing an animation, tracking user selection 6295 * of content, or similar.</p> 6296 * 6297 * @param hasTransientState true if this view has transient state 6298 */ 6299 public void setHasTransientState(boolean hasTransientState) { 6300 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 6301 mTransientStateCount - 1; 6302 if (mTransientStateCount < 0) { 6303 mTransientStateCount = 0; 6304 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 6305 "unmatched pair of setHasTransientState calls"); 6306 } else if ((hasTransientState && mTransientStateCount == 1) || 6307 (!hasTransientState && mTransientStateCount == 0)) { 6308 // update flag if we've just incremented up from 0 or decremented down to 0 6309 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 6310 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 6311 if (mParent != null) { 6312 try { 6313 mParent.childHasTransientStateChanged(this, hasTransientState); 6314 } catch (AbstractMethodError e) { 6315 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 6316 " does not fully implement ViewParent", e); 6317 } 6318 } 6319 } 6320 } 6321 6322 /** 6323 * Returns true if this view is currently attached to a window. 6324 */ 6325 public boolean isAttachedToWindow() { 6326 return mAttachInfo != null; 6327 } 6328 6329 /** 6330 * Returns true if this view has been through at least one layout since it 6331 * was last attached to or detached from a window. 6332 */ 6333 public boolean isLaidOut() { 6334 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 6335 } 6336 6337 /** 6338 * If this view doesn't do any drawing on its own, set this flag to 6339 * allow further optimizations. By default, this flag is not set on 6340 * View, but could be set on some View subclasses such as ViewGroup. 6341 * 6342 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 6343 * you should clear this flag. 6344 * 6345 * @param willNotDraw whether or not this View draw on its own 6346 */ 6347 public void setWillNotDraw(boolean willNotDraw) { 6348 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 6349 } 6350 6351 /** 6352 * Returns whether or not this View draws on its own. 6353 * 6354 * @return true if this view has nothing to draw, false otherwise 6355 */ 6356 @ViewDebug.ExportedProperty(category = "drawing") 6357 public boolean willNotDraw() { 6358 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 6359 } 6360 6361 /** 6362 * When a View's drawing cache is enabled, drawing is redirected to an 6363 * offscreen bitmap. Some views, like an ImageView, must be able to 6364 * bypass this mechanism if they already draw a single bitmap, to avoid 6365 * unnecessary usage of the memory. 6366 * 6367 * @param willNotCacheDrawing true if this view does not cache its 6368 * drawing, false otherwise 6369 */ 6370 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 6371 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 6372 } 6373 6374 /** 6375 * Returns whether or not this View can cache its drawing or not. 6376 * 6377 * @return true if this view does not cache its drawing, false otherwise 6378 */ 6379 @ViewDebug.ExportedProperty(category = "drawing") 6380 public boolean willNotCacheDrawing() { 6381 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 6382 } 6383 6384 /** 6385 * Indicates whether this view reacts to click events or not. 6386 * 6387 * @return true if the view is clickable, false otherwise 6388 * 6389 * @see #setClickable(boolean) 6390 * @attr ref android.R.styleable#View_clickable 6391 */ 6392 @ViewDebug.ExportedProperty 6393 public boolean isClickable() { 6394 return (mViewFlags & CLICKABLE) == CLICKABLE; 6395 } 6396 6397 /** 6398 * Enables or disables click events for this view. When a view 6399 * is clickable it will change its state to "pressed" on every click. 6400 * Subclasses should set the view clickable to visually react to 6401 * user's clicks. 6402 * 6403 * @param clickable true to make the view clickable, false otherwise 6404 * 6405 * @see #isClickable() 6406 * @attr ref android.R.styleable#View_clickable 6407 */ 6408 public void setClickable(boolean clickable) { 6409 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 6410 } 6411 6412 /** 6413 * Indicates whether this view reacts to long click events or not. 6414 * 6415 * @return true if the view is long clickable, false otherwise 6416 * 6417 * @see #setLongClickable(boolean) 6418 * @attr ref android.R.styleable#View_longClickable 6419 */ 6420 public boolean isLongClickable() { 6421 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 6422 } 6423 6424 /** 6425 * Enables or disables long click events for this view. When a view is long 6426 * clickable it reacts to the user holding down the button for a longer 6427 * duration than a tap. This event can either launch the listener or a 6428 * context menu. 6429 * 6430 * @param longClickable true to make the view long clickable, false otherwise 6431 * @see #isLongClickable() 6432 * @attr ref android.R.styleable#View_longClickable 6433 */ 6434 public void setLongClickable(boolean longClickable) { 6435 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 6436 } 6437 6438 /** 6439 * Sets the pressed state for this view. 6440 * 6441 * @see #isClickable() 6442 * @see #setClickable(boolean) 6443 * 6444 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 6445 * the View's internal state from a previously set "pressed" state. 6446 */ 6447 public void setPressed(boolean pressed) { 6448 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 6449 6450 if (pressed) { 6451 mPrivateFlags |= PFLAG_PRESSED; 6452 } else { 6453 mPrivateFlags &= ~PFLAG_PRESSED; 6454 } 6455 6456 if (needsRefresh) { 6457 refreshDrawableState(); 6458 } 6459 dispatchSetPressed(pressed); 6460 } 6461 6462 /** 6463 * Dispatch setPressed to all of this View's children. 6464 * 6465 * @see #setPressed(boolean) 6466 * 6467 * @param pressed The new pressed state 6468 */ 6469 protected void dispatchSetPressed(boolean pressed) { 6470 } 6471 6472 /** 6473 * Indicates whether the view is currently in pressed state. Unless 6474 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 6475 * the pressed state. 6476 * 6477 * @see #setPressed(boolean) 6478 * @see #isClickable() 6479 * @see #setClickable(boolean) 6480 * 6481 * @return true if the view is currently pressed, false otherwise 6482 */ 6483 public boolean isPressed() { 6484 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 6485 } 6486 6487 /** 6488 * Indicates whether this view will save its state (that is, 6489 * whether its {@link #onSaveInstanceState} method will be called). 6490 * 6491 * @return Returns true if the view state saving is enabled, else false. 6492 * 6493 * @see #setSaveEnabled(boolean) 6494 * @attr ref android.R.styleable#View_saveEnabled 6495 */ 6496 public boolean isSaveEnabled() { 6497 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 6498 } 6499 6500 /** 6501 * Controls whether the saving of this view's state is 6502 * enabled (that is, whether its {@link #onSaveInstanceState} method 6503 * will be called). Note that even if freezing is enabled, the 6504 * view still must have an id assigned to it (via {@link #setId(int)}) 6505 * for its state to be saved. This flag can only disable the 6506 * saving of this view; any child views may still have their state saved. 6507 * 6508 * @param enabled Set to false to <em>disable</em> state saving, or true 6509 * (the default) to allow it. 6510 * 6511 * @see #isSaveEnabled() 6512 * @see #setId(int) 6513 * @see #onSaveInstanceState() 6514 * @attr ref android.R.styleable#View_saveEnabled 6515 */ 6516 public void setSaveEnabled(boolean enabled) { 6517 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 6518 } 6519 6520 /** 6521 * Gets whether the framework should discard touches when the view's 6522 * window is obscured by another visible window. 6523 * Refer to the {@link View} security documentation for more details. 6524 * 6525 * @return True if touch filtering is enabled. 6526 * 6527 * @see #setFilterTouchesWhenObscured(boolean) 6528 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 6529 */ 6530 @ViewDebug.ExportedProperty 6531 public boolean getFilterTouchesWhenObscured() { 6532 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 6533 } 6534 6535 /** 6536 * Sets whether the framework should discard touches when the view's 6537 * window is obscured by another visible window. 6538 * Refer to the {@link View} security documentation for more details. 6539 * 6540 * @param enabled True if touch filtering should be enabled. 6541 * 6542 * @see #getFilterTouchesWhenObscured 6543 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 6544 */ 6545 public void setFilterTouchesWhenObscured(boolean enabled) { 6546 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 6547 FILTER_TOUCHES_WHEN_OBSCURED); 6548 } 6549 6550 /** 6551 * Indicates whether the entire hierarchy under this view will save its 6552 * state when a state saving traversal occurs from its parent. The default 6553 * is true; if false, these views will not be saved unless 6554 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 6555 * 6556 * @return Returns true if the view state saving from parent is enabled, else false. 6557 * 6558 * @see #setSaveFromParentEnabled(boolean) 6559 */ 6560 public boolean isSaveFromParentEnabled() { 6561 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 6562 } 6563 6564 /** 6565 * Controls whether the entire hierarchy under this view will save its 6566 * state when a state saving traversal occurs from its parent. The default 6567 * is true; if false, these views will not be saved unless 6568 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 6569 * 6570 * @param enabled Set to false to <em>disable</em> state saving, or true 6571 * (the default) to allow it. 6572 * 6573 * @see #isSaveFromParentEnabled() 6574 * @see #setId(int) 6575 * @see #onSaveInstanceState() 6576 */ 6577 public void setSaveFromParentEnabled(boolean enabled) { 6578 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 6579 } 6580 6581 6582 /** 6583 * Returns whether this View is able to take focus. 6584 * 6585 * @return True if this view can take focus, or false otherwise. 6586 * @attr ref android.R.styleable#View_focusable 6587 */ 6588 @ViewDebug.ExportedProperty(category = "focus") 6589 public final boolean isFocusable() { 6590 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 6591 } 6592 6593 /** 6594 * When a view is focusable, it may not want to take focus when in touch mode. 6595 * For example, a button would like focus when the user is navigating via a D-pad 6596 * so that the user can click on it, but once the user starts touching the screen, 6597 * the button shouldn't take focus 6598 * @return Whether the view is focusable in touch mode. 6599 * @attr ref android.R.styleable#View_focusableInTouchMode 6600 */ 6601 @ViewDebug.ExportedProperty 6602 public final boolean isFocusableInTouchMode() { 6603 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 6604 } 6605 6606 /** 6607 * Find the nearest view in the specified direction that can take focus. 6608 * This does not actually give focus to that view. 6609 * 6610 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 6611 * 6612 * @return The nearest focusable in the specified direction, or null if none 6613 * can be found. 6614 */ 6615 public View focusSearch(int direction) { 6616 if (mParent != null) { 6617 return mParent.focusSearch(this, direction); 6618 } else { 6619 return null; 6620 } 6621 } 6622 6623 /** 6624 * This method is the last chance for the focused view and its ancestors to 6625 * respond to an arrow key. This is called when the focused view did not 6626 * consume the key internally, nor could the view system find a new view in 6627 * the requested direction to give focus to. 6628 * 6629 * @param focused The currently focused view. 6630 * @param direction The direction focus wants to move. One of FOCUS_UP, 6631 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 6632 * @return True if the this view consumed this unhandled move. 6633 */ 6634 public boolean dispatchUnhandledMove(View focused, int direction) { 6635 return false; 6636 } 6637 6638 /** 6639 * If a user manually specified the next view id for a particular direction, 6640 * use the root to look up the view. 6641 * @param root The root view of the hierarchy containing this view. 6642 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 6643 * or FOCUS_BACKWARD. 6644 * @return The user specified next view, or null if there is none. 6645 */ 6646 View findUserSetNextFocus(View root, int direction) { 6647 switch (direction) { 6648 case FOCUS_LEFT: 6649 if (mNextFocusLeftId == View.NO_ID) return null; 6650 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 6651 case FOCUS_RIGHT: 6652 if (mNextFocusRightId == View.NO_ID) return null; 6653 return findViewInsideOutShouldExist(root, mNextFocusRightId); 6654 case FOCUS_UP: 6655 if (mNextFocusUpId == View.NO_ID) return null; 6656 return findViewInsideOutShouldExist(root, mNextFocusUpId); 6657 case FOCUS_DOWN: 6658 if (mNextFocusDownId == View.NO_ID) return null; 6659 return findViewInsideOutShouldExist(root, mNextFocusDownId); 6660 case FOCUS_FORWARD: 6661 if (mNextFocusForwardId == View.NO_ID) return null; 6662 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 6663 case FOCUS_BACKWARD: { 6664 if (mID == View.NO_ID) return null; 6665 final int id = mID; 6666 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 6667 @Override 6668 public boolean apply(View t) { 6669 return t.mNextFocusForwardId == id; 6670 } 6671 }); 6672 } 6673 } 6674 return null; 6675 } 6676 6677 private View findViewInsideOutShouldExist(View root, int id) { 6678 if (mMatchIdPredicate == null) { 6679 mMatchIdPredicate = new MatchIdPredicate(); 6680 } 6681 mMatchIdPredicate.mId = id; 6682 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 6683 if (result == null) { 6684 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 6685 } 6686 return result; 6687 } 6688 6689 /** 6690 * Find and return all focusable views that are descendants of this view, 6691 * possibly including this view if it is focusable itself. 6692 * 6693 * @param direction The direction of the focus 6694 * @return A list of focusable views 6695 */ 6696 public ArrayList<View> getFocusables(int direction) { 6697 ArrayList<View> result = new ArrayList<View>(24); 6698 addFocusables(result, direction); 6699 return result; 6700 } 6701 6702 /** 6703 * Add any focusable views that are descendants of this view (possibly 6704 * including this view if it is focusable itself) to views. If we are in touch mode, 6705 * only add views that are also focusable in touch mode. 6706 * 6707 * @param views Focusable views found so far 6708 * @param direction The direction of the focus 6709 */ 6710 public void addFocusables(ArrayList<View> views, int direction) { 6711 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); 6712 } 6713 6714 /** 6715 * Adds any focusable views that are descendants of this view (possibly 6716 * including this view if it is focusable itself) to views. This method 6717 * adds all focusable views regardless if we are in touch mode or 6718 * only views focusable in touch mode if we are in touch mode or 6719 * only views that can take accessibility focus if accessibility is enabeld 6720 * depending on the focusable mode paramater. 6721 * 6722 * @param views Focusable views found so far or null if all we are interested is 6723 * the number of focusables. 6724 * @param direction The direction of the focus. 6725 * @param focusableMode The type of focusables to be added. 6726 * 6727 * @see #FOCUSABLES_ALL 6728 * @see #FOCUSABLES_TOUCH_MODE 6729 */ 6730 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { 6731 if (views == null) { 6732 return; 6733 } 6734 if (!isFocusable()) { 6735 return; 6736 } 6737 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 6738 && isInTouchMode() && !isFocusableInTouchMode()) { 6739 return; 6740 } 6741 views.add(this); 6742 } 6743 6744 /** 6745 * Finds the Views that contain given text. The containment is case insensitive. 6746 * The search is performed by either the text that the View renders or the content 6747 * description that describes the view for accessibility purposes and the view does 6748 * not render or both. Clients can specify how the search is to be performed via 6749 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 6750 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 6751 * 6752 * @param outViews The output list of matching Views. 6753 * @param searched The text to match against. 6754 * 6755 * @see #FIND_VIEWS_WITH_TEXT 6756 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 6757 * @see #setContentDescription(CharSequence) 6758 */ 6759 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) { 6760 if (getAccessibilityNodeProvider() != null) { 6761 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 6762 outViews.add(this); 6763 } 6764 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 6765 && (searched != null && searched.length() > 0) 6766 && (mContentDescription != null && mContentDescription.length() > 0)) { 6767 String searchedLowerCase = searched.toString().toLowerCase(); 6768 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 6769 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 6770 outViews.add(this); 6771 } 6772 } 6773 } 6774 6775 /** 6776 * Find and return all touchable views that are descendants of this view, 6777 * possibly including this view if it is touchable itself. 6778 * 6779 * @return A list of touchable views 6780 */ 6781 public ArrayList<View> getTouchables() { 6782 ArrayList<View> result = new ArrayList<View>(); 6783 addTouchables(result); 6784 return result; 6785 } 6786 6787 /** 6788 * Add any touchable views that are descendants of this view (possibly 6789 * including this view if it is touchable itself) to views. 6790 * 6791 * @param views Touchable views found so far 6792 */ 6793 public void addTouchables(ArrayList<View> views) { 6794 final int viewFlags = mViewFlags; 6795 6796 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 6797 && (viewFlags & ENABLED_MASK) == ENABLED) { 6798 views.add(this); 6799 } 6800 } 6801 6802 /** 6803 * Returns whether this View is accessibility focused. 6804 * 6805 * @return True if this View is accessibility focused. 6806 * @hide 6807 */ 6808 public boolean isAccessibilityFocused() { 6809 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 6810 } 6811 6812 /** 6813 * Call this to try to give accessibility focus to this view. 6814 * 6815 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 6816 * returns false or the view is no visible or the view already has accessibility 6817 * focus. 6818 * 6819 * See also {@link #focusSearch(int)}, which is what you call to say that you 6820 * have focus, and you want your parent to look for the next one. 6821 * 6822 * @return Whether this view actually took accessibility focus. 6823 * 6824 * @hide 6825 */ 6826 public boolean requestAccessibilityFocus() { 6827 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 6828 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 6829 return false; 6830 } 6831 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 6832 return false; 6833 } 6834 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 6835 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 6836 ViewRootImpl viewRootImpl = getViewRootImpl(); 6837 if (viewRootImpl != null) { 6838 viewRootImpl.setAccessibilityFocus(this, null); 6839 } 6840 invalidate(); 6841 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 6842 return true; 6843 } 6844 return false; 6845 } 6846 6847 /** 6848 * Call this to try to clear accessibility focus of this view. 6849 * 6850 * See also {@link #focusSearch(int)}, which is what you call to say that you 6851 * have focus, and you want your parent to look for the next one. 6852 * 6853 * @hide 6854 */ 6855 public void clearAccessibilityFocus() { 6856 clearAccessibilityFocusNoCallbacks(); 6857 // Clear the global reference of accessibility focus if this 6858 // view or any of its descendants had accessibility focus. 6859 ViewRootImpl viewRootImpl = getViewRootImpl(); 6860 if (viewRootImpl != null) { 6861 View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 6862 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 6863 viewRootImpl.setAccessibilityFocus(null, null); 6864 } 6865 } 6866 } 6867 6868 private void sendAccessibilityHoverEvent(int eventType) { 6869 // Since we are not delivering to a client accessibility events from not 6870 // important views (unless the clinet request that) we need to fire the 6871 // event from the deepest view exposed to the client. As a consequence if 6872 // the user crosses a not exposed view the client will see enter and exit 6873 // of the exposed predecessor followed by and enter and exit of that same 6874 // predecessor when entering and exiting the not exposed descendant. This 6875 // is fine since the client has a clear idea which view is hovered at the 6876 // price of a couple more events being sent. This is a simple and 6877 // working solution. 6878 View source = this; 6879 while (true) { 6880 if (source.includeForAccessibility()) { 6881 source.sendAccessibilityEvent(eventType); 6882 return; 6883 } 6884 ViewParent parent = source.getParent(); 6885 if (parent instanceof View) { 6886 source = (View) parent; 6887 } else { 6888 return; 6889 } 6890 } 6891 } 6892 6893 /** 6894 * Clears accessibility focus without calling any callback methods 6895 * normally invoked in {@link #clearAccessibilityFocus()}. This method 6896 * is used for clearing accessibility focus when giving this focus to 6897 * another view. 6898 */ 6899 void clearAccessibilityFocusNoCallbacks() { 6900 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 6901 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 6902 invalidate(); 6903 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 6904 } 6905 } 6906 6907 /** 6908 * Call this to try to give focus to a specific view or to one of its 6909 * descendants. 6910 * 6911 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 6912 * false), or if it is focusable and it is not focusable in touch mode 6913 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 6914 * 6915 * See also {@link #focusSearch(int)}, which is what you call to say that you 6916 * have focus, and you want your parent to look for the next one. 6917 * 6918 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 6919 * {@link #FOCUS_DOWN} and <code>null</code>. 6920 * 6921 * @return Whether this view or one of its descendants actually took focus. 6922 */ 6923 public final boolean requestFocus() { 6924 return requestFocus(View.FOCUS_DOWN); 6925 } 6926 6927 /** 6928 * Call this to try to give focus to a specific view or to one of its 6929 * descendants and give it a hint about what direction focus is heading. 6930 * 6931 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 6932 * false), or if it is focusable and it is not focusable in touch mode 6933 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 6934 * 6935 * See also {@link #focusSearch(int)}, which is what you call to say that you 6936 * have focus, and you want your parent to look for the next one. 6937 * 6938 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 6939 * <code>null</code> set for the previously focused rectangle. 6940 * 6941 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 6942 * @return Whether this view or one of its descendants actually took focus. 6943 */ 6944 public final boolean requestFocus(int direction) { 6945 return requestFocus(direction, null); 6946 } 6947 6948 /** 6949 * Call this to try to give focus to a specific view or to one of its descendants 6950 * and give it hints about the direction and a specific rectangle that the focus 6951 * is coming from. The rectangle can help give larger views a finer grained hint 6952 * about where focus is coming from, and therefore, where to show selection, or 6953 * forward focus change internally. 6954 * 6955 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 6956 * false), or if it is focusable and it is not focusable in touch mode 6957 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 6958 * 6959 * A View will not take focus if it is not visible. 6960 * 6961 * A View will not take focus if one of its parents has 6962 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 6963 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 6964 * 6965 * See also {@link #focusSearch(int)}, which is what you call to say that you 6966 * have focus, and you want your parent to look for the next one. 6967 * 6968 * You may wish to override this method if your custom {@link View} has an internal 6969 * {@link View} that it wishes to forward the request to. 6970 * 6971 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 6972 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 6973 * to give a finer grained hint about where focus is coming from. May be null 6974 * if there is no hint. 6975 * @return Whether this view or one of its descendants actually took focus. 6976 */ 6977 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 6978 return requestFocusNoSearch(direction, previouslyFocusedRect); 6979 } 6980 6981 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 6982 // need to be focusable 6983 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 6984 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 6985 return false; 6986 } 6987 6988 // need to be focusable in touch mode if in touch mode 6989 if (isInTouchMode() && 6990 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 6991 return false; 6992 } 6993 6994 // need to not have any parents blocking us 6995 if (hasAncestorThatBlocksDescendantFocus()) { 6996 return false; 6997 } 6998 6999 handleFocusGainInternal(direction, previouslyFocusedRect); 7000 return true; 7001 } 7002 7003 /** 7004 * Call this to try to give focus to a specific view or to one of its descendants. This is a 7005 * special variant of {@link #requestFocus() } that will allow views that are not focuable in 7006 * touch mode to request focus when they are touched. 7007 * 7008 * @return Whether this view or one of its descendants actually took focus. 7009 * 7010 * @see #isInTouchMode() 7011 * 7012 */ 7013 public final boolean requestFocusFromTouch() { 7014 // Leave touch mode if we need to 7015 if (isInTouchMode()) { 7016 ViewRootImpl viewRoot = getViewRootImpl(); 7017 if (viewRoot != null) { 7018 viewRoot.ensureTouchMode(false); 7019 } 7020 } 7021 return requestFocus(View.FOCUS_DOWN); 7022 } 7023 7024 /** 7025 * @return Whether any ancestor of this view blocks descendant focus. 7026 */ 7027 private boolean hasAncestorThatBlocksDescendantFocus() { 7028 ViewParent ancestor = mParent; 7029 while (ancestor instanceof ViewGroup) { 7030 final ViewGroup vgAncestor = (ViewGroup) ancestor; 7031 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { 7032 return true; 7033 } else { 7034 ancestor = vgAncestor.getParent(); 7035 } 7036 } 7037 return false; 7038 } 7039 7040 /** 7041 * Gets the mode for determining whether this View is important for accessibility 7042 * which is if it fires accessibility events and if it is reported to 7043 * accessibility services that query the screen. 7044 * 7045 * @return The mode for determining whether a View is important for accessibility. 7046 * 7047 * @attr ref android.R.styleable#View_importantForAccessibility 7048 * 7049 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 7050 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 7051 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 7052 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 7053 */ 7054 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 7055 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 7056 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 7057 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 7058 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 7059 to = "noHideDescendants") 7060 }) 7061 public int getImportantForAccessibility() { 7062 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 7063 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 7064 } 7065 7066 /** 7067 * Sets the live region mode for this view. This indicates to accessibility 7068 * services whether they should automatically notify the user about changes 7069 * to the view's content description or text, or to the content descriptions 7070 * or text of the view's children (where applicable). 7071 * <p> 7072 * For example, in a login screen with a TextView that displays an "incorrect 7073 * password" notification, that view should be marked as a live region with 7074 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 7075 * <p> 7076 * To disable change notifications for this view, use 7077 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 7078 * mode for most views. 7079 * <p> 7080 * To indicate that the user should be notified of changes, use 7081 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 7082 * <p> 7083 * If the view's changes should interrupt ongoing speech and notify the user 7084 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 7085 * 7086 * @param mode The live region mode for this view, one of: 7087 * <ul> 7088 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 7089 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 7090 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 7091 * </ul> 7092 * @attr ref android.R.styleable#View_accessibilityLiveRegion 7093 */ 7094 public void setAccessibilityLiveRegion(int mode) { 7095 if (mode != getAccessibilityLiveRegion()) { 7096 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 7097 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 7098 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 7099 notifyViewAccessibilityStateChangedIfNeeded( 7100 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7101 } 7102 } 7103 7104 /** 7105 * Gets the live region mode for this View. 7106 * 7107 * @return The live region mode for the view. 7108 * 7109 * @attr ref android.R.styleable#View_accessibilityLiveRegion 7110 * 7111 * @see #setAccessibilityLiveRegion(int) 7112 */ 7113 public int getAccessibilityLiveRegion() { 7114 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 7115 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 7116 } 7117 7118 /** 7119 * Sets how to determine whether this view is important for accessibility 7120 * which is if it fires accessibility events and if it is reported to 7121 * accessibility services that query the screen. 7122 * 7123 * @param mode How to determine whether this view is important for accessibility. 7124 * 7125 * @attr ref android.R.styleable#View_importantForAccessibility 7126 * 7127 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 7128 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 7129 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 7130 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 7131 */ 7132 public void setImportantForAccessibility(int mode) { 7133 final int oldMode = getImportantForAccessibility(); 7134 if (mode != oldMode) { 7135 // If we're moving between AUTO and another state, we might not need 7136 // to send a subtree changed notification. We'll store the computed 7137 // importance, since we'll need to check it later to make sure. 7138 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 7139 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 7140 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 7141 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 7142 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 7143 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 7144 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 7145 notifySubtreeAccessibilityStateChangedIfNeeded(); 7146 } else { 7147 notifyViewAccessibilityStateChangedIfNeeded( 7148 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7149 } 7150 } 7151 } 7152 7153 /** 7154 * Gets whether this view should be exposed for accessibility. 7155 * 7156 * @return Whether the view is exposed for accessibility. 7157 * 7158 * @hide 7159 */ 7160 public boolean isImportantForAccessibility() { 7161 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 7162 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 7163 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 7164 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 7165 return false; 7166 } 7167 7168 // Check parent mode to ensure we're not hidden. 7169 ViewParent parent = mParent; 7170 while (parent instanceof View) { 7171 if (((View) parent).getImportantForAccessibility() 7172 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 7173 return false; 7174 } 7175 parent = parent.getParent(); 7176 } 7177 7178 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 7179 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 7180 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE; 7181 } 7182 7183 /** 7184 * Gets the parent for accessibility purposes. Note that the parent for 7185 * accessibility is not necessary the immediate parent. It is the first 7186 * predecessor that is important for accessibility. 7187 * 7188 * @return The parent for accessibility purposes. 7189 */ 7190 public ViewParent getParentForAccessibility() { 7191 if (mParent instanceof View) { 7192 View parentView = (View) mParent; 7193 if (parentView.includeForAccessibility()) { 7194 return mParent; 7195 } else { 7196 return mParent.getParentForAccessibility(); 7197 } 7198 } 7199 return null; 7200 } 7201 7202 /** 7203 * Adds the children of a given View for accessibility. Since some Views are 7204 * not important for accessibility the children for accessibility are not 7205 * necessarily direct children of the view, rather they are the first level of 7206 * descendants important for accessibility. 7207 * 7208 * @param children The list of children for accessibility. 7209 */ 7210 public void addChildrenForAccessibility(ArrayList<View> children) { 7211 if (includeForAccessibility()) { 7212 children.add(this); 7213 } 7214 } 7215 7216 /** 7217 * Whether to regard this view for accessibility. A view is regarded for 7218 * accessibility if it is important for accessibility or the querying 7219 * accessibility service has explicitly requested that view not 7220 * important for accessibility are regarded. 7221 * 7222 * @return Whether to regard the view for accessibility. 7223 * 7224 * @hide 7225 */ 7226 public boolean includeForAccessibility() { 7227 //noinspection SimplifiableIfStatement 7228 if (mAttachInfo != null) { 7229 return (mAttachInfo.mAccessibilityFetchFlags 7230 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 7231 || isImportantForAccessibility(); 7232 } 7233 return false; 7234 } 7235 7236 /** 7237 * Returns whether the View is considered actionable from 7238 * accessibility perspective. Such view are important for 7239 * accessibility. 7240 * 7241 * @return True if the view is actionable for accessibility. 7242 * 7243 * @hide 7244 */ 7245 public boolean isActionableForAccessibility() { 7246 return (isClickable() || isLongClickable() || isFocusable()); 7247 } 7248 7249 /** 7250 * Returns whether the View has registered callbacks wich makes it 7251 * important for accessibility. 7252 * 7253 * @return True if the view is actionable for accessibility. 7254 */ 7255 private boolean hasListenersForAccessibility() { 7256 ListenerInfo info = getListenerInfo(); 7257 return mTouchDelegate != null || info.mOnKeyListener != null 7258 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 7259 || info.mOnHoverListener != null || info.mOnDragListener != null; 7260 } 7261 7262 /** 7263 * Notifies that the accessibility state of this view changed. The change 7264 * is local to this view and does not represent structural changes such 7265 * as children and parent. For example, the view became focusable. The 7266 * notification is at at most once every 7267 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 7268 * to avoid unnecessary load to the system. Also once a view has a pending 7269 * notifucation this method is a NOP until the notification has been sent. 7270 * 7271 * @hide 7272 */ 7273 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 7274 if (!AccessibilityManager.getInstance(mContext).isEnabled()) { 7275 return; 7276 } 7277 if (mSendViewStateChangedAccessibilityEvent == null) { 7278 mSendViewStateChangedAccessibilityEvent = 7279 new SendViewStateChangedAccessibilityEvent(); 7280 } 7281 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType); 7282 } 7283 7284 /** 7285 * Notifies that the accessibility state of this view changed. The change 7286 * is *not* local to this view and does represent structural changes such 7287 * as children and parent. For example, the view size changed. The 7288 * notification is at at most once every 7289 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 7290 * to avoid unnecessary load to the system. Also once a view has a pending 7291 * notifucation this method is a NOP until the notification has been sent. 7292 * 7293 * @hide 7294 */ 7295 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 7296 if (!AccessibilityManager.getInstance(mContext).isEnabled()) { 7297 return; 7298 } 7299 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 7300 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 7301 if (mParent != null) { 7302 try { 7303 mParent.notifySubtreeAccessibilityStateChanged( 7304 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 7305 } catch (AbstractMethodError e) { 7306 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 7307 " does not fully implement ViewParent", e); 7308 } 7309 } 7310 } 7311 } 7312 7313 /** 7314 * Reset the flag indicating the accessibility state of the subtree rooted 7315 * at this view changed. 7316 */ 7317 void resetSubtreeAccessibilityStateChanged() { 7318 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 7319 } 7320 7321 /** 7322 * Performs the specified accessibility action on the view. For 7323 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 7324 * <p> 7325 * If an {@link AccessibilityDelegate} has been specified via calling 7326 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7327 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 7328 * is responsible for handling this call. 7329 * </p> 7330 * 7331 * @param action The action to perform. 7332 * @param arguments Optional action arguments. 7333 * @return Whether the action was performed. 7334 */ 7335 public boolean performAccessibilityAction(int action, Bundle arguments) { 7336 if (mAccessibilityDelegate != null) { 7337 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 7338 } else { 7339 return performAccessibilityActionInternal(action, arguments); 7340 } 7341 } 7342 7343 /** 7344 * @see #performAccessibilityAction(int, Bundle) 7345 * 7346 * Note: Called from the default {@link AccessibilityDelegate}. 7347 */ 7348 boolean performAccessibilityActionInternal(int action, Bundle arguments) { 7349 switch (action) { 7350 case AccessibilityNodeInfo.ACTION_CLICK: { 7351 if (isClickable()) { 7352 performClick(); 7353 return true; 7354 } 7355 } break; 7356 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 7357 if (isLongClickable()) { 7358 performLongClick(); 7359 return true; 7360 } 7361 } break; 7362 case AccessibilityNodeInfo.ACTION_FOCUS: { 7363 if (!hasFocus()) { 7364 // Get out of touch mode since accessibility 7365 // wants to move focus around. 7366 getViewRootImpl().ensureTouchMode(false); 7367 return requestFocus(); 7368 } 7369 } break; 7370 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 7371 if (hasFocus()) { 7372 clearFocus(); 7373 return !isFocused(); 7374 } 7375 } break; 7376 case AccessibilityNodeInfo.ACTION_SELECT: { 7377 if (!isSelected()) { 7378 setSelected(true); 7379 return isSelected(); 7380 } 7381 } break; 7382 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 7383 if (isSelected()) { 7384 setSelected(false); 7385 return !isSelected(); 7386 } 7387 } break; 7388 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 7389 if (!isAccessibilityFocused()) { 7390 return requestAccessibilityFocus(); 7391 } 7392 } break; 7393 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 7394 if (isAccessibilityFocused()) { 7395 clearAccessibilityFocus(); 7396 return true; 7397 } 7398 } break; 7399 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 7400 if (arguments != null) { 7401 final int granularity = arguments.getInt( 7402 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 7403 final boolean extendSelection = arguments.getBoolean( 7404 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 7405 return traverseAtGranularity(granularity, true, extendSelection); 7406 } 7407 } break; 7408 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 7409 if (arguments != null) { 7410 final int granularity = arguments.getInt( 7411 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 7412 final boolean extendSelection = arguments.getBoolean( 7413 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 7414 return traverseAtGranularity(granularity, false, extendSelection); 7415 } 7416 } break; 7417 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 7418 CharSequence text = getIterableTextForAccessibility(); 7419 if (text == null) { 7420 return false; 7421 } 7422 final int start = (arguments != null) ? arguments.getInt( 7423 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 7424 final int end = (arguments != null) ? arguments.getInt( 7425 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 7426 // Only cursor position can be specified (selection length == 0) 7427 if ((getAccessibilitySelectionStart() != start 7428 || getAccessibilitySelectionEnd() != end) 7429 && (start == end)) { 7430 setAccessibilitySelection(start, end); 7431 notifyViewAccessibilityStateChangedIfNeeded( 7432 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7433 return true; 7434 } 7435 } break; 7436 } 7437 return false; 7438 } 7439 7440 private boolean traverseAtGranularity(int granularity, boolean forward, 7441 boolean extendSelection) { 7442 CharSequence text = getIterableTextForAccessibility(); 7443 if (text == null || text.length() == 0) { 7444 return false; 7445 } 7446 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 7447 if (iterator == null) { 7448 return false; 7449 } 7450 int current = getAccessibilitySelectionEnd(); 7451 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 7452 current = forward ? 0 : text.length(); 7453 } 7454 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 7455 if (range == null) { 7456 return false; 7457 } 7458 final int segmentStart = range[0]; 7459 final int segmentEnd = range[1]; 7460 int selectionStart; 7461 int selectionEnd; 7462 if (extendSelection && isAccessibilitySelectionExtendable()) { 7463 selectionStart = getAccessibilitySelectionStart(); 7464 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 7465 selectionStart = forward ? segmentStart : segmentEnd; 7466 } 7467 selectionEnd = forward ? segmentEnd : segmentStart; 7468 } else { 7469 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 7470 } 7471 setAccessibilitySelection(selectionStart, selectionEnd); 7472 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 7473 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 7474 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 7475 return true; 7476 } 7477 7478 /** 7479 * Gets the text reported for accessibility purposes. 7480 * 7481 * @return The accessibility text. 7482 * 7483 * @hide 7484 */ 7485 public CharSequence getIterableTextForAccessibility() { 7486 return getContentDescription(); 7487 } 7488 7489 /** 7490 * Gets whether accessibility selection can be extended. 7491 * 7492 * @return If selection is extensible. 7493 * 7494 * @hide 7495 */ 7496 public boolean isAccessibilitySelectionExtendable() { 7497 return false; 7498 } 7499 7500 /** 7501 * @hide 7502 */ 7503 public int getAccessibilitySelectionStart() { 7504 return mAccessibilityCursorPosition; 7505 } 7506 7507 /** 7508 * @hide 7509 */ 7510 public int getAccessibilitySelectionEnd() { 7511 return getAccessibilitySelectionStart(); 7512 } 7513 7514 /** 7515 * @hide 7516 */ 7517 public void setAccessibilitySelection(int start, int end) { 7518 if (start == end && end == mAccessibilityCursorPosition) { 7519 return; 7520 } 7521 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 7522 mAccessibilityCursorPosition = start; 7523 } else { 7524 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 7525 } 7526 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 7527 } 7528 7529 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 7530 int fromIndex, int toIndex) { 7531 if (mParent == null) { 7532 return; 7533 } 7534 AccessibilityEvent event = AccessibilityEvent.obtain( 7535 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 7536 onInitializeAccessibilityEvent(event); 7537 onPopulateAccessibilityEvent(event); 7538 event.setFromIndex(fromIndex); 7539 event.setToIndex(toIndex); 7540 event.setAction(action); 7541 event.setMovementGranularity(granularity); 7542 mParent.requestSendAccessibilityEvent(this, event); 7543 } 7544 7545 /** 7546 * @hide 7547 */ 7548 public TextSegmentIterator getIteratorForGranularity(int granularity) { 7549 switch (granularity) { 7550 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 7551 CharSequence text = getIterableTextForAccessibility(); 7552 if (text != null && text.length() > 0) { 7553 CharacterTextSegmentIterator iterator = 7554 CharacterTextSegmentIterator.getInstance( 7555 mContext.getResources().getConfiguration().locale); 7556 iterator.initialize(text.toString()); 7557 return iterator; 7558 } 7559 } break; 7560 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 7561 CharSequence text = getIterableTextForAccessibility(); 7562 if (text != null && text.length() > 0) { 7563 WordTextSegmentIterator iterator = 7564 WordTextSegmentIterator.getInstance( 7565 mContext.getResources().getConfiguration().locale); 7566 iterator.initialize(text.toString()); 7567 return iterator; 7568 } 7569 } break; 7570 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 7571 CharSequence text = getIterableTextForAccessibility(); 7572 if (text != null && text.length() > 0) { 7573 ParagraphTextSegmentIterator iterator = 7574 ParagraphTextSegmentIterator.getInstance(); 7575 iterator.initialize(text.toString()); 7576 return iterator; 7577 } 7578 } break; 7579 } 7580 return null; 7581 } 7582 7583 /** 7584 * @hide 7585 */ 7586 public void dispatchStartTemporaryDetach() { 7587 clearDisplayList(); 7588 7589 onStartTemporaryDetach(); 7590 } 7591 7592 /** 7593 * This is called when a container is going to temporarily detach a child, with 7594 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 7595 * It will either be followed by {@link #onFinishTemporaryDetach()} or 7596 * {@link #onDetachedFromWindow()} when the container is done. 7597 */ 7598 public void onStartTemporaryDetach() { 7599 removeUnsetPressCallback(); 7600 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 7601 } 7602 7603 /** 7604 * @hide 7605 */ 7606 public void dispatchFinishTemporaryDetach() { 7607 onFinishTemporaryDetach(); 7608 } 7609 7610 /** 7611 * Called after {@link #onStartTemporaryDetach} when the container is done 7612 * changing the view. 7613 */ 7614 public void onFinishTemporaryDetach() { 7615 } 7616 7617 /** 7618 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 7619 * for this view's window. Returns null if the view is not currently attached 7620 * to the window. Normally you will not need to use this directly, but 7621 * just use the standard high-level event callbacks like 7622 * {@link #onKeyDown(int, KeyEvent)}. 7623 */ 7624 public KeyEvent.DispatcherState getKeyDispatcherState() { 7625 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 7626 } 7627 7628 /** 7629 * Dispatch a key event before it is processed by any input method 7630 * associated with the view hierarchy. This can be used to intercept 7631 * key events in special situations before the IME consumes them; a 7632 * typical example would be handling the BACK key to update the application's 7633 * UI instead of allowing the IME to see it and close itself. 7634 * 7635 * @param event The key event to be dispatched. 7636 * @return True if the event was handled, false otherwise. 7637 */ 7638 public boolean dispatchKeyEventPreIme(KeyEvent event) { 7639 return onKeyPreIme(event.getKeyCode(), event); 7640 } 7641 7642 /** 7643 * Dispatch a key event to the next view on the focus path. This path runs 7644 * from the top of the view tree down to the currently focused view. If this 7645 * view has focus, it will dispatch to itself. Otherwise it will dispatch 7646 * the next node down the focus path. This method also fires any key 7647 * listeners. 7648 * 7649 * @param event The key event to be dispatched. 7650 * @return True if the event was handled, false otherwise. 7651 */ 7652 public boolean dispatchKeyEvent(KeyEvent event) { 7653 if (mInputEventConsistencyVerifier != null) { 7654 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 7655 } 7656 7657 // Give any attached key listener a first crack at the event. 7658 //noinspection SimplifiableIfStatement 7659 ListenerInfo li = mListenerInfo; 7660 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 7661 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 7662 return true; 7663 } 7664 7665 if (event.dispatch(this, mAttachInfo != null 7666 ? mAttachInfo.mKeyDispatchState : null, this)) { 7667 return true; 7668 } 7669 7670 if (mInputEventConsistencyVerifier != null) { 7671 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 7672 } 7673 return false; 7674 } 7675 7676 /** 7677 * Dispatches a key shortcut event. 7678 * 7679 * @param event The key event to be dispatched. 7680 * @return True if the event was handled by the view, false otherwise. 7681 */ 7682 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7683 return onKeyShortcut(event.getKeyCode(), event); 7684 } 7685 7686 /** 7687 * Pass the touch screen motion event down to the target view, or this 7688 * view if it is the target. 7689 * 7690 * @param event The motion event to be dispatched. 7691 * @return True if the event was handled by the view, false otherwise. 7692 */ 7693 public boolean dispatchTouchEvent(MotionEvent event) { 7694 if (mInputEventConsistencyVerifier != null) { 7695 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 7696 } 7697 7698 if (onFilterTouchEventForSecurity(event)) { 7699 //noinspection SimplifiableIfStatement 7700 ListenerInfo li = mListenerInfo; 7701 if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 7702 && li.mOnTouchListener.onTouch(this, event)) { 7703 return true; 7704 } 7705 7706 if (onTouchEvent(event)) { 7707 return true; 7708 } 7709 } 7710 7711 if (mInputEventConsistencyVerifier != null) { 7712 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 7713 } 7714 return false; 7715 } 7716 7717 /** 7718 * Filter the touch event to apply security policies. 7719 * 7720 * @param event The motion event to be filtered. 7721 * @return True if the event should be dispatched, false if the event should be dropped. 7722 * 7723 * @see #getFilterTouchesWhenObscured 7724 */ 7725 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 7726 //noinspection RedundantIfStatement 7727 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 7728 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 7729 // Window is obscured, drop this touch. 7730 return false; 7731 } 7732 return true; 7733 } 7734 7735 /** 7736 * Pass a trackball motion event down to the focused view. 7737 * 7738 * @param event The motion event to be dispatched. 7739 * @return True if the event was handled by the view, false otherwise. 7740 */ 7741 public boolean dispatchTrackballEvent(MotionEvent event) { 7742 if (mInputEventConsistencyVerifier != null) { 7743 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 7744 } 7745 7746 return onTrackballEvent(event); 7747 } 7748 7749 /** 7750 * Dispatch a generic motion event. 7751 * <p> 7752 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 7753 * are delivered to the view under the pointer. All other generic motion events are 7754 * delivered to the focused view. Hover events are handled specially and are delivered 7755 * to {@link #onHoverEvent(MotionEvent)}. 7756 * </p> 7757 * 7758 * @param event The motion event to be dispatched. 7759 * @return True if the event was handled by the view, false otherwise. 7760 */ 7761 public boolean dispatchGenericMotionEvent(MotionEvent event) { 7762 if (mInputEventConsistencyVerifier != null) { 7763 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 7764 } 7765 7766 final int source = event.getSource(); 7767 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 7768 final int action = event.getAction(); 7769 if (action == MotionEvent.ACTION_HOVER_ENTER 7770 || action == MotionEvent.ACTION_HOVER_MOVE 7771 || action == MotionEvent.ACTION_HOVER_EXIT) { 7772 if (dispatchHoverEvent(event)) { 7773 return true; 7774 } 7775 } else if (dispatchGenericPointerEvent(event)) { 7776 return true; 7777 } 7778 } else if (dispatchGenericFocusedEvent(event)) { 7779 return true; 7780 } 7781 7782 if (dispatchGenericMotionEventInternal(event)) { 7783 return true; 7784 } 7785 7786 if (mInputEventConsistencyVerifier != null) { 7787 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 7788 } 7789 return false; 7790 } 7791 7792 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 7793 //noinspection SimplifiableIfStatement 7794 ListenerInfo li = mListenerInfo; 7795 if (li != null && li.mOnGenericMotionListener != null 7796 && (mViewFlags & ENABLED_MASK) == ENABLED 7797 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 7798 return true; 7799 } 7800 7801 if (onGenericMotionEvent(event)) { 7802 return true; 7803 } 7804 7805 if (mInputEventConsistencyVerifier != null) { 7806 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 7807 } 7808 return false; 7809 } 7810 7811 /** 7812 * Dispatch a hover event. 7813 * <p> 7814 * Do not call this method directly. 7815 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 7816 * </p> 7817 * 7818 * @param event The motion event to be dispatched. 7819 * @return True if the event was handled by the view, false otherwise. 7820 */ 7821 protected boolean dispatchHoverEvent(MotionEvent event) { 7822 ListenerInfo li = mListenerInfo; 7823 //noinspection SimplifiableIfStatement 7824 if (li != null && li.mOnHoverListener != null 7825 && (mViewFlags & ENABLED_MASK) == ENABLED 7826 && li.mOnHoverListener.onHover(this, event)) { 7827 return true; 7828 } 7829 7830 return onHoverEvent(event); 7831 } 7832 7833 /** 7834 * Returns true if the view has a child to which it has recently sent 7835 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 7836 * it does not have a hovered child, then it must be the innermost hovered view. 7837 * @hide 7838 */ 7839 protected boolean hasHoveredChild() { 7840 return false; 7841 } 7842 7843 /** 7844 * Dispatch a generic motion event to the view under the first pointer. 7845 * <p> 7846 * Do not call this method directly. 7847 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 7848 * </p> 7849 * 7850 * @param event The motion event to be dispatched. 7851 * @return True if the event was handled by the view, false otherwise. 7852 */ 7853 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 7854 return false; 7855 } 7856 7857 /** 7858 * Dispatch a generic motion event to the currently focused view. 7859 * <p> 7860 * Do not call this method directly. 7861 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 7862 * </p> 7863 * 7864 * @param event The motion event to be dispatched. 7865 * @return True if the event was handled by the view, false otherwise. 7866 */ 7867 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 7868 return false; 7869 } 7870 7871 /** 7872 * Dispatch a pointer event. 7873 * <p> 7874 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 7875 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 7876 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 7877 * and should not be expected to handle other pointing device features. 7878 * </p> 7879 * 7880 * @param event The motion event to be dispatched. 7881 * @return True if the event was handled by the view, false otherwise. 7882 * @hide 7883 */ 7884 public final boolean dispatchPointerEvent(MotionEvent event) { 7885 if (event.isTouchEvent()) { 7886 return dispatchTouchEvent(event); 7887 } else { 7888 return dispatchGenericMotionEvent(event); 7889 } 7890 } 7891 7892 /** 7893 * Called when the window containing this view gains or loses window focus. 7894 * ViewGroups should override to route to their children. 7895 * 7896 * @param hasFocus True if the window containing this view now has focus, 7897 * false otherwise. 7898 */ 7899 public void dispatchWindowFocusChanged(boolean hasFocus) { 7900 onWindowFocusChanged(hasFocus); 7901 } 7902 7903 /** 7904 * Called when the window containing this view gains or loses focus. Note 7905 * that this is separate from view focus: to receive key events, both 7906 * your view and its window must have focus. If a window is displayed 7907 * on top of yours that takes input focus, then your own window will lose 7908 * focus but the view focus will remain unchanged. 7909 * 7910 * @param hasWindowFocus True if the window containing this view now has 7911 * focus, false otherwise. 7912 */ 7913 public void onWindowFocusChanged(boolean hasWindowFocus) { 7914 InputMethodManager imm = InputMethodManager.peekInstance(); 7915 if (!hasWindowFocus) { 7916 if (isPressed()) { 7917 setPressed(false); 7918 } 7919 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 7920 imm.focusOut(this); 7921 } 7922 removeLongPressCallback(); 7923 removeTapCallback(); 7924 onFocusLost(); 7925 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 7926 imm.focusIn(this); 7927 } 7928 refreshDrawableState(); 7929 } 7930 7931 /** 7932 * Returns true if this view is in a window that currently has window focus. 7933 * Note that this is not the same as the view itself having focus. 7934 * 7935 * @return True if this view is in a window that currently has window focus. 7936 */ 7937 public boolean hasWindowFocus() { 7938 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 7939 } 7940 7941 /** 7942 * Dispatch a view visibility change down the view hierarchy. 7943 * ViewGroups should override to route to their children. 7944 * @param changedView The view whose visibility changed. Could be 'this' or 7945 * an ancestor view. 7946 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 7947 * {@link #INVISIBLE} or {@link #GONE}. 7948 */ 7949 protected void dispatchVisibilityChanged(View changedView, int visibility) { 7950 onVisibilityChanged(changedView, visibility); 7951 } 7952 7953 /** 7954 * Called when the visibility of the view or an ancestor of the view is changed. 7955 * @param changedView The view whose visibility changed. Could be 'this' or 7956 * an ancestor view. 7957 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 7958 * {@link #INVISIBLE} or {@link #GONE}. 7959 */ 7960 protected void onVisibilityChanged(View changedView, int visibility) { 7961 if (visibility == VISIBLE) { 7962 if (mAttachInfo != null) { 7963 initialAwakenScrollBars(); 7964 } else { 7965 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH; 7966 } 7967 } 7968 } 7969 7970 /** 7971 * Dispatch a hint about whether this view is displayed. For instance, when 7972 * a View moves out of the screen, it might receives a display hint indicating 7973 * the view is not displayed. Applications should not <em>rely</em> on this hint 7974 * as there is no guarantee that they will receive one. 7975 * 7976 * @param hint A hint about whether or not this view is displayed: 7977 * {@link #VISIBLE} or {@link #INVISIBLE}. 7978 */ 7979 public void dispatchDisplayHint(int hint) { 7980 onDisplayHint(hint); 7981 } 7982 7983 /** 7984 * Gives this view a hint about whether is displayed or not. For instance, when 7985 * a View moves out of the screen, it might receives a display hint indicating 7986 * the view is not displayed. Applications should not <em>rely</em> on this hint 7987 * as there is no guarantee that they will receive one. 7988 * 7989 * @param hint A hint about whether or not this view is displayed: 7990 * {@link #VISIBLE} or {@link #INVISIBLE}. 7991 */ 7992 protected void onDisplayHint(int hint) { 7993 } 7994 7995 /** 7996 * Dispatch a window visibility change down the view hierarchy. 7997 * ViewGroups should override to route to their children. 7998 * 7999 * @param visibility The new visibility of the window. 8000 * 8001 * @see #onWindowVisibilityChanged(int) 8002 */ 8003 public void dispatchWindowVisibilityChanged(int visibility) { 8004 onWindowVisibilityChanged(visibility); 8005 } 8006 8007 /** 8008 * Called when the window containing has change its visibility 8009 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 8010 * that this tells you whether or not your window is being made visible 8011 * to the window manager; this does <em>not</em> tell you whether or not 8012 * your window is obscured by other windows on the screen, even if it 8013 * is itself visible. 8014 * 8015 * @param visibility The new visibility of the window. 8016 */ 8017 protected void onWindowVisibilityChanged(int visibility) { 8018 if (visibility == VISIBLE) { 8019 initialAwakenScrollBars(); 8020 } 8021 } 8022 8023 /** 8024 * Returns the current visibility of the window this view is attached to 8025 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 8026 * 8027 * @return Returns the current visibility of the view's window. 8028 */ 8029 public int getWindowVisibility() { 8030 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 8031 } 8032 8033 /** 8034 * Retrieve the overall visible display size in which the window this view is 8035 * attached to has been positioned in. This takes into account screen 8036 * decorations above the window, for both cases where the window itself 8037 * is being position inside of them or the window is being placed under 8038 * then and covered insets are used for the window to position its content 8039 * inside. In effect, this tells you the available area where content can 8040 * be placed and remain visible to users. 8041 * 8042 * <p>This function requires an IPC back to the window manager to retrieve 8043 * the requested information, so should not be used in performance critical 8044 * code like drawing. 8045 * 8046 * @param outRect Filled in with the visible display frame. If the view 8047 * is not attached to a window, this is simply the raw display size. 8048 */ 8049 public void getWindowVisibleDisplayFrame(Rect outRect) { 8050 if (mAttachInfo != null) { 8051 try { 8052 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 8053 } catch (RemoteException e) { 8054 return; 8055 } 8056 // XXX This is really broken, and probably all needs to be done 8057 // in the window manager, and we need to know more about whether 8058 // we want the area behind or in front of the IME. 8059 final Rect insets = mAttachInfo.mVisibleInsets; 8060 outRect.left += insets.left; 8061 outRect.top += insets.top; 8062 outRect.right -= insets.right; 8063 outRect.bottom -= insets.bottom; 8064 return; 8065 } 8066 // The view is not attached to a display so we don't have a context. 8067 // Make a best guess about the display size. 8068 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 8069 d.getRectSize(outRect); 8070 } 8071 8072 /** 8073 * Dispatch a notification about a resource configuration change down 8074 * the view hierarchy. 8075 * ViewGroups should override to route to their children. 8076 * 8077 * @param newConfig The new resource configuration. 8078 * 8079 * @see #onConfigurationChanged(android.content.res.Configuration) 8080 */ 8081 public void dispatchConfigurationChanged(Configuration newConfig) { 8082 onConfigurationChanged(newConfig); 8083 } 8084 8085 /** 8086 * Called when the current configuration of the resources being used 8087 * by the application have changed. You can use this to decide when 8088 * to reload resources that can changed based on orientation and other 8089 * configuration characterstics. You only need to use this if you are 8090 * not relying on the normal {@link android.app.Activity} mechanism of 8091 * recreating the activity instance upon a configuration change. 8092 * 8093 * @param newConfig The new resource configuration. 8094 */ 8095 protected void onConfigurationChanged(Configuration newConfig) { 8096 } 8097 8098 /** 8099 * Private function to aggregate all per-view attributes in to the view 8100 * root. 8101 */ 8102 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 8103 performCollectViewAttributes(attachInfo, visibility); 8104 } 8105 8106 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 8107 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 8108 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 8109 attachInfo.mKeepScreenOn = true; 8110 } 8111 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 8112 ListenerInfo li = mListenerInfo; 8113 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 8114 attachInfo.mHasSystemUiListeners = true; 8115 } 8116 } 8117 } 8118 8119 void needGlobalAttributesUpdate(boolean force) { 8120 final AttachInfo ai = mAttachInfo; 8121 if (ai != null && !ai.mRecomputeGlobalAttributes) { 8122 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 8123 || ai.mHasSystemUiListeners) { 8124 ai.mRecomputeGlobalAttributes = true; 8125 } 8126 } 8127 } 8128 8129 /** 8130 * Returns whether the device is currently in touch mode. Touch mode is entered 8131 * once the user begins interacting with the device by touch, and affects various 8132 * things like whether focus is always visible to the user. 8133 * 8134 * @return Whether the device is in touch mode. 8135 */ 8136 @ViewDebug.ExportedProperty 8137 public boolean isInTouchMode() { 8138 if (mAttachInfo != null) { 8139 return mAttachInfo.mInTouchMode; 8140 } else { 8141 return ViewRootImpl.isInTouchMode(); 8142 } 8143 } 8144 8145 /** 8146 * Returns the context the view is running in, through which it can 8147 * access the current theme, resources, etc. 8148 * 8149 * @return The view's Context. 8150 */ 8151 @ViewDebug.CapturedViewProperty 8152 public final Context getContext() { 8153 return mContext; 8154 } 8155 8156 /** 8157 * Handle a key event before it is processed by any input method 8158 * associated with the view hierarchy. This can be used to intercept 8159 * key events in special situations before the IME consumes them; a 8160 * typical example would be handling the BACK key to update the application's 8161 * UI instead of allowing the IME to see it and close itself. 8162 * 8163 * @param keyCode The value in event.getKeyCode(). 8164 * @param event Description of the key event. 8165 * @return If you handled the event, return true. If you want to allow the 8166 * event to be handled by the next receiver, return false. 8167 */ 8168 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 8169 return false; 8170 } 8171 8172 /** 8173 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 8174 * KeyEvent.Callback.onKeyDown()}: perform press of the view 8175 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 8176 * is released, if the view is enabled and clickable. 8177 * 8178 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8179 * although some may elect to do so in some situations. Do not rely on this to 8180 * catch software key presses. 8181 * 8182 * @param keyCode A key code that represents the button pressed, from 8183 * {@link android.view.KeyEvent}. 8184 * @param event The KeyEvent object that defines the button action. 8185 */ 8186 public boolean onKeyDown(int keyCode, KeyEvent event) { 8187 boolean result = false; 8188 8189 if (KeyEvent.isConfirmKey(keyCode)) { 8190 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 8191 return true; 8192 } 8193 // Long clickable items don't necessarily have to be clickable 8194 if (((mViewFlags & CLICKABLE) == CLICKABLE || 8195 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && 8196 (event.getRepeatCount() == 0)) { 8197 setPressed(true); 8198 checkForLongClick(0); 8199 return true; 8200 } 8201 } 8202 return result; 8203 } 8204 8205 /** 8206 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 8207 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 8208 * the event). 8209 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8210 * although some may elect to do so in some situations. Do not rely on this to 8211 * catch software key presses. 8212 */ 8213 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 8214 return false; 8215 } 8216 8217 /** 8218 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 8219 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 8220 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or 8221 * {@link KeyEvent#KEYCODE_ENTER} is released. 8222 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8223 * although some may elect to do so in some situations. Do not rely on this to 8224 * catch software key presses. 8225 * 8226 * @param keyCode A key code that represents the button pressed, from 8227 * {@link android.view.KeyEvent}. 8228 * @param event The KeyEvent object that defines the button action. 8229 */ 8230 public boolean onKeyUp(int keyCode, KeyEvent event) { 8231 if (KeyEvent.isConfirmKey(keyCode)) { 8232 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 8233 return true; 8234 } 8235 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 8236 setPressed(false); 8237 8238 if (!mHasPerformedLongPress) { 8239 // This is a tap, so remove the longpress check 8240 removeLongPressCallback(); 8241 return performClick(); 8242 } 8243 } 8244 } 8245 return false; 8246 } 8247 8248 /** 8249 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 8250 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 8251 * the event). 8252 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8253 * although some may elect to do so in some situations. Do not rely on this to 8254 * catch software key presses. 8255 * 8256 * @param keyCode A key code that represents the button pressed, from 8257 * {@link android.view.KeyEvent}. 8258 * @param repeatCount The number of times the action was made. 8259 * @param event The KeyEvent object that defines the button action. 8260 */ 8261 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 8262 return false; 8263 } 8264 8265 /** 8266 * Called on the focused view when a key shortcut event is not handled. 8267 * Override this method to implement local key shortcuts for the View. 8268 * Key shortcuts can also be implemented by setting the 8269 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 8270 * 8271 * @param keyCode The value in event.getKeyCode(). 8272 * @param event Description of the key event. 8273 * @return If you handled the event, return true. If you want to allow the 8274 * event to be handled by the next receiver, return false. 8275 */ 8276 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 8277 return false; 8278 } 8279 8280 /** 8281 * Check whether the called view is a text editor, in which case it 8282 * would make sense to automatically display a soft input window for 8283 * it. Subclasses should override this if they implement 8284 * {@link #onCreateInputConnection(EditorInfo)} to return true if 8285 * a call on that method would return a non-null InputConnection, and 8286 * they are really a first-class editor that the user would normally 8287 * start typing on when the go into a window containing your view. 8288 * 8289 * <p>The default implementation always returns false. This does 8290 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 8291 * will not be called or the user can not otherwise perform edits on your 8292 * view; it is just a hint to the system that this is not the primary 8293 * purpose of this view. 8294 * 8295 * @return Returns true if this view is a text editor, else false. 8296 */ 8297 public boolean onCheckIsTextEditor() { 8298 return false; 8299 } 8300 8301 /** 8302 * Create a new InputConnection for an InputMethod to interact 8303 * with the view. The default implementation returns null, since it doesn't 8304 * support input methods. You can override this to implement such support. 8305 * This is only needed for views that take focus and text input. 8306 * 8307 * <p>When implementing this, you probably also want to implement 8308 * {@link #onCheckIsTextEditor()} to indicate you will return a 8309 * non-null InputConnection. 8310 * 8311 * @param outAttrs Fill in with attribute information about the connection. 8312 */ 8313 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 8314 return null; 8315 } 8316 8317 /** 8318 * Called by the {@link android.view.inputmethod.InputMethodManager} 8319 * when a view who is not the current 8320 * input connection target is trying to make a call on the manager. The 8321 * default implementation returns false; you can override this to return 8322 * true for certain views if you are performing InputConnection proxying 8323 * to them. 8324 * @param view The View that is making the InputMethodManager call. 8325 * @return Return true to allow the call, false to reject. 8326 */ 8327 public boolean checkInputConnectionProxy(View view) { 8328 return false; 8329 } 8330 8331 /** 8332 * Show the context menu for this view. It is not safe to hold on to the 8333 * menu after returning from this method. 8334 * 8335 * You should normally not overload this method. Overload 8336 * {@link #onCreateContextMenu(ContextMenu)} or define an 8337 * {@link OnCreateContextMenuListener} to add items to the context menu. 8338 * 8339 * @param menu The context menu to populate 8340 */ 8341 public void createContextMenu(ContextMenu menu) { 8342 ContextMenuInfo menuInfo = getContextMenuInfo(); 8343 8344 // Sets the current menu info so all items added to menu will have 8345 // my extra info set. 8346 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 8347 8348 onCreateContextMenu(menu); 8349 ListenerInfo li = mListenerInfo; 8350 if (li != null && li.mOnCreateContextMenuListener != null) { 8351 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 8352 } 8353 8354 // Clear the extra information so subsequent items that aren't mine don't 8355 // have my extra info. 8356 ((MenuBuilder)menu).setCurrentMenuInfo(null); 8357 8358 if (mParent != null) { 8359 mParent.createContextMenu(menu); 8360 } 8361 } 8362 8363 /** 8364 * Views should implement this if they have extra information to associate 8365 * with the context menu. The return result is supplied as a parameter to 8366 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 8367 * callback. 8368 * 8369 * @return Extra information about the item for which the context menu 8370 * should be shown. This information will vary across different 8371 * subclasses of View. 8372 */ 8373 protected ContextMenuInfo getContextMenuInfo() { 8374 return null; 8375 } 8376 8377 /** 8378 * Views should implement this if the view itself is going to add items to 8379 * the context menu. 8380 * 8381 * @param menu the context menu to populate 8382 */ 8383 protected void onCreateContextMenu(ContextMenu menu) { 8384 } 8385 8386 /** 8387 * Implement this method to handle trackball motion events. The 8388 * <em>relative</em> movement of the trackball since the last event 8389 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 8390 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 8391 * that a movement of 1 corresponds to the user pressing one DPAD key (so 8392 * they will often be fractional values, representing the more fine-grained 8393 * movement information available from a trackball). 8394 * 8395 * @param event The motion event. 8396 * @return True if the event was handled, false otherwise. 8397 */ 8398 public boolean onTrackballEvent(MotionEvent event) { 8399 return false; 8400 } 8401 8402 /** 8403 * Implement this method to handle generic motion events. 8404 * <p> 8405 * Generic motion events describe joystick movements, mouse hovers, track pad 8406 * touches, scroll wheel movements and other input events. The 8407 * {@link MotionEvent#getSource() source} of the motion event specifies 8408 * the class of input that was received. Implementations of this method 8409 * must examine the bits in the source before processing the event. 8410 * The following code example shows how this is done. 8411 * </p><p> 8412 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 8413 * are delivered to the view under the pointer. All other generic motion events are 8414 * delivered to the focused view. 8415 * </p> 8416 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 8417 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 8418 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 8419 * // process the joystick movement... 8420 * return true; 8421 * } 8422 * } 8423 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 8424 * switch (event.getAction()) { 8425 * case MotionEvent.ACTION_HOVER_MOVE: 8426 * // process the mouse hover movement... 8427 * return true; 8428 * case MotionEvent.ACTION_SCROLL: 8429 * // process the scroll wheel movement... 8430 * return true; 8431 * } 8432 * } 8433 * return super.onGenericMotionEvent(event); 8434 * }</pre> 8435 * 8436 * @param event The generic motion event being processed. 8437 * @return True if the event was handled, false otherwise. 8438 */ 8439 public boolean onGenericMotionEvent(MotionEvent event) { 8440 return false; 8441 } 8442 8443 /** 8444 * Implement this method to handle hover events. 8445 * <p> 8446 * This method is called whenever a pointer is hovering into, over, or out of the 8447 * bounds of a view and the view is not currently being touched. 8448 * Hover events are represented as pointer events with action 8449 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 8450 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 8451 * </p> 8452 * <ul> 8453 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 8454 * when the pointer enters the bounds of the view.</li> 8455 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 8456 * when the pointer has already entered the bounds of the view and has moved.</li> 8457 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 8458 * when the pointer has exited the bounds of the view or when the pointer is 8459 * about to go down due to a button click, tap, or similar user action that 8460 * causes the view to be touched.</li> 8461 * </ul> 8462 * <p> 8463 * The view should implement this method to return true to indicate that it is 8464 * handling the hover event, such as by changing its drawable state. 8465 * </p><p> 8466 * The default implementation calls {@link #setHovered} to update the hovered state 8467 * of the view when a hover enter or hover exit event is received, if the view 8468 * is enabled and is clickable. The default implementation also sends hover 8469 * accessibility events. 8470 * </p> 8471 * 8472 * @param event The motion event that describes the hover. 8473 * @return True if the view handled the hover event. 8474 * 8475 * @see #isHovered 8476 * @see #setHovered 8477 * @see #onHoverChanged 8478 */ 8479 public boolean onHoverEvent(MotionEvent event) { 8480 // The root view may receive hover (or touch) events that are outside the bounds of 8481 // the window. This code ensures that we only send accessibility events for 8482 // hovers that are actually within the bounds of the root view. 8483 final int action = event.getActionMasked(); 8484 if (!mSendingHoverAccessibilityEvents) { 8485 if ((action == MotionEvent.ACTION_HOVER_ENTER 8486 || action == MotionEvent.ACTION_HOVER_MOVE) 8487 && !hasHoveredChild() 8488 && pointInView(event.getX(), event.getY())) { 8489 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 8490 mSendingHoverAccessibilityEvents = true; 8491 } 8492 } else { 8493 if (action == MotionEvent.ACTION_HOVER_EXIT 8494 || (action == MotionEvent.ACTION_MOVE 8495 && !pointInView(event.getX(), event.getY()))) { 8496 mSendingHoverAccessibilityEvents = false; 8497 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 8498 // If the window does not have input focus we take away accessibility 8499 // focus as soon as the user stop hovering over the view. 8500 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) { 8501 getViewRootImpl().setAccessibilityFocus(null, null); 8502 } 8503 } 8504 } 8505 8506 if (isHoverable()) { 8507 switch (action) { 8508 case MotionEvent.ACTION_HOVER_ENTER: 8509 setHovered(true); 8510 break; 8511 case MotionEvent.ACTION_HOVER_EXIT: 8512 setHovered(false); 8513 break; 8514 } 8515 8516 // Dispatch the event to onGenericMotionEvent before returning true. 8517 // This is to provide compatibility with existing applications that 8518 // handled HOVER_MOVE events in onGenericMotionEvent and that would 8519 // break because of the new default handling for hoverable views 8520 // in onHoverEvent. 8521 // Note that onGenericMotionEvent will be called by default when 8522 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 8523 dispatchGenericMotionEventInternal(event); 8524 // The event was already handled by calling setHovered(), so always 8525 // return true. 8526 return true; 8527 } 8528 8529 return false; 8530 } 8531 8532 /** 8533 * Returns true if the view should handle {@link #onHoverEvent} 8534 * by calling {@link #setHovered} to change its hovered state. 8535 * 8536 * @return True if the view is hoverable. 8537 */ 8538 private boolean isHoverable() { 8539 final int viewFlags = mViewFlags; 8540 if ((viewFlags & ENABLED_MASK) == DISABLED) { 8541 return false; 8542 } 8543 8544 return (viewFlags & CLICKABLE) == CLICKABLE 8545 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 8546 } 8547 8548 /** 8549 * Returns true if the view is currently hovered. 8550 * 8551 * @return True if the view is currently hovered. 8552 * 8553 * @see #setHovered 8554 * @see #onHoverChanged 8555 */ 8556 @ViewDebug.ExportedProperty 8557 public boolean isHovered() { 8558 return (mPrivateFlags & PFLAG_HOVERED) != 0; 8559 } 8560 8561 /** 8562 * Sets whether the view is currently hovered. 8563 * <p> 8564 * Calling this method also changes the drawable state of the view. This 8565 * enables the view to react to hover by using different drawable resources 8566 * to change its appearance. 8567 * </p><p> 8568 * The {@link #onHoverChanged} method is called when the hovered state changes. 8569 * </p> 8570 * 8571 * @param hovered True if the view is hovered. 8572 * 8573 * @see #isHovered 8574 * @see #onHoverChanged 8575 */ 8576 public void setHovered(boolean hovered) { 8577 if (hovered) { 8578 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 8579 mPrivateFlags |= PFLAG_HOVERED; 8580 refreshDrawableState(); 8581 onHoverChanged(true); 8582 } 8583 } else { 8584 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 8585 mPrivateFlags &= ~PFLAG_HOVERED; 8586 refreshDrawableState(); 8587 onHoverChanged(false); 8588 } 8589 } 8590 } 8591 8592 /** 8593 * Implement this method to handle hover state changes. 8594 * <p> 8595 * This method is called whenever the hover state changes as a result of a 8596 * call to {@link #setHovered}. 8597 * </p> 8598 * 8599 * @param hovered The current hover state, as returned by {@link #isHovered}. 8600 * 8601 * @see #isHovered 8602 * @see #setHovered 8603 */ 8604 public void onHoverChanged(boolean hovered) { 8605 } 8606 8607 /** 8608 * Implement this method to handle touch screen motion events. 8609 * <p> 8610 * If this method is used to detect click actions, it is recommended that 8611 * the actions be performed by implementing and calling 8612 * {@link #performClick()}. This will ensure consistent system behavior, 8613 * including: 8614 * <ul> 8615 * <li>obeying click sound preferences 8616 * <li>dispatching OnClickListener calls 8617 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 8618 * accessibility features are enabled 8619 * </ul> 8620 * 8621 * @param event The motion event. 8622 * @return True if the event was handled, false otherwise. 8623 */ 8624 public boolean onTouchEvent(MotionEvent event) { 8625 final int viewFlags = mViewFlags; 8626 8627 if ((viewFlags & ENABLED_MASK) == DISABLED) { 8628 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 8629 setPressed(false); 8630 } 8631 // A disabled view that is clickable still consumes the touch 8632 // events, it just doesn't respond to them. 8633 return (((viewFlags & CLICKABLE) == CLICKABLE || 8634 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 8635 } 8636 8637 if (mTouchDelegate != null) { 8638 if (mTouchDelegate.onTouchEvent(event)) { 8639 return true; 8640 } 8641 } 8642 8643 if (((viewFlags & CLICKABLE) == CLICKABLE || 8644 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 8645 switch (event.getAction()) { 8646 case MotionEvent.ACTION_UP: 8647 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 8648 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 8649 // take focus if we don't have it already and we should in 8650 // touch mode. 8651 boolean focusTaken = false; 8652 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 8653 focusTaken = requestFocus(); 8654 } 8655 8656 if (prepressed) { 8657 // The button is being released before we actually 8658 // showed it as pressed. Make it show the pressed 8659 // state now (before scheduling the click) to ensure 8660 // the user sees it. 8661 setPressed(true); 8662 } 8663 8664 if (!mHasPerformedLongPress) { 8665 // This is a tap, so remove the longpress check 8666 removeLongPressCallback(); 8667 8668 // Only perform take click actions if we were in the pressed state 8669 if (!focusTaken) { 8670 // Use a Runnable and post this rather than calling 8671 // performClick directly. This lets other visual state 8672 // of the view update before click actions start. 8673 if (mPerformClick == null) { 8674 mPerformClick = new PerformClick(); 8675 } 8676 if (!post(mPerformClick)) { 8677 performClick(); 8678 } 8679 } 8680 } 8681 8682 if (mUnsetPressedState == null) { 8683 mUnsetPressedState = new UnsetPressedState(); 8684 } 8685 8686 if (prepressed) { 8687 postDelayed(mUnsetPressedState, 8688 ViewConfiguration.getPressedStateDuration()); 8689 } else if (!post(mUnsetPressedState)) { 8690 // If the post failed, unpress right now 8691 mUnsetPressedState.run(); 8692 } 8693 removeTapCallback(); 8694 } 8695 break; 8696 8697 case MotionEvent.ACTION_DOWN: 8698 mHasPerformedLongPress = false; 8699 8700 if (performButtonActionOnTouchDown(event)) { 8701 break; 8702 } 8703 8704 // Walk up the hierarchy to determine if we're inside a scrolling container. 8705 boolean isInScrollingContainer = isInScrollingContainer(); 8706 8707 // For views inside a scrolling container, delay the pressed feedback for 8708 // a short period in case this is a scroll. 8709 if (isInScrollingContainer) { 8710 mPrivateFlags |= PFLAG_PREPRESSED; 8711 if (mPendingCheckForTap == null) { 8712 mPendingCheckForTap = new CheckForTap(); 8713 } 8714 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 8715 } else { 8716 // Not inside a scrolling container, so show the feedback right away 8717 setPressed(true); 8718 checkForLongClick(0); 8719 } 8720 break; 8721 8722 case MotionEvent.ACTION_CANCEL: 8723 setPressed(false); 8724 removeTapCallback(); 8725 removeLongPressCallback(); 8726 break; 8727 8728 case MotionEvent.ACTION_MOVE: 8729 final int x = (int) event.getX(); 8730 final int y = (int) event.getY(); 8731 8732 // Be lenient about moving outside of buttons 8733 if (!pointInView(x, y, mTouchSlop)) { 8734 // Outside button 8735 removeTapCallback(); 8736 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 8737 // Remove any future long press/tap checks 8738 removeLongPressCallback(); 8739 8740 setPressed(false); 8741 } 8742 } 8743 break; 8744 } 8745 return true; 8746 } 8747 8748 return false; 8749 } 8750 8751 /** 8752 * @hide 8753 */ 8754 public boolean isInScrollingContainer() { 8755 ViewParent p = getParent(); 8756 while (p != null && p instanceof ViewGroup) { 8757 if (((ViewGroup) p).shouldDelayChildPressedState()) { 8758 return true; 8759 } 8760 p = p.getParent(); 8761 } 8762 return false; 8763 } 8764 8765 /** 8766 * Remove the longpress detection timer. 8767 */ 8768 private void removeLongPressCallback() { 8769 if (mPendingCheckForLongPress != null) { 8770 removeCallbacks(mPendingCheckForLongPress); 8771 } 8772 } 8773 8774 /** 8775 * Remove the pending click action 8776 */ 8777 private void removePerformClickCallback() { 8778 if (mPerformClick != null) { 8779 removeCallbacks(mPerformClick); 8780 } 8781 } 8782 8783 /** 8784 * Remove the prepress detection timer. 8785 */ 8786 private void removeUnsetPressCallback() { 8787 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 8788 setPressed(false); 8789 removeCallbacks(mUnsetPressedState); 8790 } 8791 } 8792 8793 /** 8794 * Remove the tap detection timer. 8795 */ 8796 private void removeTapCallback() { 8797 if (mPendingCheckForTap != null) { 8798 mPrivateFlags &= ~PFLAG_PREPRESSED; 8799 removeCallbacks(mPendingCheckForTap); 8800 } 8801 } 8802 8803 /** 8804 * Cancels a pending long press. Your subclass can use this if you 8805 * want the context menu to come up if the user presses and holds 8806 * at the same place, but you don't want it to come up if they press 8807 * and then move around enough to cause scrolling. 8808 */ 8809 public void cancelLongPress() { 8810 removeLongPressCallback(); 8811 8812 /* 8813 * The prepressed state handled by the tap callback is a display 8814 * construct, but the tap callback will post a long press callback 8815 * less its own timeout. Remove it here. 8816 */ 8817 removeTapCallback(); 8818 } 8819 8820 /** 8821 * Remove the pending callback for sending a 8822 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 8823 */ 8824 private void removeSendViewScrolledAccessibilityEventCallback() { 8825 if (mSendViewScrolledAccessibilityEvent != null) { 8826 removeCallbacks(mSendViewScrolledAccessibilityEvent); 8827 mSendViewScrolledAccessibilityEvent.mIsPending = false; 8828 } 8829 } 8830 8831 /** 8832 * Sets the TouchDelegate for this View. 8833 */ 8834 public void setTouchDelegate(TouchDelegate delegate) { 8835 mTouchDelegate = delegate; 8836 } 8837 8838 /** 8839 * Gets the TouchDelegate for this View. 8840 */ 8841 public TouchDelegate getTouchDelegate() { 8842 return mTouchDelegate; 8843 } 8844 8845 /** 8846 * Set flags controlling behavior of this view. 8847 * 8848 * @param flags Constant indicating the value which should be set 8849 * @param mask Constant indicating the bit range that should be changed 8850 */ 8851 void setFlags(int flags, int mask) { 8852 final boolean accessibilityEnabled = 8853 AccessibilityManager.getInstance(mContext).isEnabled(); 8854 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 8855 8856 int old = mViewFlags; 8857 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 8858 8859 int changed = mViewFlags ^ old; 8860 if (changed == 0) { 8861 return; 8862 } 8863 int privateFlags = mPrivateFlags; 8864 8865 /* Check if the FOCUSABLE bit has changed */ 8866 if (((changed & FOCUSABLE_MASK) != 0) && 8867 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { 8868 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 8869 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 8870 /* Give up focus if we are no longer focusable */ 8871 clearFocus(); 8872 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 8873 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 8874 /* 8875 * Tell the view system that we are now available to take focus 8876 * if no one else already has it. 8877 */ 8878 if (mParent != null) mParent.focusableViewAvailable(this); 8879 } 8880 } 8881 8882 final int newVisibility = flags & VISIBILITY_MASK; 8883 if (newVisibility == VISIBLE) { 8884 if ((changed & VISIBILITY_MASK) != 0) { 8885 /* 8886 * If this view is becoming visible, invalidate it in case it changed while 8887 * it was not visible. Marking it drawn ensures that the invalidation will 8888 * go through. 8889 */ 8890 mPrivateFlags |= PFLAG_DRAWN; 8891 invalidate(true); 8892 8893 needGlobalAttributesUpdate(true); 8894 8895 // a view becoming visible is worth notifying the parent 8896 // about in case nothing has focus. even if this specific view 8897 // isn't focusable, it may contain something that is, so let 8898 // the root view try to give this focus if nothing else does. 8899 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 8900 mParent.focusableViewAvailable(this); 8901 } 8902 } 8903 } 8904 8905 /* Check if the GONE bit has changed */ 8906 if ((changed & GONE) != 0) { 8907 needGlobalAttributesUpdate(false); 8908 requestLayout(); 8909 8910 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 8911 if (hasFocus()) clearFocus(); 8912 clearAccessibilityFocus(); 8913 destroyDrawingCache(); 8914 if (mParent instanceof View) { 8915 // GONE views noop invalidation, so invalidate the parent 8916 ((View) mParent).invalidate(true); 8917 } 8918 // Mark the view drawn to ensure that it gets invalidated properly the next 8919 // time it is visible and gets invalidated 8920 mPrivateFlags |= PFLAG_DRAWN; 8921 } 8922 if (mAttachInfo != null) { 8923 mAttachInfo.mViewVisibilityChanged = true; 8924 } 8925 } 8926 8927 /* Check if the VISIBLE bit has changed */ 8928 if ((changed & INVISIBLE) != 0) { 8929 needGlobalAttributesUpdate(false); 8930 /* 8931 * If this view is becoming invisible, set the DRAWN flag so that 8932 * the next invalidate() will not be skipped. 8933 */ 8934 mPrivateFlags |= PFLAG_DRAWN; 8935 8936 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 8937 // root view becoming invisible shouldn't clear focus and accessibility focus 8938 if (getRootView() != this) { 8939 if (hasFocus()) clearFocus(); 8940 clearAccessibilityFocus(); 8941 } 8942 } 8943 if (mAttachInfo != null) { 8944 mAttachInfo.mViewVisibilityChanged = true; 8945 } 8946 } 8947 8948 if ((changed & VISIBILITY_MASK) != 0) { 8949 // If the view is invisible, cleanup its display list to free up resources 8950 if (newVisibility != VISIBLE) { 8951 cleanupDraw(); 8952 } 8953 8954 if (mParent instanceof ViewGroup) { 8955 ((ViewGroup) mParent).onChildVisibilityChanged(this, 8956 (changed & VISIBILITY_MASK), newVisibility); 8957 ((View) mParent).invalidate(true); 8958 } else if (mParent != null) { 8959 mParent.invalidateChild(this, null); 8960 } 8961 dispatchVisibilityChanged(this, newVisibility); 8962 } 8963 8964 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 8965 destroyDrawingCache(); 8966 } 8967 8968 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 8969 destroyDrawingCache(); 8970 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 8971 invalidateParentCaches(); 8972 } 8973 8974 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 8975 destroyDrawingCache(); 8976 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 8977 } 8978 8979 if ((changed & DRAW_MASK) != 0) { 8980 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 8981 if (mBackground != null) { 8982 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 8983 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; 8984 } else { 8985 mPrivateFlags |= PFLAG_SKIP_DRAW; 8986 } 8987 } else { 8988 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 8989 } 8990 requestLayout(); 8991 invalidate(true); 8992 } 8993 8994 if ((changed & KEEP_SCREEN_ON) != 0) { 8995 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 8996 mParent.recomputeViewAttributes(this); 8997 } 8998 } 8999 9000 if (accessibilityEnabled) { 9001 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0 9002 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) { 9003 if (oldIncludeForAccessibility != includeForAccessibility()) { 9004 notifySubtreeAccessibilityStateChangedIfNeeded(); 9005 } else { 9006 notifyViewAccessibilityStateChangedIfNeeded( 9007 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9008 } 9009 } else if ((changed & ENABLED_MASK) != 0) { 9010 notifyViewAccessibilityStateChangedIfNeeded( 9011 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9012 } 9013 } 9014 } 9015 9016 /** 9017 * Change the view's z order in the tree, so it's on top of other sibling 9018 * views. This ordering change may affect layout, if the parent container 9019 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 9020 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 9021 * method should be followed by calls to {@link #requestLayout()} and 9022 * {@link View#invalidate()} on the view's parent to force the parent to redraw 9023 * with the new child ordering. 9024 * 9025 * @see ViewGroup#bringChildToFront(View) 9026 */ 9027 public void bringToFront() { 9028 if (mParent != null) { 9029 mParent.bringChildToFront(this); 9030 } 9031 } 9032 9033 /** 9034 * This is called in response to an internal scroll in this view (i.e., the 9035 * view scrolled its own contents). This is typically as a result of 9036 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 9037 * called. 9038 * 9039 * @param l Current horizontal scroll origin. 9040 * @param t Current vertical scroll origin. 9041 * @param oldl Previous horizontal scroll origin. 9042 * @param oldt Previous vertical scroll origin. 9043 */ 9044 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 9045 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 9046 postSendViewScrolledAccessibilityEventCallback(); 9047 } 9048 9049 mBackgroundSizeChanged = true; 9050 9051 final AttachInfo ai = mAttachInfo; 9052 if (ai != null) { 9053 ai.mViewScrollChanged = true; 9054 } 9055 } 9056 9057 /** 9058 * Interface definition for a callback to be invoked when the layout bounds of a view 9059 * changes due to layout processing. 9060 */ 9061 public interface OnLayoutChangeListener { 9062 /** 9063 * Called when the focus state of a view has changed. 9064 * 9065 * @param v The view whose state has changed. 9066 * @param left The new value of the view's left property. 9067 * @param top The new value of the view's top property. 9068 * @param right The new value of the view's right property. 9069 * @param bottom The new value of the view's bottom property. 9070 * @param oldLeft The previous value of the view's left property. 9071 * @param oldTop The previous value of the view's top property. 9072 * @param oldRight The previous value of the view's right property. 9073 * @param oldBottom The previous value of the view's bottom property. 9074 */ 9075 void onLayoutChange(View v, int left, int top, int right, int bottom, 9076 int oldLeft, int oldTop, int oldRight, int oldBottom); 9077 } 9078 9079 /** 9080 * This is called during layout when the size of this view has changed. If 9081 * you were just added to the view hierarchy, you're called with the old 9082 * values of 0. 9083 * 9084 * @param w Current width of this view. 9085 * @param h Current height of this view. 9086 * @param oldw Old width of this view. 9087 * @param oldh Old height of this view. 9088 */ 9089 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 9090 } 9091 9092 /** 9093 * Called by draw to draw the child views. This may be overridden 9094 * by derived classes to gain control just before its children are drawn 9095 * (but after its own view has been drawn). 9096 * @param canvas the canvas on which to draw the view 9097 */ 9098 protected void dispatchDraw(Canvas canvas) { 9099 9100 } 9101 9102 /** 9103 * Gets the parent of this view. Note that the parent is a 9104 * ViewParent and not necessarily a View. 9105 * 9106 * @return Parent of this view. 9107 */ 9108 public final ViewParent getParent() { 9109 return mParent; 9110 } 9111 9112 /** 9113 * Set the horizontal scrolled position of your view. This will cause a call to 9114 * {@link #onScrollChanged(int, int, int, int)} and the view will be 9115 * invalidated. 9116 * @param value the x position to scroll to 9117 */ 9118 public void setScrollX(int value) { 9119 scrollTo(value, mScrollY); 9120 } 9121 9122 /** 9123 * Set the vertical scrolled position of your view. This will cause a call to 9124 * {@link #onScrollChanged(int, int, int, int)} and the view will be 9125 * invalidated. 9126 * @param value the y position to scroll to 9127 */ 9128 public void setScrollY(int value) { 9129 scrollTo(mScrollX, value); 9130 } 9131 9132 /** 9133 * Return the scrolled left position of this view. This is the left edge of 9134 * the displayed part of your view. You do not need to draw any pixels 9135 * farther left, since those are outside of the frame of your view on 9136 * screen. 9137 * 9138 * @return The left edge of the displayed part of your view, in pixels. 9139 */ 9140 public final int getScrollX() { 9141 return mScrollX; 9142 } 9143 9144 /** 9145 * Return the scrolled top position of this view. This is the top edge of 9146 * the displayed part of your view. You do not need to draw any pixels above 9147 * it, since those are outside of the frame of your view on screen. 9148 * 9149 * @return The top edge of the displayed part of your view, in pixels. 9150 */ 9151 public final int getScrollY() { 9152 return mScrollY; 9153 } 9154 9155 /** 9156 * Return the width of the your view. 9157 * 9158 * @return The width of your view, in pixels. 9159 */ 9160 @ViewDebug.ExportedProperty(category = "layout") 9161 public final int getWidth() { 9162 return mRight - mLeft; 9163 } 9164 9165 /** 9166 * Return the height of your view. 9167 * 9168 * @return The height of your view, in pixels. 9169 */ 9170 @ViewDebug.ExportedProperty(category = "layout") 9171 public final int getHeight() { 9172 return mBottom - mTop; 9173 } 9174 9175 /** 9176 * Return the visible drawing bounds of your view. Fills in the output 9177 * rectangle with the values from getScrollX(), getScrollY(), 9178 * getWidth(), and getHeight(). These bounds do not account for any 9179 * transformation properties currently set on the view, such as 9180 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 9181 * 9182 * @param outRect The (scrolled) drawing bounds of the view. 9183 */ 9184 public void getDrawingRect(Rect outRect) { 9185 outRect.left = mScrollX; 9186 outRect.top = mScrollY; 9187 outRect.right = mScrollX + (mRight - mLeft); 9188 outRect.bottom = mScrollY + (mBottom - mTop); 9189 } 9190 9191 /** 9192 * Like {@link #getMeasuredWidthAndState()}, but only returns the 9193 * raw width component (that is the result is masked by 9194 * {@link #MEASURED_SIZE_MASK}). 9195 * 9196 * @return The raw measured width of this view. 9197 */ 9198 public final int getMeasuredWidth() { 9199 return mMeasuredWidth & MEASURED_SIZE_MASK; 9200 } 9201 9202 /** 9203 * Return the full width measurement information for this view as computed 9204 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 9205 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 9206 * This should be used during measurement and layout calculations only. Use 9207 * {@link #getWidth()} to see how wide a view is after layout. 9208 * 9209 * @return The measured width of this view as a bit mask. 9210 */ 9211 public final int getMeasuredWidthAndState() { 9212 return mMeasuredWidth; 9213 } 9214 9215 /** 9216 * Like {@link #getMeasuredHeightAndState()}, but only returns the 9217 * raw width component (that is the result is masked by 9218 * {@link #MEASURED_SIZE_MASK}). 9219 * 9220 * @return The raw measured height of this view. 9221 */ 9222 public final int getMeasuredHeight() { 9223 return mMeasuredHeight & MEASURED_SIZE_MASK; 9224 } 9225 9226 /** 9227 * Return the full height measurement information for this view as computed 9228 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 9229 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 9230 * This should be used during measurement and layout calculations only. Use 9231 * {@link #getHeight()} to see how wide a view is after layout. 9232 * 9233 * @return The measured width of this view as a bit mask. 9234 */ 9235 public final int getMeasuredHeightAndState() { 9236 return mMeasuredHeight; 9237 } 9238 9239 /** 9240 * Return only the state bits of {@link #getMeasuredWidthAndState()} 9241 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 9242 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 9243 * and the height component is at the shifted bits 9244 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 9245 */ 9246 public final int getMeasuredState() { 9247 return (mMeasuredWidth&MEASURED_STATE_MASK) 9248 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 9249 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 9250 } 9251 9252 /** 9253 * The transform matrix of this view, which is calculated based on the current 9254 * roation, scale, and pivot properties. 9255 * 9256 * @see #getRotation() 9257 * @see #getScaleX() 9258 * @see #getScaleY() 9259 * @see #getPivotX() 9260 * @see #getPivotY() 9261 * @return The current transform matrix for the view 9262 */ 9263 public Matrix getMatrix() { 9264 if (mTransformationInfo != null) { 9265 updateMatrix(); 9266 return mTransformationInfo.mMatrix; 9267 } 9268 return Matrix.IDENTITY_MATRIX; 9269 } 9270 9271 /** 9272 * Utility function to determine if the value is far enough away from zero to be 9273 * considered non-zero. 9274 * @param value A floating point value to check for zero-ness 9275 * @return whether the passed-in value is far enough away from zero to be considered non-zero 9276 */ 9277 private static boolean nonzero(float value) { 9278 return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON); 9279 } 9280 9281 /** 9282 * Returns true if the transform matrix is the identity matrix. 9283 * Recomputes the matrix if necessary. 9284 * 9285 * @return True if the transform matrix is the identity matrix, false otherwise. 9286 */ 9287 final boolean hasIdentityMatrix() { 9288 if (mTransformationInfo != null) { 9289 updateMatrix(); 9290 return mTransformationInfo.mMatrixIsIdentity; 9291 } 9292 return true; 9293 } 9294 9295 void ensureTransformationInfo() { 9296 if (mTransformationInfo == null) { 9297 mTransformationInfo = new TransformationInfo(); 9298 } 9299 } 9300 9301 /** 9302 * Recomputes the transform matrix if necessary. 9303 */ 9304 private void updateMatrix() { 9305 final TransformationInfo info = mTransformationInfo; 9306 if (info == null) { 9307 return; 9308 } 9309 if (info.mMatrixDirty) { 9310 // transform-related properties have changed since the last time someone 9311 // asked for the matrix; recalculate it with the current values 9312 9313 // Figure out if we need to update the pivot point 9314 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 9315 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) { 9316 info.mPrevWidth = mRight - mLeft; 9317 info.mPrevHeight = mBottom - mTop; 9318 info.mPivotX = info.mPrevWidth / 2f; 9319 info.mPivotY = info.mPrevHeight / 2f; 9320 } 9321 } 9322 info.mMatrix.reset(); 9323 if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) { 9324 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY); 9325 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY); 9326 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); 9327 } else { 9328 if (info.mCamera == null) { 9329 info.mCamera = new Camera(); 9330 info.matrix3D = new Matrix(); 9331 } 9332 info.mCamera.save(); 9333 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); 9334 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation); 9335 info.mCamera.getMatrix(info.matrix3D); 9336 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY); 9337 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX, 9338 info.mPivotY + info.mTranslationY); 9339 info.mMatrix.postConcat(info.matrix3D); 9340 info.mCamera.restore(); 9341 } 9342 info.mMatrixDirty = false; 9343 info.mMatrixIsIdentity = info.mMatrix.isIdentity(); 9344 info.mInverseMatrixDirty = true; 9345 } 9346 } 9347 9348 /** 9349 * Utility method to retrieve the inverse of the current mMatrix property. 9350 * We cache the matrix to avoid recalculating it when transform properties 9351 * have not changed. 9352 * 9353 * @return The inverse of the current matrix of this view. 9354 */ 9355 final Matrix getInverseMatrix() { 9356 final TransformationInfo info = mTransformationInfo; 9357 if (info != null) { 9358 updateMatrix(); 9359 if (info.mInverseMatrixDirty) { 9360 if (info.mInverseMatrix == null) { 9361 info.mInverseMatrix = new Matrix(); 9362 } 9363 info.mMatrix.invert(info.mInverseMatrix); 9364 info.mInverseMatrixDirty = false; 9365 } 9366 return info.mInverseMatrix; 9367 } 9368 return Matrix.IDENTITY_MATRIX; 9369 } 9370 9371 /** 9372 * Gets the distance along the Z axis from the camera to this view. 9373 * 9374 * @see #setCameraDistance(float) 9375 * 9376 * @return The distance along the Z axis. 9377 */ 9378 public float getCameraDistance() { 9379 ensureTransformationInfo(); 9380 final float dpi = mResources.getDisplayMetrics().densityDpi; 9381 final TransformationInfo info = mTransformationInfo; 9382 if (info.mCamera == null) { 9383 info.mCamera = new Camera(); 9384 info.matrix3D = new Matrix(); 9385 } 9386 return -(info.mCamera.getLocationZ() * dpi); 9387 } 9388 9389 /** 9390 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 9391 * views are drawn) from the camera to this view. The camera's distance 9392 * affects 3D transformations, for instance rotations around the X and Y 9393 * axis. If the rotationX or rotationY properties are changed and this view is 9394 * large (more than half the size of the screen), it is recommended to always 9395 * use a camera distance that's greater than the height (X axis rotation) or 9396 * the width (Y axis rotation) of this view.</p> 9397 * 9398 * <p>The distance of the camera from the view plane can have an affect on the 9399 * perspective distortion of the view when it is rotated around the x or y axis. 9400 * For example, a large distance will result in a large viewing angle, and there 9401 * will not be much perspective distortion of the view as it rotates. A short 9402 * distance may cause much more perspective distortion upon rotation, and can 9403 * also result in some drawing artifacts if the rotated view ends up partially 9404 * behind the camera (which is why the recommendation is to use a distance at 9405 * least as far as the size of the view, if the view is to be rotated.)</p> 9406 * 9407 * <p>The distance is expressed in "depth pixels." The default distance depends 9408 * on the screen density. For instance, on a medium density display, the 9409 * default distance is 1280. On a high density display, the default distance 9410 * is 1920.</p> 9411 * 9412 * <p>If you want to specify a distance that leads to visually consistent 9413 * results across various densities, use the following formula:</p> 9414 * <pre> 9415 * float scale = context.getResources().getDisplayMetrics().density; 9416 * view.setCameraDistance(distance * scale); 9417 * </pre> 9418 * 9419 * <p>The density scale factor of a high density display is 1.5, 9420 * and 1920 = 1280 * 1.5.</p> 9421 * 9422 * @param distance The distance in "depth pixels", if negative the opposite 9423 * value is used 9424 * 9425 * @see #setRotationX(float) 9426 * @see #setRotationY(float) 9427 */ 9428 public void setCameraDistance(float distance) { 9429 invalidateViewProperty(true, false); 9430 9431 ensureTransformationInfo(); 9432 final float dpi = mResources.getDisplayMetrics().densityDpi; 9433 final TransformationInfo info = mTransformationInfo; 9434 if (info.mCamera == null) { 9435 info.mCamera = new Camera(); 9436 info.matrix3D = new Matrix(); 9437 } 9438 9439 info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi); 9440 info.mMatrixDirty = true; 9441 9442 invalidateViewProperty(false, false); 9443 if (mDisplayList != null) { 9444 mDisplayList.setCameraDistance(-Math.abs(distance) / dpi); 9445 } 9446 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9447 // View was rejected last time it was drawn by its parent; this may have changed 9448 invalidateParentIfNeeded(); 9449 } 9450 } 9451 9452 /** 9453 * The degrees that the view is rotated around the pivot point. 9454 * 9455 * @see #setRotation(float) 9456 * @see #getPivotX() 9457 * @see #getPivotY() 9458 * 9459 * @return The degrees of rotation. 9460 */ 9461 @ViewDebug.ExportedProperty(category = "drawing") 9462 public float getRotation() { 9463 return mTransformationInfo != null ? mTransformationInfo.mRotation : 0; 9464 } 9465 9466 /** 9467 * Sets the degrees that the view is rotated around the pivot point. Increasing values 9468 * result in clockwise rotation. 9469 * 9470 * @param rotation The degrees of rotation. 9471 * 9472 * @see #getRotation() 9473 * @see #getPivotX() 9474 * @see #getPivotY() 9475 * @see #setRotationX(float) 9476 * @see #setRotationY(float) 9477 * 9478 * @attr ref android.R.styleable#View_rotation 9479 */ 9480 public void setRotation(float rotation) { 9481 ensureTransformationInfo(); 9482 final TransformationInfo info = mTransformationInfo; 9483 if (info.mRotation != rotation) { 9484 // Double-invalidation is necessary to capture view's old and new areas 9485 invalidateViewProperty(true, false); 9486 info.mRotation = rotation; 9487 info.mMatrixDirty = true; 9488 invalidateViewProperty(false, true); 9489 if (mDisplayList != null) { 9490 mDisplayList.setRotation(rotation); 9491 } 9492 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9493 // View was rejected last time it was drawn by its parent; this may have changed 9494 invalidateParentIfNeeded(); 9495 } 9496 } 9497 } 9498 9499 /** 9500 * The degrees that the view is rotated around the vertical axis through the pivot point. 9501 * 9502 * @see #getPivotX() 9503 * @see #getPivotY() 9504 * @see #setRotationY(float) 9505 * 9506 * @return The degrees of Y rotation. 9507 */ 9508 @ViewDebug.ExportedProperty(category = "drawing") 9509 public float getRotationY() { 9510 return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0; 9511 } 9512 9513 /** 9514 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 9515 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 9516 * down the y axis. 9517 * 9518 * When rotating large views, it is recommended to adjust the camera distance 9519 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 9520 * 9521 * @param rotationY The degrees of Y rotation. 9522 * 9523 * @see #getRotationY() 9524 * @see #getPivotX() 9525 * @see #getPivotY() 9526 * @see #setRotation(float) 9527 * @see #setRotationX(float) 9528 * @see #setCameraDistance(float) 9529 * 9530 * @attr ref android.R.styleable#View_rotationY 9531 */ 9532 public void setRotationY(float rotationY) { 9533 ensureTransformationInfo(); 9534 final TransformationInfo info = mTransformationInfo; 9535 if (info.mRotationY != rotationY) { 9536 invalidateViewProperty(true, false); 9537 info.mRotationY = rotationY; 9538 info.mMatrixDirty = true; 9539 invalidateViewProperty(false, true); 9540 if (mDisplayList != null) { 9541 mDisplayList.setRotationY(rotationY); 9542 } 9543 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9544 // View was rejected last time it was drawn by its parent; this may have changed 9545 invalidateParentIfNeeded(); 9546 } 9547 } 9548 } 9549 9550 /** 9551 * The degrees that the view is rotated around the horizontal axis through the pivot point. 9552 * 9553 * @see #getPivotX() 9554 * @see #getPivotY() 9555 * @see #setRotationX(float) 9556 * 9557 * @return The degrees of X rotation. 9558 */ 9559 @ViewDebug.ExportedProperty(category = "drawing") 9560 public float getRotationX() { 9561 return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0; 9562 } 9563 9564 /** 9565 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 9566 * Increasing values result in clockwise rotation from the viewpoint of looking down the 9567 * x axis. 9568 * 9569 * When rotating large views, it is recommended to adjust the camera distance 9570 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 9571 * 9572 * @param rotationX The degrees of X rotation. 9573 * 9574 * @see #getRotationX() 9575 * @see #getPivotX() 9576 * @see #getPivotY() 9577 * @see #setRotation(float) 9578 * @see #setRotationY(float) 9579 * @see #setCameraDistance(float) 9580 * 9581 * @attr ref android.R.styleable#View_rotationX 9582 */ 9583 public void setRotationX(float rotationX) { 9584 ensureTransformationInfo(); 9585 final TransformationInfo info = mTransformationInfo; 9586 if (info.mRotationX != rotationX) { 9587 invalidateViewProperty(true, false); 9588 info.mRotationX = rotationX; 9589 info.mMatrixDirty = true; 9590 invalidateViewProperty(false, true); 9591 if (mDisplayList != null) { 9592 mDisplayList.setRotationX(rotationX); 9593 } 9594 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9595 // View was rejected last time it was drawn by its parent; this may have changed 9596 invalidateParentIfNeeded(); 9597 } 9598 } 9599 } 9600 9601 /** 9602 * The amount that the view is scaled in x around the pivot point, as a proportion of 9603 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 9604 * 9605 * <p>By default, this is 1.0f. 9606 * 9607 * @see #getPivotX() 9608 * @see #getPivotY() 9609 * @return The scaling factor. 9610 */ 9611 @ViewDebug.ExportedProperty(category = "drawing") 9612 public float getScaleX() { 9613 return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1; 9614 } 9615 9616 /** 9617 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 9618 * the view's unscaled width. A value of 1 means that no scaling is applied. 9619 * 9620 * @param scaleX The scaling factor. 9621 * @see #getPivotX() 9622 * @see #getPivotY() 9623 * 9624 * @attr ref android.R.styleable#View_scaleX 9625 */ 9626 public void setScaleX(float scaleX) { 9627 ensureTransformationInfo(); 9628 final TransformationInfo info = mTransformationInfo; 9629 if (info.mScaleX != scaleX) { 9630 invalidateViewProperty(true, false); 9631 info.mScaleX = scaleX; 9632 info.mMatrixDirty = true; 9633 invalidateViewProperty(false, true); 9634 if (mDisplayList != null) { 9635 mDisplayList.setScaleX(scaleX); 9636 } 9637 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9638 // View was rejected last time it was drawn by its parent; this may have changed 9639 invalidateParentIfNeeded(); 9640 } 9641 } 9642 } 9643 9644 /** 9645 * The amount that the view is scaled in y around the pivot point, as a proportion of 9646 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 9647 * 9648 * <p>By default, this is 1.0f. 9649 * 9650 * @see #getPivotX() 9651 * @see #getPivotY() 9652 * @return The scaling factor. 9653 */ 9654 @ViewDebug.ExportedProperty(category = "drawing") 9655 public float getScaleY() { 9656 return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1; 9657 } 9658 9659 /** 9660 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 9661 * the view's unscaled width. A value of 1 means that no scaling is applied. 9662 * 9663 * @param scaleY The scaling factor. 9664 * @see #getPivotX() 9665 * @see #getPivotY() 9666 * 9667 * @attr ref android.R.styleable#View_scaleY 9668 */ 9669 public void setScaleY(float scaleY) { 9670 ensureTransformationInfo(); 9671 final TransformationInfo info = mTransformationInfo; 9672 if (info.mScaleY != scaleY) { 9673 invalidateViewProperty(true, false); 9674 info.mScaleY = scaleY; 9675 info.mMatrixDirty = true; 9676 invalidateViewProperty(false, true); 9677 if (mDisplayList != null) { 9678 mDisplayList.setScaleY(scaleY); 9679 } 9680 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9681 // View was rejected last time it was drawn by its parent; this may have changed 9682 invalidateParentIfNeeded(); 9683 } 9684 } 9685 } 9686 9687 /** 9688 * The x location of the point around which the view is {@link #setRotation(float) rotated} 9689 * and {@link #setScaleX(float) scaled}. 9690 * 9691 * @see #getRotation() 9692 * @see #getScaleX() 9693 * @see #getScaleY() 9694 * @see #getPivotY() 9695 * @return The x location of the pivot point. 9696 * 9697 * @attr ref android.R.styleable#View_transformPivotX 9698 */ 9699 @ViewDebug.ExportedProperty(category = "drawing") 9700 public float getPivotX() { 9701 return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0; 9702 } 9703 9704 /** 9705 * Sets the x location of the point around which the view is 9706 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 9707 * By default, the pivot point is centered on the object. 9708 * Setting this property disables this behavior and causes the view to use only the 9709 * explicitly set pivotX and pivotY values. 9710 * 9711 * @param pivotX The x location of the pivot point. 9712 * @see #getRotation() 9713 * @see #getScaleX() 9714 * @see #getScaleY() 9715 * @see #getPivotY() 9716 * 9717 * @attr ref android.R.styleable#View_transformPivotX 9718 */ 9719 public void setPivotX(float pivotX) { 9720 ensureTransformationInfo(); 9721 final TransformationInfo info = mTransformationInfo; 9722 boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 9723 PFLAG_PIVOT_EXPLICITLY_SET; 9724 if (info.mPivotX != pivotX || !pivotSet) { 9725 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET; 9726 invalidateViewProperty(true, false); 9727 info.mPivotX = pivotX; 9728 info.mMatrixDirty = true; 9729 invalidateViewProperty(false, true); 9730 if (mDisplayList != null) { 9731 mDisplayList.setPivotX(pivotX); 9732 } 9733 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9734 // View was rejected last time it was drawn by its parent; this may have changed 9735 invalidateParentIfNeeded(); 9736 } 9737 } 9738 } 9739 9740 /** 9741 * The y location of the point around which the view is {@link #setRotation(float) rotated} 9742 * and {@link #setScaleY(float) scaled}. 9743 * 9744 * @see #getRotation() 9745 * @see #getScaleX() 9746 * @see #getScaleY() 9747 * @see #getPivotY() 9748 * @return The y location of the pivot point. 9749 * 9750 * @attr ref android.R.styleable#View_transformPivotY 9751 */ 9752 @ViewDebug.ExportedProperty(category = "drawing") 9753 public float getPivotY() { 9754 return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0; 9755 } 9756 9757 /** 9758 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 9759 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 9760 * Setting this property disables this behavior and causes the view to use only the 9761 * explicitly set pivotX and pivotY values. 9762 * 9763 * @param pivotY The y location of the pivot point. 9764 * @see #getRotation() 9765 * @see #getScaleX() 9766 * @see #getScaleY() 9767 * @see #getPivotY() 9768 * 9769 * @attr ref android.R.styleable#View_transformPivotY 9770 */ 9771 public void setPivotY(float pivotY) { 9772 ensureTransformationInfo(); 9773 final TransformationInfo info = mTransformationInfo; 9774 boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 9775 PFLAG_PIVOT_EXPLICITLY_SET; 9776 if (info.mPivotY != pivotY || !pivotSet) { 9777 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET; 9778 invalidateViewProperty(true, false); 9779 info.mPivotY = pivotY; 9780 info.mMatrixDirty = true; 9781 invalidateViewProperty(false, true); 9782 if (mDisplayList != null) { 9783 mDisplayList.setPivotY(pivotY); 9784 } 9785 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 9786 // View was rejected last time it was drawn by its parent; this may have changed 9787 invalidateParentIfNeeded(); 9788 } 9789 } 9790 } 9791 9792 /** 9793 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 9794 * completely transparent and 1 means the view is completely opaque. 9795 * 9796 * <p>By default this is 1.0f. 9797 * @return The opacity of the view. 9798 */ 9799 @ViewDebug.ExportedProperty(category = "drawing") 9800 public float getAlpha() { 9801 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 9802 } 9803 9804 /** 9805 * Returns whether this View has content which overlaps. 9806 * 9807 * <p>This function, intended to be overridden by specific View types, is an optimization when 9808 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 9809 * an offscreen buffer and then composited into place, which can be expensive. If the view has 9810 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 9811 * directly. An example of overlapping rendering is a TextView with a background image, such as 9812 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 9813 * ImageView with only the foreground image. The default implementation returns true; subclasses 9814 * should override if they have cases which can be optimized.</p> 9815 * 9816 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas} 9817 * necessitates that a View return true if it uses the methods internally without passing the 9818 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p> 9819 * 9820 * @return true if the content in this view might overlap, false otherwise. 9821 */ 9822 public boolean hasOverlappingRendering() { 9823 return true; 9824 } 9825 9826 /** 9827 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is 9828 * completely transparent and 1 means the view is completely opaque.</p> 9829 * 9830 * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant 9831 * performance implications, especially for large views. It is best to use the alpha property 9832 * sparingly and transiently, as in the case of fading animations.</p> 9833 * 9834 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 9835 * strongly recommended for performance reasons to either override 9836 * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a 9837 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p> 9838 * 9839 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 9840 * responsible for applying the opacity itself.</p> 9841 * 9842 * <p>Note that if the view is backed by a 9843 * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a 9844 * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than 9845 * 1.0 will supercede the alpha of the layer paint.</p> 9846 * 9847 * @param alpha The opacity of the view. 9848 * 9849 * @see #hasOverlappingRendering() 9850 * @see #setLayerType(int, android.graphics.Paint) 9851 * 9852 * @attr ref android.R.styleable#View_alpha 9853 */ 9854 public void setAlpha(float alpha) { 9855 ensureTransformationInfo(); 9856 if (mTransformationInfo.mAlpha != alpha) { 9857 mTransformationInfo.mAlpha = alpha; 9858 if (onSetAlpha((int) (alpha * 255))) { 9859 mPrivateFlags |= PFLAG_ALPHA_SET; 9860 // subclass is handling alpha - don't optimize rendering cache invalidation 9861 invalidateParentCaches(); 9862 invalidate(true); 9863 } else { 9864 mPrivateFlags &= ~PFLAG_ALPHA_SET; 9865 invalidateViewProperty(true, false); 9866 if (mDisplayList != null) { 9867 mDisplayList.setAlpha(getFinalAlpha()); 9868 } 9869 } 9870 } 9871 } 9872 9873 /** 9874 * Faster version of setAlpha() which performs the same steps except there are 9875 * no calls to invalidate(). The caller of this function should perform proper invalidation 9876 * on the parent and this object. The return value indicates whether the subclass handles 9877 * alpha (the return value for onSetAlpha()). 9878 * 9879 * @param alpha The new value for the alpha property 9880 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 9881 * the new value for the alpha property is different from the old value 9882 */ 9883 boolean setAlphaNoInvalidation(float alpha) { 9884 ensureTransformationInfo(); 9885 if (mTransformationInfo.mAlpha != alpha) { 9886 mTransformationInfo.mAlpha = alpha; 9887 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 9888 if (subclassHandlesAlpha) { 9889 mPrivateFlags |= PFLAG_ALPHA_SET; 9890 return true; 9891 } else { 9892 mPrivateFlags &= ~PFLAG_ALPHA_SET; 9893 if (mDisplayList != null) { 9894 mDisplayList.setAlpha(getFinalAlpha()); 9895 } 9896 } 9897 } 9898 return false; 9899 } 9900 9901 /** 9902 * This property is hidden and intended only for use by the Fade transition, which 9903 * animates it to produce a visual translucency that does not side-effect (or get 9904 * affected by) the real alpha property. This value is composited with the other 9905 * alpha value (and the AlphaAnimation value, when that is present) to produce 9906 * a final visual translucency result, which is what is passed into the DisplayList. 9907 * 9908 * @hide 9909 */ 9910 public void setTransitionAlpha(float alpha) { 9911 ensureTransformationInfo(); 9912 if (mTransformationInfo.mTransitionAlpha != alpha) { 9913 mTransformationInfo.mTransitionAlpha = alpha; 9914 mPrivateFlags &= ~PFLAG_ALPHA_SET; 9915 invalidateViewProperty(true, false); 9916 if (mDisplayList != null) { 9917 mDisplayList.setAlpha(getFinalAlpha()); 9918 } 9919 } 9920 } 9921 9922 /** 9923 * Calculates the visual alpha of this view, which is a combination of the actual 9924 * alpha value and the transitionAlpha value (if set). 9925 */ 9926 private float getFinalAlpha() { 9927 if (mTransformationInfo != null) { 9928 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 9929 } 9930 return 1; 9931 } 9932 9933 /** 9934 * This property is hidden and intended only for use by the Fade transition, which 9935 * animates it to produce a visual translucency that does not side-effect (or get 9936 * affected by) the real alpha property. This value is composited with the other 9937 * alpha value (and the AlphaAnimation value, when that is present) to produce 9938 * a final visual translucency result, which is what is passed into the DisplayList. 9939 * 9940 * @hide 9941 */ 9942 public float getTransitionAlpha() { 9943 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 9944 } 9945 9946 /** 9947 * Top position of this view relative to its parent. 9948 * 9949 * @return The top of this view, in pixels. 9950 */ 9951 @ViewDebug.CapturedViewProperty 9952 public final int getTop() { 9953 return mTop; 9954 } 9955 9956 /** 9957 * Sets the top position of this view relative to its parent. This method is meant to be called 9958 * by the layout system and should not generally be called otherwise, because the property 9959 * may be changed at any time by the layout. 9960 * 9961 * @param top The top of this view, in pixels. 9962 */ 9963 public final void setTop(int top) { 9964 if (top != mTop) { 9965 updateMatrix(); 9966 final boolean matrixIsIdentity = mTransformationInfo == null 9967 || mTransformationInfo.mMatrixIsIdentity; 9968 if (matrixIsIdentity) { 9969 if (mAttachInfo != null) { 9970 int minTop; 9971 int yLoc; 9972 if (top < mTop) { 9973 minTop = top; 9974 yLoc = top - mTop; 9975 } else { 9976 minTop = mTop; 9977 yLoc = 0; 9978 } 9979 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 9980 } 9981 } else { 9982 // Double-invalidation is necessary to capture view's old and new areas 9983 invalidate(true); 9984 } 9985 9986 int width = mRight - mLeft; 9987 int oldHeight = mBottom - mTop; 9988 9989 mTop = top; 9990 if (mDisplayList != null) { 9991 mDisplayList.setTop(mTop); 9992 } 9993 9994 sizeChange(width, mBottom - mTop, width, oldHeight); 9995 9996 if (!matrixIsIdentity) { 9997 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 9998 // A change in dimension means an auto-centered pivot point changes, too 9999 mTransformationInfo.mMatrixDirty = true; 10000 } 10001 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10002 invalidate(true); 10003 } 10004 mBackgroundSizeChanged = true; 10005 invalidateParentIfNeeded(); 10006 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10007 // View was rejected last time it was drawn by its parent; this may have changed 10008 invalidateParentIfNeeded(); 10009 } 10010 } 10011 } 10012 10013 /** 10014 * Bottom position of this view relative to its parent. 10015 * 10016 * @return The bottom of this view, in pixels. 10017 */ 10018 @ViewDebug.CapturedViewProperty 10019 public final int getBottom() { 10020 return mBottom; 10021 } 10022 10023 /** 10024 * True if this view has changed since the last time being drawn. 10025 * 10026 * @return The dirty state of this view. 10027 */ 10028 public boolean isDirty() { 10029 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 10030 } 10031 10032 /** 10033 * Sets the bottom position of this view relative to its parent. This method is meant to be 10034 * called by the layout system and should not generally be called otherwise, because the 10035 * property may be changed at any time by the layout. 10036 * 10037 * @param bottom The bottom of this view, in pixels. 10038 */ 10039 public final void setBottom(int bottom) { 10040 if (bottom != mBottom) { 10041 updateMatrix(); 10042 final boolean matrixIsIdentity = mTransformationInfo == null 10043 || mTransformationInfo.mMatrixIsIdentity; 10044 if (matrixIsIdentity) { 10045 if (mAttachInfo != null) { 10046 int maxBottom; 10047 if (bottom < mBottom) { 10048 maxBottom = mBottom; 10049 } else { 10050 maxBottom = bottom; 10051 } 10052 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 10053 } 10054 } else { 10055 // Double-invalidation is necessary to capture view's old and new areas 10056 invalidate(true); 10057 } 10058 10059 int width = mRight - mLeft; 10060 int oldHeight = mBottom - mTop; 10061 10062 mBottom = bottom; 10063 if (mDisplayList != null) { 10064 mDisplayList.setBottom(mBottom); 10065 } 10066 10067 sizeChange(width, mBottom - mTop, width, oldHeight); 10068 10069 if (!matrixIsIdentity) { 10070 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 10071 // A change in dimension means an auto-centered pivot point changes, too 10072 mTransformationInfo.mMatrixDirty = true; 10073 } 10074 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10075 invalidate(true); 10076 } 10077 mBackgroundSizeChanged = true; 10078 invalidateParentIfNeeded(); 10079 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10080 // View was rejected last time it was drawn by its parent; this may have changed 10081 invalidateParentIfNeeded(); 10082 } 10083 } 10084 } 10085 10086 /** 10087 * Left position of this view relative to its parent. 10088 * 10089 * @return The left edge of this view, in pixels. 10090 */ 10091 @ViewDebug.CapturedViewProperty 10092 public final int getLeft() { 10093 return mLeft; 10094 } 10095 10096 /** 10097 * Sets the left position of this view relative to its parent. This method is meant to be called 10098 * by the layout system and should not generally be called otherwise, because the property 10099 * may be changed at any time by the layout. 10100 * 10101 * @param left The bottom of this view, in pixels. 10102 */ 10103 public final void setLeft(int left) { 10104 if (left != mLeft) { 10105 updateMatrix(); 10106 final boolean matrixIsIdentity = mTransformationInfo == null 10107 || mTransformationInfo.mMatrixIsIdentity; 10108 if (matrixIsIdentity) { 10109 if (mAttachInfo != null) { 10110 int minLeft; 10111 int xLoc; 10112 if (left < mLeft) { 10113 minLeft = left; 10114 xLoc = left - mLeft; 10115 } else { 10116 minLeft = mLeft; 10117 xLoc = 0; 10118 } 10119 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 10120 } 10121 } else { 10122 // Double-invalidation is necessary to capture view's old and new areas 10123 invalidate(true); 10124 } 10125 10126 int oldWidth = mRight - mLeft; 10127 int height = mBottom - mTop; 10128 10129 mLeft = left; 10130 if (mDisplayList != null) { 10131 mDisplayList.setLeft(left); 10132 } 10133 10134 sizeChange(mRight - mLeft, height, oldWidth, height); 10135 10136 if (!matrixIsIdentity) { 10137 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 10138 // A change in dimension means an auto-centered pivot point changes, too 10139 mTransformationInfo.mMatrixDirty = true; 10140 } 10141 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10142 invalidate(true); 10143 } 10144 mBackgroundSizeChanged = true; 10145 invalidateParentIfNeeded(); 10146 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10147 // View was rejected last time it was drawn by its parent; this may have changed 10148 invalidateParentIfNeeded(); 10149 } 10150 } 10151 } 10152 10153 /** 10154 * Right position of this view relative to its parent. 10155 * 10156 * @return The right edge of this view, in pixels. 10157 */ 10158 @ViewDebug.CapturedViewProperty 10159 public final int getRight() { 10160 return mRight; 10161 } 10162 10163 /** 10164 * Sets the right position of this view relative to its parent. This method is meant to be called 10165 * by the layout system and should not generally be called otherwise, because the property 10166 * may be changed at any time by the layout. 10167 * 10168 * @param right The bottom of this view, in pixels. 10169 */ 10170 public final void setRight(int right) { 10171 if (right != mRight) { 10172 updateMatrix(); 10173 final boolean matrixIsIdentity = mTransformationInfo == null 10174 || mTransformationInfo.mMatrixIsIdentity; 10175 if (matrixIsIdentity) { 10176 if (mAttachInfo != null) { 10177 int maxRight; 10178 if (right < mRight) { 10179 maxRight = mRight; 10180 } else { 10181 maxRight = right; 10182 } 10183 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 10184 } 10185 } else { 10186 // Double-invalidation is necessary to capture view's old and new areas 10187 invalidate(true); 10188 } 10189 10190 int oldWidth = mRight - mLeft; 10191 int height = mBottom - mTop; 10192 10193 mRight = right; 10194 if (mDisplayList != null) { 10195 mDisplayList.setRight(mRight); 10196 } 10197 10198 sizeChange(mRight - mLeft, height, oldWidth, height); 10199 10200 if (!matrixIsIdentity) { 10201 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 10202 // A change in dimension means an auto-centered pivot point changes, too 10203 mTransformationInfo.mMatrixDirty = true; 10204 } 10205 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10206 invalidate(true); 10207 } 10208 mBackgroundSizeChanged = true; 10209 invalidateParentIfNeeded(); 10210 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10211 // View was rejected last time it was drawn by its parent; this may have changed 10212 invalidateParentIfNeeded(); 10213 } 10214 } 10215 } 10216 10217 /** 10218 * The visual x position of this view, in pixels. This is equivalent to the 10219 * {@link #setTranslationX(float) translationX} property plus the current 10220 * {@link #getLeft() left} property. 10221 * 10222 * @return The visual x position of this view, in pixels. 10223 */ 10224 @ViewDebug.ExportedProperty(category = "drawing") 10225 public float getX() { 10226 return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0); 10227 } 10228 10229 /** 10230 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 10231 * {@link #setTranslationX(float) translationX} property to be the difference between 10232 * the x value passed in and the current {@link #getLeft() left} property. 10233 * 10234 * @param x The visual x position of this view, in pixels. 10235 */ 10236 public void setX(float x) { 10237 setTranslationX(x - mLeft); 10238 } 10239 10240 /** 10241 * The visual y position of this view, in pixels. This is equivalent to the 10242 * {@link #setTranslationY(float) translationY} property plus the current 10243 * {@link #getTop() top} property. 10244 * 10245 * @return The visual y position of this view, in pixels. 10246 */ 10247 @ViewDebug.ExportedProperty(category = "drawing") 10248 public float getY() { 10249 return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0); 10250 } 10251 10252 /** 10253 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 10254 * {@link #setTranslationY(float) translationY} property to be the difference between 10255 * the y value passed in and the current {@link #getTop() top} property. 10256 * 10257 * @param y The visual y position of this view, in pixels. 10258 */ 10259 public void setY(float y) { 10260 setTranslationY(y - mTop); 10261 } 10262 10263 10264 /** 10265 * The horizontal location of this view relative to its {@link #getLeft() left} position. 10266 * This position is post-layout, in addition to wherever the object's 10267 * layout placed it. 10268 * 10269 * @return The horizontal position of this view relative to its left position, in pixels. 10270 */ 10271 @ViewDebug.ExportedProperty(category = "drawing") 10272 public float getTranslationX() { 10273 return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0; 10274 } 10275 10276 /** 10277 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 10278 * This effectively positions the object post-layout, in addition to wherever the object's 10279 * layout placed it. 10280 * 10281 * @param translationX The horizontal position of this view relative to its left position, 10282 * in pixels. 10283 * 10284 * @attr ref android.R.styleable#View_translationX 10285 */ 10286 public void setTranslationX(float translationX) { 10287 ensureTransformationInfo(); 10288 final TransformationInfo info = mTransformationInfo; 10289 if (info.mTranslationX != translationX) { 10290 // Double-invalidation is necessary to capture view's old and new areas 10291 invalidateViewProperty(true, false); 10292 info.mTranslationX = translationX; 10293 info.mMatrixDirty = true; 10294 invalidateViewProperty(false, true); 10295 if (mDisplayList != null) { 10296 mDisplayList.setTranslationX(translationX); 10297 } 10298 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10299 // View was rejected last time it was drawn by its parent; this may have changed 10300 invalidateParentIfNeeded(); 10301 } 10302 } 10303 } 10304 10305 /** 10306 * The horizontal location of this view relative to its {@link #getTop() top} position. 10307 * This position is post-layout, in addition to wherever the object's 10308 * layout placed it. 10309 * 10310 * @return The vertical position of this view relative to its top position, 10311 * in pixels. 10312 */ 10313 @ViewDebug.ExportedProperty(category = "drawing") 10314 public float getTranslationY() { 10315 return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0; 10316 } 10317 10318 /** 10319 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 10320 * This effectively positions the object post-layout, in addition to wherever the object's 10321 * layout placed it. 10322 * 10323 * @param translationY The vertical position of this view relative to its top position, 10324 * in pixels. 10325 * 10326 * @attr ref android.R.styleable#View_translationY 10327 */ 10328 public void setTranslationY(float translationY) { 10329 ensureTransformationInfo(); 10330 final TransformationInfo info = mTransformationInfo; 10331 if (info.mTranslationY != translationY) { 10332 invalidateViewProperty(true, false); 10333 info.mTranslationY = translationY; 10334 info.mMatrixDirty = true; 10335 invalidateViewProperty(false, true); 10336 if (mDisplayList != null) { 10337 mDisplayList.setTranslationY(translationY); 10338 } 10339 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10340 // View was rejected last time it was drawn by its parent; this may have changed 10341 invalidateParentIfNeeded(); 10342 } 10343 } 10344 } 10345 10346 /** 10347 * Hit rectangle in parent's coordinates 10348 * 10349 * @param outRect The hit rectangle of the view. 10350 */ 10351 public void getHitRect(Rect outRect) { 10352 updateMatrix(); 10353 final TransformationInfo info = mTransformationInfo; 10354 if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) { 10355 outRect.set(mLeft, mTop, mRight, mBottom); 10356 } else { 10357 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 10358 tmpRect.set(0, 0, getWidth(), getHeight()); 10359 info.mMatrix.mapRect(tmpRect); 10360 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 10361 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 10362 } 10363 } 10364 10365 /** 10366 * Determines whether the given point, in local coordinates is inside the view. 10367 */ 10368 /*package*/ final boolean pointInView(float localX, float localY) { 10369 return localX >= 0 && localX < (mRight - mLeft) 10370 && localY >= 0 && localY < (mBottom - mTop); 10371 } 10372 10373 /** 10374 * Utility method to determine whether the given point, in local coordinates, 10375 * is inside the view, where the area of the view is expanded by the slop factor. 10376 * This method is called while processing touch-move events to determine if the event 10377 * is still within the view. 10378 * 10379 * @hide 10380 */ 10381 public boolean pointInView(float localX, float localY, float slop) { 10382 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 10383 localY < ((mBottom - mTop) + slop); 10384 } 10385 10386 /** 10387 * When a view has focus and the user navigates away from it, the next view is searched for 10388 * starting from the rectangle filled in by this method. 10389 * 10390 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 10391 * of the view. However, if your view maintains some idea of internal selection, 10392 * such as a cursor, or a selected row or column, you should override this method and 10393 * fill in a more specific rectangle. 10394 * 10395 * @param r The rectangle to fill in, in this view's coordinates. 10396 */ 10397 public void getFocusedRect(Rect r) { 10398 getDrawingRect(r); 10399 } 10400 10401 /** 10402 * If some part of this view is not clipped by any of its parents, then 10403 * return that area in r in global (root) coordinates. To convert r to local 10404 * coordinates (without taking possible View rotations into account), offset 10405 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 10406 * If the view is completely clipped or translated out, return false. 10407 * 10408 * @param r If true is returned, r holds the global coordinates of the 10409 * visible portion of this view. 10410 * @param globalOffset If true is returned, globalOffset holds the dx,dy 10411 * between this view and its root. globalOffet may be null. 10412 * @return true if r is non-empty (i.e. part of the view is visible at the 10413 * root level. 10414 */ 10415 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 10416 int width = mRight - mLeft; 10417 int height = mBottom - mTop; 10418 if (width > 0 && height > 0) { 10419 r.set(0, 0, width, height); 10420 if (globalOffset != null) { 10421 globalOffset.set(-mScrollX, -mScrollY); 10422 } 10423 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 10424 } 10425 return false; 10426 } 10427 10428 public final boolean getGlobalVisibleRect(Rect r) { 10429 return getGlobalVisibleRect(r, null); 10430 } 10431 10432 public final boolean getLocalVisibleRect(Rect r) { 10433 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 10434 if (getGlobalVisibleRect(r, offset)) { 10435 r.offset(-offset.x, -offset.y); // make r local 10436 return true; 10437 } 10438 return false; 10439 } 10440 10441 /** 10442 * Offset this view's vertical location by the specified number of pixels. 10443 * 10444 * @param offset the number of pixels to offset the view by 10445 */ 10446 public void offsetTopAndBottom(int offset) { 10447 if (offset != 0) { 10448 updateMatrix(); 10449 final boolean matrixIsIdentity = mTransformationInfo == null 10450 || mTransformationInfo.mMatrixIsIdentity; 10451 if (matrixIsIdentity) { 10452 if (mDisplayList != null) { 10453 invalidateViewProperty(false, false); 10454 } else { 10455 final ViewParent p = mParent; 10456 if (p != null && mAttachInfo != null) { 10457 final Rect r = mAttachInfo.mTmpInvalRect; 10458 int minTop; 10459 int maxBottom; 10460 int yLoc; 10461 if (offset < 0) { 10462 minTop = mTop + offset; 10463 maxBottom = mBottom; 10464 yLoc = offset; 10465 } else { 10466 minTop = mTop; 10467 maxBottom = mBottom + offset; 10468 yLoc = 0; 10469 } 10470 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 10471 p.invalidateChild(this, r); 10472 } 10473 } 10474 } else { 10475 invalidateViewProperty(false, false); 10476 } 10477 10478 mTop += offset; 10479 mBottom += offset; 10480 if (mDisplayList != null) { 10481 mDisplayList.offsetTopAndBottom(offset); 10482 invalidateViewProperty(false, false); 10483 } else { 10484 if (!matrixIsIdentity) { 10485 invalidateViewProperty(false, true); 10486 } 10487 invalidateParentIfNeeded(); 10488 } 10489 } 10490 } 10491 10492 /** 10493 * Offset this view's horizontal location by the specified amount of pixels. 10494 * 10495 * @param offset the number of pixels to offset the view by 10496 */ 10497 public void offsetLeftAndRight(int offset) { 10498 if (offset != 0) { 10499 updateMatrix(); 10500 final boolean matrixIsIdentity = mTransformationInfo == null 10501 || mTransformationInfo.mMatrixIsIdentity; 10502 if (matrixIsIdentity) { 10503 if (mDisplayList != null) { 10504 invalidateViewProperty(false, false); 10505 } else { 10506 final ViewParent p = mParent; 10507 if (p != null && mAttachInfo != null) { 10508 final Rect r = mAttachInfo.mTmpInvalRect; 10509 int minLeft; 10510 int maxRight; 10511 if (offset < 0) { 10512 minLeft = mLeft + offset; 10513 maxRight = mRight; 10514 } else { 10515 minLeft = mLeft; 10516 maxRight = mRight + offset; 10517 } 10518 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 10519 p.invalidateChild(this, r); 10520 } 10521 } 10522 } else { 10523 invalidateViewProperty(false, false); 10524 } 10525 10526 mLeft += offset; 10527 mRight += offset; 10528 if (mDisplayList != null) { 10529 mDisplayList.offsetLeftAndRight(offset); 10530 invalidateViewProperty(false, false); 10531 } else { 10532 if (!matrixIsIdentity) { 10533 invalidateViewProperty(false, true); 10534 } 10535 invalidateParentIfNeeded(); 10536 } 10537 } 10538 } 10539 10540 /** 10541 * Get the LayoutParams associated with this view. All views should have 10542 * layout parameters. These supply parameters to the <i>parent</i> of this 10543 * view specifying how it should be arranged. There are many subclasses of 10544 * ViewGroup.LayoutParams, and these correspond to the different subclasses 10545 * of ViewGroup that are responsible for arranging their children. 10546 * 10547 * This method may return null if this View is not attached to a parent 10548 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 10549 * was not invoked successfully. When a View is attached to a parent 10550 * ViewGroup, this method must not return null. 10551 * 10552 * @return The LayoutParams associated with this view, or null if no 10553 * parameters have been set yet 10554 */ 10555 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 10556 public ViewGroup.LayoutParams getLayoutParams() { 10557 return mLayoutParams; 10558 } 10559 10560 /** 10561 * Set the layout parameters associated with this view. These supply 10562 * parameters to the <i>parent</i> of this view specifying how it should be 10563 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 10564 * correspond to the different subclasses of ViewGroup that are responsible 10565 * for arranging their children. 10566 * 10567 * @param params The layout parameters for this view, cannot be null 10568 */ 10569 public void setLayoutParams(ViewGroup.LayoutParams params) { 10570 if (params == null) { 10571 throw new NullPointerException("Layout parameters cannot be null"); 10572 } 10573 mLayoutParams = params; 10574 resolveLayoutParams(); 10575 if (mParent instanceof ViewGroup) { 10576 ((ViewGroup) mParent).onSetLayoutParams(this, params); 10577 } 10578 requestLayout(); 10579 } 10580 10581 /** 10582 * Resolve the layout parameters depending on the resolved layout direction 10583 * 10584 * @hide 10585 */ 10586 public void resolveLayoutParams() { 10587 if (mLayoutParams != null) { 10588 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 10589 } 10590 } 10591 10592 /** 10593 * Set the scrolled position of your view. This will cause a call to 10594 * {@link #onScrollChanged(int, int, int, int)} and the view will be 10595 * invalidated. 10596 * @param x the x position to scroll to 10597 * @param y the y position to scroll to 10598 */ 10599 public void scrollTo(int x, int y) { 10600 if (mScrollX != x || mScrollY != y) { 10601 int oldX = mScrollX; 10602 int oldY = mScrollY; 10603 mScrollX = x; 10604 mScrollY = y; 10605 invalidateParentCaches(); 10606 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 10607 if (!awakenScrollBars()) { 10608 postInvalidateOnAnimation(); 10609 } 10610 } 10611 } 10612 10613 /** 10614 * Move the scrolled position of your view. This will cause a call to 10615 * {@link #onScrollChanged(int, int, int, int)} and the view will be 10616 * invalidated. 10617 * @param x the amount of pixels to scroll by horizontally 10618 * @param y the amount of pixels to scroll by vertically 10619 */ 10620 public void scrollBy(int x, int y) { 10621 scrollTo(mScrollX + x, mScrollY + y); 10622 } 10623 10624 /** 10625 * <p>Trigger the scrollbars to draw. When invoked this method starts an 10626 * animation to fade the scrollbars out after a default delay. If a subclass 10627 * provides animated scrolling, the start delay should equal the duration 10628 * of the scrolling animation.</p> 10629 * 10630 * <p>The animation starts only if at least one of the scrollbars is 10631 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 10632 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10633 * this method returns true, and false otherwise. If the animation is 10634 * started, this method calls {@link #invalidate()}; in that case the 10635 * caller should not call {@link #invalidate()}.</p> 10636 * 10637 * <p>This method should be invoked every time a subclass directly updates 10638 * the scroll parameters.</p> 10639 * 10640 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 10641 * and {@link #scrollTo(int, int)}.</p> 10642 * 10643 * @return true if the animation is played, false otherwise 10644 * 10645 * @see #awakenScrollBars(int) 10646 * @see #scrollBy(int, int) 10647 * @see #scrollTo(int, int) 10648 * @see #isHorizontalScrollBarEnabled() 10649 * @see #isVerticalScrollBarEnabled() 10650 * @see #setHorizontalScrollBarEnabled(boolean) 10651 * @see #setVerticalScrollBarEnabled(boolean) 10652 */ 10653 protected boolean awakenScrollBars() { 10654 return mScrollCache != null && 10655 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 10656 } 10657 10658 /** 10659 * Trigger the scrollbars to draw. 10660 * This method differs from awakenScrollBars() only in its default duration. 10661 * initialAwakenScrollBars() will show the scroll bars for longer than 10662 * usual to give the user more of a chance to notice them. 10663 * 10664 * @return true if the animation is played, false otherwise. 10665 */ 10666 private boolean initialAwakenScrollBars() { 10667 return mScrollCache != null && 10668 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 10669 } 10670 10671 /** 10672 * <p> 10673 * Trigger the scrollbars to draw. When invoked this method starts an 10674 * animation to fade the scrollbars out after a fixed delay. If a subclass 10675 * provides animated scrolling, the start delay should equal the duration of 10676 * the scrolling animation. 10677 * </p> 10678 * 10679 * <p> 10680 * The animation starts only if at least one of the scrollbars is enabled, 10681 * as specified by {@link #isHorizontalScrollBarEnabled()} and 10682 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10683 * this method returns true, and false otherwise. If the animation is 10684 * started, this method calls {@link #invalidate()}; in that case the caller 10685 * should not call {@link #invalidate()}. 10686 * </p> 10687 * 10688 * <p> 10689 * This method should be invoked everytime a subclass directly updates the 10690 * scroll parameters. 10691 * </p> 10692 * 10693 * @param startDelay the delay, in milliseconds, after which the animation 10694 * should start; when the delay is 0, the animation starts 10695 * immediately 10696 * @return true if the animation is played, false otherwise 10697 * 10698 * @see #scrollBy(int, int) 10699 * @see #scrollTo(int, int) 10700 * @see #isHorizontalScrollBarEnabled() 10701 * @see #isVerticalScrollBarEnabled() 10702 * @see #setHorizontalScrollBarEnabled(boolean) 10703 * @see #setVerticalScrollBarEnabled(boolean) 10704 */ 10705 protected boolean awakenScrollBars(int startDelay) { 10706 return awakenScrollBars(startDelay, true); 10707 } 10708 10709 /** 10710 * <p> 10711 * Trigger the scrollbars to draw. When invoked this method starts an 10712 * animation to fade the scrollbars out after a fixed delay. If a subclass 10713 * provides animated scrolling, the start delay should equal the duration of 10714 * the scrolling animation. 10715 * </p> 10716 * 10717 * <p> 10718 * The animation starts only if at least one of the scrollbars is enabled, 10719 * as specified by {@link #isHorizontalScrollBarEnabled()} and 10720 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10721 * this method returns true, and false otherwise. If the animation is 10722 * started, this method calls {@link #invalidate()} if the invalidate parameter 10723 * is set to true; in that case the caller 10724 * should not call {@link #invalidate()}. 10725 * </p> 10726 * 10727 * <p> 10728 * This method should be invoked everytime a subclass directly updates the 10729 * scroll parameters. 10730 * </p> 10731 * 10732 * @param startDelay the delay, in milliseconds, after which the animation 10733 * should start; when the delay is 0, the animation starts 10734 * immediately 10735 * 10736 * @param invalidate Wheter this method should call invalidate 10737 * 10738 * @return true if the animation is played, false otherwise 10739 * 10740 * @see #scrollBy(int, int) 10741 * @see #scrollTo(int, int) 10742 * @see #isHorizontalScrollBarEnabled() 10743 * @see #isVerticalScrollBarEnabled() 10744 * @see #setHorizontalScrollBarEnabled(boolean) 10745 * @see #setVerticalScrollBarEnabled(boolean) 10746 */ 10747 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 10748 final ScrollabilityCache scrollCache = mScrollCache; 10749 10750 if (scrollCache == null || !scrollCache.fadeScrollBars) { 10751 return false; 10752 } 10753 10754 if (scrollCache.scrollBar == null) { 10755 scrollCache.scrollBar = new ScrollBarDrawable(); 10756 } 10757 10758 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 10759 10760 if (invalidate) { 10761 // Invalidate to show the scrollbars 10762 postInvalidateOnAnimation(); 10763 } 10764 10765 if (scrollCache.state == ScrollabilityCache.OFF) { 10766 // FIXME: this is copied from WindowManagerService. 10767 // We should get this value from the system when it 10768 // is possible to do so. 10769 final int KEY_REPEAT_FIRST_DELAY = 750; 10770 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 10771 } 10772 10773 // Tell mScrollCache when we should start fading. This may 10774 // extend the fade start time if one was already scheduled 10775 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 10776 scrollCache.fadeStartTime = fadeStartTime; 10777 scrollCache.state = ScrollabilityCache.ON; 10778 10779 // Schedule our fader to run, unscheduling any old ones first 10780 if (mAttachInfo != null) { 10781 mAttachInfo.mHandler.removeCallbacks(scrollCache); 10782 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 10783 } 10784 10785 return true; 10786 } 10787 10788 return false; 10789 } 10790 10791 /** 10792 * Do not invalidate views which are not visible and which are not running an animation. They 10793 * will not get drawn and they should not set dirty flags as if they will be drawn 10794 */ 10795 private boolean skipInvalidate() { 10796 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 10797 (!(mParent instanceof ViewGroup) || 10798 !((ViewGroup) mParent).isViewTransitioning(this)); 10799 } 10800 /** 10801 * Mark the area defined by dirty as needing to be drawn. If the view is 10802 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point 10803 * in the future. This must be called from a UI thread. To call from a non-UI 10804 * thread, call {@link #postInvalidate()}. 10805 * 10806 * WARNING: This method is destructive to dirty. 10807 * @param dirty the rectangle representing the bounds of the dirty region 10808 */ 10809 public void invalidate(Rect dirty) { 10810 if (skipInvalidate()) { 10811 return; 10812 } 10813 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || 10814 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID || 10815 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) { 10816 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 10817 mPrivateFlags |= PFLAG_INVALIDATED; 10818 mPrivateFlags |= PFLAG_DIRTY; 10819 final ViewParent p = mParent; 10820 final AttachInfo ai = mAttachInfo; 10821 //noinspection PointlessBooleanExpression,ConstantConditions 10822 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 10823 if (p != null && ai != null && ai.mHardwareAccelerated) { 10824 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 10825 // with a null dirty rect, which tells the ViewAncestor to redraw everything 10826 p.invalidateChild(this, null); 10827 return; 10828 } 10829 } 10830 if (p != null && ai != null) { 10831 final int scrollX = mScrollX; 10832 final int scrollY = mScrollY; 10833 final Rect r = ai.mTmpInvalRect; 10834 r.set(dirty.left - scrollX, dirty.top - scrollY, 10835 dirty.right - scrollX, dirty.bottom - scrollY); 10836 mParent.invalidateChild(this, r); 10837 } 10838 } 10839 } 10840 10841 /** 10842 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. 10843 * The coordinates of the dirty rect are relative to the view. 10844 * If the view is visible, {@link #onDraw(android.graphics.Canvas)} 10845 * will be called at some point in the future. This must be called from 10846 * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. 10847 * @param l the left position of the dirty region 10848 * @param t the top position of the dirty region 10849 * @param r the right position of the dirty region 10850 * @param b the bottom position of the dirty region 10851 */ 10852 public void invalidate(int l, int t, int r, int b) { 10853 if (skipInvalidate()) { 10854 return; 10855 } 10856 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || 10857 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID || 10858 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) { 10859 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 10860 mPrivateFlags |= PFLAG_INVALIDATED; 10861 mPrivateFlags |= PFLAG_DIRTY; 10862 final ViewParent p = mParent; 10863 final AttachInfo ai = mAttachInfo; 10864 //noinspection PointlessBooleanExpression,ConstantConditions 10865 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 10866 if (p != null && ai != null && ai.mHardwareAccelerated) { 10867 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 10868 // with a null dirty rect, which tells the ViewAncestor to redraw everything 10869 p.invalidateChild(this, null); 10870 return; 10871 } 10872 } 10873 if (p != null && ai != null && l < r && t < b) { 10874 final int scrollX = mScrollX; 10875 final int scrollY = mScrollY; 10876 final Rect tmpr = ai.mTmpInvalRect; 10877 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); 10878 p.invalidateChild(this, tmpr); 10879 } 10880 } 10881 } 10882 10883 /** 10884 * Invalidate the whole view. If the view is visible, 10885 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 10886 * the future. This must be called from a UI thread. To call from a non-UI thread, 10887 * call {@link #postInvalidate()}. 10888 */ 10889 public void invalidate() { 10890 invalidate(true); 10891 } 10892 10893 /** 10894 * This is where the invalidate() work actually happens. A full invalidate() 10895 * causes the drawing cache to be invalidated, but this function can be called with 10896 * invalidateCache set to false to skip that invalidation step for cases that do not 10897 * need it (for example, a component that remains at the same dimensions with the same 10898 * content). 10899 * 10900 * @param invalidateCache Whether the drawing cache for this view should be invalidated as 10901 * well. This is usually true for a full invalidate, but may be set to false if the 10902 * View's contents or dimensions have not changed. 10903 */ 10904 void invalidate(boolean invalidateCache) { 10905 if (skipInvalidate()) { 10906 return; 10907 } 10908 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) || 10909 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) || 10910 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) { 10911 mLastIsOpaque = isOpaque(); 10912 mPrivateFlags &= ~PFLAG_DRAWN; 10913 mPrivateFlags |= PFLAG_DIRTY; 10914 if (invalidateCache) { 10915 mPrivateFlags |= PFLAG_INVALIDATED; 10916 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 10917 } 10918 final AttachInfo ai = mAttachInfo; 10919 final ViewParent p = mParent; 10920 //noinspection PointlessBooleanExpression,ConstantConditions 10921 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 10922 if (p != null && ai != null && ai.mHardwareAccelerated) { 10923 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 10924 // with a null dirty rect, which tells the ViewAncestor to redraw everything 10925 p.invalidateChild(this, null); 10926 return; 10927 } 10928 } 10929 10930 if (p != null && ai != null) { 10931 final Rect r = ai.mTmpInvalRect; 10932 r.set(0, 0, mRight - mLeft, mBottom - mTop); 10933 // Don't call invalidate -- we don't want to internally scroll 10934 // our own bounds 10935 p.invalidateChild(this, r); 10936 } 10937 } 10938 } 10939 10940 /** 10941 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 10942 * set any flags or handle all of the cases handled by the default invalidation methods. 10943 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 10944 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 10945 * walk up the hierarchy, transforming the dirty rect as necessary. 10946 * 10947 * The method also handles normal invalidation logic if display list properties are not 10948 * being used in this view. The invalidateParent and forceRedraw flags are used by that 10949 * backup approach, to handle these cases used in the various property-setting methods. 10950 * 10951 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 10952 * are not being used in this view 10953 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 10954 * list properties are not being used in this view 10955 */ 10956 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 10957 if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) { 10958 if (invalidateParent) { 10959 invalidateParentCaches(); 10960 } 10961 if (forceRedraw) { 10962 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10963 } 10964 invalidate(false); 10965 } else { 10966 final AttachInfo ai = mAttachInfo; 10967 final ViewParent p = mParent; 10968 if (p != null && ai != null) { 10969 final Rect r = ai.mTmpInvalRect; 10970 r.set(0, 0, mRight - mLeft, mBottom - mTop); 10971 if (mParent instanceof ViewGroup) { 10972 ((ViewGroup) mParent).invalidateChildFast(this, r); 10973 } else { 10974 mParent.invalidateChild(this, r); 10975 } 10976 } 10977 } 10978 } 10979 10980 /** 10981 * Utility method to transform a given Rect by the current matrix of this view. 10982 */ 10983 void transformRect(final Rect rect) { 10984 if (!getMatrix().isIdentity()) { 10985 RectF boundingRect = mAttachInfo.mTmpTransformRect; 10986 boundingRect.set(rect); 10987 getMatrix().mapRect(boundingRect); 10988 rect.set((int) Math.floor(boundingRect.left), 10989 (int) Math.floor(boundingRect.top), 10990 (int) Math.ceil(boundingRect.right), 10991 (int) Math.ceil(boundingRect.bottom)); 10992 } 10993 } 10994 10995 /** 10996 * Used to indicate that the parent of this view should clear its caches. This functionality 10997 * is used to force the parent to rebuild its display list (when hardware-accelerated), 10998 * which is necessary when various parent-managed properties of the view change, such as 10999 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 11000 * clears the parent caches and does not causes an invalidate event. 11001 * 11002 * @hide 11003 */ 11004 protected void invalidateParentCaches() { 11005 if (mParent instanceof View) { 11006 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 11007 } 11008 } 11009 11010 /** 11011 * Used to indicate that the parent of this view should be invalidated. This functionality 11012 * is used to force the parent to rebuild its display list (when hardware-accelerated), 11013 * which is necessary when various parent-managed properties of the view change, such as 11014 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 11015 * an invalidation event to the parent. 11016 * 11017 * @hide 11018 */ 11019 protected void invalidateParentIfNeeded() { 11020 if (isHardwareAccelerated() && mParent instanceof View) { 11021 ((View) mParent).invalidate(true); 11022 } 11023 } 11024 11025 /** 11026 * Indicates whether this View is opaque. An opaque View guarantees that it will 11027 * draw all the pixels overlapping its bounds using a fully opaque color. 11028 * 11029 * Subclasses of View should override this method whenever possible to indicate 11030 * whether an instance is opaque. Opaque Views are treated in a special way by 11031 * the View hierarchy, possibly allowing it to perform optimizations during 11032 * invalidate/draw passes. 11033 * 11034 * @return True if this View is guaranteed to be fully opaque, false otherwise. 11035 */ 11036 @ViewDebug.ExportedProperty(category = "drawing") 11037 public boolean isOpaque() { 11038 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 11039 getFinalAlpha() >= 1.0f; 11040 } 11041 11042 /** 11043 * @hide 11044 */ 11045 protected void computeOpaqueFlags() { 11046 // Opaque if: 11047 // - Has a background 11048 // - Background is opaque 11049 // - Doesn't have scrollbars or scrollbars overlay 11050 11051 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 11052 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 11053 } else { 11054 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 11055 } 11056 11057 final int flags = mViewFlags; 11058 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 11059 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 11060 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 11061 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 11062 } else { 11063 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 11064 } 11065 } 11066 11067 /** 11068 * @hide 11069 */ 11070 protected boolean hasOpaqueScrollbars() { 11071 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 11072 } 11073 11074 /** 11075 * @return A handler associated with the thread running the View. This 11076 * handler can be used to pump events in the UI events queue. 11077 */ 11078 public Handler getHandler() { 11079 final AttachInfo attachInfo = mAttachInfo; 11080 if (attachInfo != null) { 11081 return attachInfo.mHandler; 11082 } 11083 return null; 11084 } 11085 11086 /** 11087 * Gets the view root associated with the View. 11088 * @return The view root, or null if none. 11089 * @hide 11090 */ 11091 public ViewRootImpl getViewRootImpl() { 11092 if (mAttachInfo != null) { 11093 return mAttachInfo.mViewRootImpl; 11094 } 11095 return null; 11096 } 11097 11098 /** 11099 * <p>Causes the Runnable to be added to the message queue. 11100 * The runnable will be run on the user interface thread.</p> 11101 * 11102 * @param action The Runnable that will be executed. 11103 * 11104 * @return Returns true if the Runnable was successfully placed in to the 11105 * message queue. Returns false on failure, usually because the 11106 * looper processing the message queue is exiting. 11107 * 11108 * @see #postDelayed 11109 * @see #removeCallbacks 11110 */ 11111 public boolean post(Runnable action) { 11112 final AttachInfo attachInfo = mAttachInfo; 11113 if (attachInfo != null) { 11114 return attachInfo.mHandler.post(action); 11115 } 11116 // Assume that post will succeed later 11117 ViewRootImpl.getRunQueue().post(action); 11118 return true; 11119 } 11120 11121 /** 11122 * <p>Causes the Runnable to be added to the message queue, to be run 11123 * after the specified amount of time elapses. 11124 * The runnable will be run on the user interface thread.</p> 11125 * 11126 * @param action The Runnable that will be executed. 11127 * @param delayMillis The delay (in milliseconds) until the Runnable 11128 * will be executed. 11129 * 11130 * @return true if the Runnable was successfully placed in to the 11131 * message queue. Returns false on failure, usually because the 11132 * looper processing the message queue is exiting. Note that a 11133 * result of true does not mean the Runnable will be processed -- 11134 * if the looper is quit before the delivery time of the message 11135 * occurs then the message will be dropped. 11136 * 11137 * @see #post 11138 * @see #removeCallbacks 11139 */ 11140 public boolean postDelayed(Runnable action, long delayMillis) { 11141 final AttachInfo attachInfo = mAttachInfo; 11142 if (attachInfo != null) { 11143 return attachInfo.mHandler.postDelayed(action, delayMillis); 11144 } 11145 // Assume that post will succeed later 11146 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); 11147 return true; 11148 } 11149 11150 /** 11151 * <p>Causes the Runnable to execute on the next animation time step. 11152 * The runnable will be run on the user interface thread.</p> 11153 * 11154 * @param action The Runnable that will be executed. 11155 * 11156 * @see #postOnAnimationDelayed 11157 * @see #removeCallbacks 11158 */ 11159 public void postOnAnimation(Runnable action) { 11160 final AttachInfo attachInfo = mAttachInfo; 11161 if (attachInfo != null) { 11162 attachInfo.mViewRootImpl.mChoreographer.postCallback( 11163 Choreographer.CALLBACK_ANIMATION, action, null); 11164 } else { 11165 // Assume that post will succeed later 11166 ViewRootImpl.getRunQueue().post(action); 11167 } 11168 } 11169 11170 /** 11171 * <p>Causes the Runnable to execute on the next animation time step, 11172 * after the specified amount of time elapses. 11173 * The runnable will be run on the user interface thread.</p> 11174 * 11175 * @param action The Runnable that will be executed. 11176 * @param delayMillis The delay (in milliseconds) until the Runnable 11177 * will be executed. 11178 * 11179 * @see #postOnAnimation 11180 * @see #removeCallbacks 11181 */ 11182 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 11183 final AttachInfo attachInfo = mAttachInfo; 11184 if (attachInfo != null) { 11185 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 11186 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 11187 } else { 11188 // Assume that post will succeed later 11189 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); 11190 } 11191 } 11192 11193 /** 11194 * <p>Removes the specified Runnable from the message queue.</p> 11195 * 11196 * @param action The Runnable to remove from the message handling queue 11197 * 11198 * @return true if this view could ask the Handler to remove the Runnable, 11199 * false otherwise. When the returned value is true, the Runnable 11200 * may or may not have been actually removed from the message queue 11201 * (for instance, if the Runnable was not in the queue already.) 11202 * 11203 * @see #post 11204 * @see #postDelayed 11205 * @see #postOnAnimation 11206 * @see #postOnAnimationDelayed 11207 */ 11208 public boolean removeCallbacks(Runnable action) { 11209 if (action != null) { 11210 final AttachInfo attachInfo = mAttachInfo; 11211 if (attachInfo != null) { 11212 attachInfo.mHandler.removeCallbacks(action); 11213 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 11214 Choreographer.CALLBACK_ANIMATION, action, null); 11215 } else { 11216 // Assume that post will succeed later 11217 ViewRootImpl.getRunQueue().removeCallbacks(action); 11218 } 11219 } 11220 return true; 11221 } 11222 11223 /** 11224 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 11225 * Use this to invalidate the View from a non-UI thread.</p> 11226 * 11227 * <p>This method can be invoked from outside of the UI thread 11228 * only when this View is attached to a window.</p> 11229 * 11230 * @see #invalidate() 11231 * @see #postInvalidateDelayed(long) 11232 */ 11233 public void postInvalidate() { 11234 postInvalidateDelayed(0); 11235 } 11236 11237 /** 11238 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 11239 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 11240 * 11241 * <p>This method can be invoked from outside of the UI thread 11242 * only when this View is attached to a window.</p> 11243 * 11244 * @param left The left coordinate of the rectangle to invalidate. 11245 * @param top The top coordinate of the rectangle to invalidate. 11246 * @param right The right coordinate of the rectangle to invalidate. 11247 * @param bottom The bottom coordinate of the rectangle to invalidate. 11248 * 11249 * @see #invalidate(int, int, int, int) 11250 * @see #invalidate(Rect) 11251 * @see #postInvalidateDelayed(long, int, int, int, int) 11252 */ 11253 public void postInvalidate(int left, int top, int right, int bottom) { 11254 postInvalidateDelayed(0, left, top, right, bottom); 11255 } 11256 11257 /** 11258 * <p>Cause an invalidate to happen on a subsequent cycle through the event 11259 * loop. Waits for the specified amount of time.</p> 11260 * 11261 * <p>This method can be invoked from outside of the UI thread 11262 * only when this View is attached to a window.</p> 11263 * 11264 * @param delayMilliseconds the duration in milliseconds to delay the 11265 * invalidation by 11266 * 11267 * @see #invalidate() 11268 * @see #postInvalidate() 11269 */ 11270 public void postInvalidateDelayed(long delayMilliseconds) { 11271 // We try only with the AttachInfo because there's no point in invalidating 11272 // if we are not attached to our window 11273 final AttachInfo attachInfo = mAttachInfo; 11274 if (attachInfo != null) { 11275 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 11276 } 11277 } 11278 11279 /** 11280 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 11281 * through the event loop. Waits for the specified amount of time.</p> 11282 * 11283 * <p>This method can be invoked from outside of the UI thread 11284 * only when this View is attached to a window.</p> 11285 * 11286 * @param delayMilliseconds the duration in milliseconds to delay the 11287 * invalidation by 11288 * @param left The left coordinate of the rectangle to invalidate. 11289 * @param top The top coordinate of the rectangle to invalidate. 11290 * @param right The right coordinate of the rectangle to invalidate. 11291 * @param bottom The bottom coordinate of the rectangle to invalidate. 11292 * 11293 * @see #invalidate(int, int, int, int) 11294 * @see #invalidate(Rect) 11295 * @see #postInvalidate(int, int, int, int) 11296 */ 11297 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 11298 int right, int bottom) { 11299 11300 // We try only with the AttachInfo because there's no point in invalidating 11301 // if we are not attached to our window 11302 final AttachInfo attachInfo = mAttachInfo; 11303 if (attachInfo != null) { 11304 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 11305 info.target = this; 11306 info.left = left; 11307 info.top = top; 11308 info.right = right; 11309 info.bottom = bottom; 11310 11311 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 11312 } 11313 } 11314 11315 /** 11316 * <p>Cause an invalidate to happen on the next animation time step, typically the 11317 * next display frame.</p> 11318 * 11319 * <p>This method can be invoked from outside of the UI thread 11320 * only when this View is attached to a window.</p> 11321 * 11322 * @see #invalidate() 11323 */ 11324 public void postInvalidateOnAnimation() { 11325 // We try only with the AttachInfo because there's no point in invalidating 11326 // if we are not attached to our window 11327 final AttachInfo attachInfo = mAttachInfo; 11328 if (attachInfo != null) { 11329 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 11330 } 11331 } 11332 11333 /** 11334 * <p>Cause an invalidate of the specified area to happen on the next animation 11335 * time step, typically the next display frame.</p> 11336 * 11337 * <p>This method can be invoked from outside of the UI thread 11338 * only when this View is attached to a window.</p> 11339 * 11340 * @param left The left coordinate of the rectangle to invalidate. 11341 * @param top The top coordinate of the rectangle to invalidate. 11342 * @param right The right coordinate of the rectangle to invalidate. 11343 * @param bottom The bottom coordinate of the rectangle to invalidate. 11344 * 11345 * @see #invalidate(int, int, int, int) 11346 * @see #invalidate(Rect) 11347 */ 11348 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 11349 // We try only with the AttachInfo because there's no point in invalidating 11350 // if we are not attached to our window 11351 final AttachInfo attachInfo = mAttachInfo; 11352 if (attachInfo != null) { 11353 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 11354 info.target = this; 11355 info.left = left; 11356 info.top = top; 11357 info.right = right; 11358 info.bottom = bottom; 11359 11360 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 11361 } 11362 } 11363 11364 /** 11365 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 11366 * This event is sent at most once every 11367 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 11368 */ 11369 private void postSendViewScrolledAccessibilityEventCallback() { 11370 if (mSendViewScrolledAccessibilityEvent == null) { 11371 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 11372 } 11373 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 11374 mSendViewScrolledAccessibilityEvent.mIsPending = true; 11375 postDelayed(mSendViewScrolledAccessibilityEvent, 11376 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 11377 } 11378 } 11379 11380 /** 11381 * Called by a parent to request that a child update its values for mScrollX 11382 * and mScrollY if necessary. This will typically be done if the child is 11383 * animating a scroll using a {@link android.widget.Scroller Scroller} 11384 * object. 11385 */ 11386 public void computeScroll() { 11387 } 11388 11389 /** 11390 * <p>Indicate whether the horizontal edges are faded when the view is 11391 * scrolled horizontally.</p> 11392 * 11393 * @return true if the horizontal edges should are faded on scroll, false 11394 * otherwise 11395 * 11396 * @see #setHorizontalFadingEdgeEnabled(boolean) 11397 * 11398 * @attr ref android.R.styleable#View_requiresFadingEdge 11399 */ 11400 public boolean isHorizontalFadingEdgeEnabled() { 11401 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 11402 } 11403 11404 /** 11405 * <p>Define whether the horizontal edges should be faded when this view 11406 * is scrolled horizontally.</p> 11407 * 11408 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 11409 * be faded when the view is scrolled 11410 * horizontally 11411 * 11412 * @see #isHorizontalFadingEdgeEnabled() 11413 * 11414 * @attr ref android.R.styleable#View_requiresFadingEdge 11415 */ 11416 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 11417 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 11418 if (horizontalFadingEdgeEnabled) { 11419 initScrollCache(); 11420 } 11421 11422 mViewFlags ^= FADING_EDGE_HORIZONTAL; 11423 } 11424 } 11425 11426 /** 11427 * <p>Indicate whether the vertical edges are faded when the view is 11428 * scrolled horizontally.</p> 11429 * 11430 * @return true if the vertical edges should are faded on scroll, false 11431 * otherwise 11432 * 11433 * @see #setVerticalFadingEdgeEnabled(boolean) 11434 * 11435 * @attr ref android.R.styleable#View_requiresFadingEdge 11436 */ 11437 public boolean isVerticalFadingEdgeEnabled() { 11438 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 11439 } 11440 11441 /** 11442 * <p>Define whether the vertical edges should be faded when this view 11443 * is scrolled vertically.</p> 11444 * 11445 * @param verticalFadingEdgeEnabled true if the vertical edges should 11446 * be faded when the view is scrolled 11447 * vertically 11448 * 11449 * @see #isVerticalFadingEdgeEnabled() 11450 * 11451 * @attr ref android.R.styleable#View_requiresFadingEdge 11452 */ 11453 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 11454 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 11455 if (verticalFadingEdgeEnabled) { 11456 initScrollCache(); 11457 } 11458 11459 mViewFlags ^= FADING_EDGE_VERTICAL; 11460 } 11461 } 11462 11463 /** 11464 * Returns the strength, or intensity, of the top faded edge. The strength is 11465 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11466 * returns 0.0 or 1.0 but no value in between. 11467 * 11468 * Subclasses should override this method to provide a smoother fade transition 11469 * when scrolling occurs. 11470 * 11471 * @return the intensity of the top fade as a float between 0.0f and 1.0f 11472 */ 11473 protected float getTopFadingEdgeStrength() { 11474 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 11475 } 11476 11477 /** 11478 * Returns the strength, or intensity, of the bottom faded edge. The strength is 11479 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11480 * returns 0.0 or 1.0 but no value in between. 11481 * 11482 * Subclasses should override this method to provide a smoother fade transition 11483 * when scrolling occurs. 11484 * 11485 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 11486 */ 11487 protected float getBottomFadingEdgeStrength() { 11488 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 11489 computeVerticalScrollRange() ? 1.0f : 0.0f; 11490 } 11491 11492 /** 11493 * Returns the strength, or intensity, of the left faded edge. The strength is 11494 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11495 * returns 0.0 or 1.0 but no value in between. 11496 * 11497 * Subclasses should override this method to provide a smoother fade transition 11498 * when scrolling occurs. 11499 * 11500 * @return the intensity of the left fade as a float between 0.0f and 1.0f 11501 */ 11502 protected float getLeftFadingEdgeStrength() { 11503 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 11504 } 11505 11506 /** 11507 * Returns the strength, or intensity, of the right faded edge. The strength is 11508 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11509 * returns 0.0 or 1.0 but no value in between. 11510 * 11511 * Subclasses should override this method to provide a smoother fade transition 11512 * when scrolling occurs. 11513 * 11514 * @return the intensity of the right fade as a float between 0.0f and 1.0f 11515 */ 11516 protected float getRightFadingEdgeStrength() { 11517 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 11518 computeHorizontalScrollRange() ? 1.0f : 0.0f; 11519 } 11520 11521 /** 11522 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 11523 * scrollbar is not drawn by default.</p> 11524 * 11525 * @return true if the horizontal scrollbar should be painted, false 11526 * otherwise 11527 * 11528 * @see #setHorizontalScrollBarEnabled(boolean) 11529 */ 11530 public boolean isHorizontalScrollBarEnabled() { 11531 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 11532 } 11533 11534 /** 11535 * <p>Define whether the horizontal scrollbar should be drawn or not. The 11536 * scrollbar is not drawn by default.</p> 11537 * 11538 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 11539 * be painted 11540 * 11541 * @see #isHorizontalScrollBarEnabled() 11542 */ 11543 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 11544 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 11545 mViewFlags ^= SCROLLBARS_HORIZONTAL; 11546 computeOpaqueFlags(); 11547 resolvePadding(); 11548 } 11549 } 11550 11551 /** 11552 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 11553 * scrollbar is not drawn by default.</p> 11554 * 11555 * @return true if the vertical scrollbar should be painted, false 11556 * otherwise 11557 * 11558 * @see #setVerticalScrollBarEnabled(boolean) 11559 */ 11560 public boolean isVerticalScrollBarEnabled() { 11561 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 11562 } 11563 11564 /** 11565 * <p>Define whether the vertical scrollbar should be drawn or not. The 11566 * scrollbar is not drawn by default.</p> 11567 * 11568 * @param verticalScrollBarEnabled true if the vertical scrollbar should 11569 * be painted 11570 * 11571 * @see #isVerticalScrollBarEnabled() 11572 */ 11573 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 11574 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 11575 mViewFlags ^= SCROLLBARS_VERTICAL; 11576 computeOpaqueFlags(); 11577 resolvePadding(); 11578 } 11579 } 11580 11581 /** 11582 * @hide 11583 */ 11584 protected void recomputePadding() { 11585 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 11586 } 11587 11588 /** 11589 * Define whether scrollbars will fade when the view is not scrolling. 11590 * 11591 * @param fadeScrollbars wheter to enable fading 11592 * 11593 * @attr ref android.R.styleable#View_fadeScrollbars 11594 */ 11595 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 11596 initScrollCache(); 11597 final ScrollabilityCache scrollabilityCache = mScrollCache; 11598 scrollabilityCache.fadeScrollBars = fadeScrollbars; 11599 if (fadeScrollbars) { 11600 scrollabilityCache.state = ScrollabilityCache.OFF; 11601 } else { 11602 scrollabilityCache.state = ScrollabilityCache.ON; 11603 } 11604 } 11605 11606 /** 11607 * 11608 * Returns true if scrollbars will fade when this view is not scrolling 11609 * 11610 * @return true if scrollbar fading is enabled 11611 * 11612 * @attr ref android.R.styleable#View_fadeScrollbars 11613 */ 11614 public boolean isScrollbarFadingEnabled() { 11615 return mScrollCache != null && mScrollCache.fadeScrollBars; 11616 } 11617 11618 /** 11619 * 11620 * Returns the delay before scrollbars fade. 11621 * 11622 * @return the delay before scrollbars fade 11623 * 11624 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 11625 */ 11626 public int getScrollBarDefaultDelayBeforeFade() { 11627 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 11628 mScrollCache.scrollBarDefaultDelayBeforeFade; 11629 } 11630 11631 /** 11632 * Define the delay before scrollbars fade. 11633 * 11634 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 11635 * 11636 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 11637 */ 11638 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 11639 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 11640 } 11641 11642 /** 11643 * 11644 * Returns the scrollbar fade duration. 11645 * 11646 * @return the scrollbar fade duration 11647 * 11648 * @attr ref android.R.styleable#View_scrollbarFadeDuration 11649 */ 11650 public int getScrollBarFadeDuration() { 11651 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 11652 mScrollCache.scrollBarFadeDuration; 11653 } 11654 11655 /** 11656 * Define the scrollbar fade duration. 11657 * 11658 * @param scrollBarFadeDuration - the scrollbar fade duration 11659 * 11660 * @attr ref android.R.styleable#View_scrollbarFadeDuration 11661 */ 11662 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 11663 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 11664 } 11665 11666 /** 11667 * 11668 * Returns the scrollbar size. 11669 * 11670 * @return the scrollbar size 11671 * 11672 * @attr ref android.R.styleable#View_scrollbarSize 11673 */ 11674 public int getScrollBarSize() { 11675 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 11676 mScrollCache.scrollBarSize; 11677 } 11678 11679 /** 11680 * Define the scrollbar size. 11681 * 11682 * @param scrollBarSize - the scrollbar size 11683 * 11684 * @attr ref android.R.styleable#View_scrollbarSize 11685 */ 11686 public void setScrollBarSize(int scrollBarSize) { 11687 getScrollCache().scrollBarSize = scrollBarSize; 11688 } 11689 11690 /** 11691 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 11692 * inset. When inset, they add to the padding of the view. And the scrollbars 11693 * can be drawn inside the padding area or on the edge of the view. For example, 11694 * if a view has a background drawable and you want to draw the scrollbars 11695 * inside the padding specified by the drawable, you can use 11696 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 11697 * appear at the edge of the view, ignoring the padding, then you can use 11698 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 11699 * @param style the style of the scrollbars. Should be one of 11700 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 11701 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 11702 * @see #SCROLLBARS_INSIDE_OVERLAY 11703 * @see #SCROLLBARS_INSIDE_INSET 11704 * @see #SCROLLBARS_OUTSIDE_OVERLAY 11705 * @see #SCROLLBARS_OUTSIDE_INSET 11706 * 11707 * @attr ref android.R.styleable#View_scrollbarStyle 11708 */ 11709 public void setScrollBarStyle(int style) { 11710 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 11711 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 11712 computeOpaqueFlags(); 11713 resolvePadding(); 11714 } 11715 } 11716 11717 /** 11718 * <p>Returns the current scrollbar style.</p> 11719 * @return the current scrollbar style 11720 * @see #SCROLLBARS_INSIDE_OVERLAY 11721 * @see #SCROLLBARS_INSIDE_INSET 11722 * @see #SCROLLBARS_OUTSIDE_OVERLAY 11723 * @see #SCROLLBARS_OUTSIDE_INSET 11724 * 11725 * @attr ref android.R.styleable#View_scrollbarStyle 11726 */ 11727 @ViewDebug.ExportedProperty(mapping = { 11728 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 11729 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 11730 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 11731 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 11732 }) 11733 public int getScrollBarStyle() { 11734 return mViewFlags & SCROLLBARS_STYLE_MASK; 11735 } 11736 11737 /** 11738 * <p>Compute the horizontal range that the horizontal scrollbar 11739 * represents.</p> 11740 * 11741 * <p>The range is expressed in arbitrary units that must be the same as the 11742 * units used by {@link #computeHorizontalScrollExtent()} and 11743 * {@link #computeHorizontalScrollOffset()}.</p> 11744 * 11745 * <p>The default range is the drawing width of this view.</p> 11746 * 11747 * @return the total horizontal range represented by the horizontal 11748 * scrollbar 11749 * 11750 * @see #computeHorizontalScrollExtent() 11751 * @see #computeHorizontalScrollOffset() 11752 * @see android.widget.ScrollBarDrawable 11753 */ 11754 protected int computeHorizontalScrollRange() { 11755 return getWidth(); 11756 } 11757 11758 /** 11759 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 11760 * within the horizontal range. This value is used to compute the position 11761 * of the thumb within the scrollbar's track.</p> 11762 * 11763 * <p>The range is expressed in arbitrary units that must be the same as the 11764 * units used by {@link #computeHorizontalScrollRange()} and 11765 * {@link #computeHorizontalScrollExtent()}.</p> 11766 * 11767 * <p>The default offset is the scroll offset of this view.</p> 11768 * 11769 * @return the horizontal offset of the scrollbar's thumb 11770 * 11771 * @see #computeHorizontalScrollRange() 11772 * @see #computeHorizontalScrollExtent() 11773 * @see android.widget.ScrollBarDrawable 11774 */ 11775 protected int computeHorizontalScrollOffset() { 11776 return mScrollX; 11777 } 11778 11779 /** 11780 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 11781 * within the horizontal range. This value is used to compute the length 11782 * of the thumb within the scrollbar's track.</p> 11783 * 11784 * <p>The range is expressed in arbitrary units that must be the same as the 11785 * units used by {@link #computeHorizontalScrollRange()} and 11786 * {@link #computeHorizontalScrollOffset()}.</p> 11787 * 11788 * <p>The default extent is the drawing width of this view.</p> 11789 * 11790 * @return the horizontal extent of the scrollbar's thumb 11791 * 11792 * @see #computeHorizontalScrollRange() 11793 * @see #computeHorizontalScrollOffset() 11794 * @see android.widget.ScrollBarDrawable 11795 */ 11796 protected int computeHorizontalScrollExtent() { 11797 return getWidth(); 11798 } 11799 11800 /** 11801 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 11802 * 11803 * <p>The range is expressed in arbitrary units that must be the same as the 11804 * units used by {@link #computeVerticalScrollExtent()} and 11805 * {@link #computeVerticalScrollOffset()}.</p> 11806 * 11807 * @return the total vertical range represented by the vertical scrollbar 11808 * 11809 * <p>The default range is the drawing height of this view.</p> 11810 * 11811 * @see #computeVerticalScrollExtent() 11812 * @see #computeVerticalScrollOffset() 11813 * @see android.widget.ScrollBarDrawable 11814 */ 11815 protected int computeVerticalScrollRange() { 11816 return getHeight(); 11817 } 11818 11819 /** 11820 * <p>Compute the vertical offset of the vertical scrollbar's thumb 11821 * within the horizontal range. This value is used to compute the position 11822 * of the thumb within the scrollbar's track.</p> 11823 * 11824 * <p>The range is expressed in arbitrary units that must be the same as the 11825 * units used by {@link #computeVerticalScrollRange()} and 11826 * {@link #computeVerticalScrollExtent()}.</p> 11827 * 11828 * <p>The default offset is the scroll offset of this view.</p> 11829 * 11830 * @return the vertical offset of the scrollbar's thumb 11831 * 11832 * @see #computeVerticalScrollRange() 11833 * @see #computeVerticalScrollExtent() 11834 * @see android.widget.ScrollBarDrawable 11835 */ 11836 protected int computeVerticalScrollOffset() { 11837 return mScrollY; 11838 } 11839 11840 /** 11841 * <p>Compute the vertical extent of the horizontal scrollbar's thumb 11842 * within the vertical range. This value is used to compute the length 11843 * of the thumb within the scrollbar's track.</p> 11844 * 11845 * <p>The range is expressed in arbitrary units that must be the same as the 11846 * units used by {@link #computeVerticalScrollRange()} and 11847 * {@link #computeVerticalScrollOffset()}.</p> 11848 * 11849 * <p>The default extent is the drawing height of this view.</p> 11850 * 11851 * @return the vertical extent of the scrollbar's thumb 11852 * 11853 * @see #computeVerticalScrollRange() 11854 * @see #computeVerticalScrollOffset() 11855 * @see android.widget.ScrollBarDrawable 11856 */ 11857 protected int computeVerticalScrollExtent() { 11858 return getHeight(); 11859 } 11860 11861 /** 11862 * Check if this view can be scrolled horizontally in a certain direction. 11863 * 11864 * @param direction Negative to check scrolling left, positive to check scrolling right. 11865 * @return true if this view can be scrolled in the specified direction, false otherwise. 11866 */ 11867 public boolean canScrollHorizontally(int direction) { 11868 final int offset = computeHorizontalScrollOffset(); 11869 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 11870 if (range == 0) return false; 11871 if (direction < 0) { 11872 return offset > 0; 11873 } else { 11874 return offset < range - 1; 11875 } 11876 } 11877 11878 /** 11879 * Check if this view can be scrolled vertically in a certain direction. 11880 * 11881 * @param direction Negative to check scrolling up, positive to check scrolling down. 11882 * @return true if this view can be scrolled in the specified direction, false otherwise. 11883 */ 11884 public boolean canScrollVertically(int direction) { 11885 final int offset = computeVerticalScrollOffset(); 11886 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 11887 if (range == 0) return false; 11888 if (direction < 0) { 11889 return offset > 0; 11890 } else { 11891 return offset < range - 1; 11892 } 11893 } 11894 11895 /** 11896 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 11897 * scrollbars are painted only if they have been awakened first.</p> 11898 * 11899 * @param canvas the canvas on which to draw the scrollbars 11900 * 11901 * @see #awakenScrollBars(int) 11902 */ 11903 protected final void onDrawScrollBars(Canvas canvas) { 11904 // scrollbars are drawn only when the animation is running 11905 final ScrollabilityCache cache = mScrollCache; 11906 if (cache != null) { 11907 11908 int state = cache.state; 11909 11910 if (state == ScrollabilityCache.OFF) { 11911 return; 11912 } 11913 11914 boolean invalidate = false; 11915 11916 if (state == ScrollabilityCache.FADING) { 11917 // We're fading -- get our fade interpolation 11918 if (cache.interpolatorValues == null) { 11919 cache.interpolatorValues = new float[1]; 11920 } 11921 11922 float[] values = cache.interpolatorValues; 11923 11924 // Stops the animation if we're done 11925 if (cache.scrollBarInterpolator.timeToValues(values) == 11926 Interpolator.Result.FREEZE_END) { 11927 cache.state = ScrollabilityCache.OFF; 11928 } else { 11929 cache.scrollBar.setAlpha(Math.round(values[0])); 11930 } 11931 11932 // This will make the scroll bars inval themselves after 11933 // drawing. We only want this when we're fading so that 11934 // we prevent excessive redraws 11935 invalidate = true; 11936 } else { 11937 // We're just on -- but we may have been fading before so 11938 // reset alpha 11939 cache.scrollBar.setAlpha(255); 11940 } 11941 11942 11943 final int viewFlags = mViewFlags; 11944 11945 final boolean drawHorizontalScrollBar = 11946 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 11947 final boolean drawVerticalScrollBar = 11948 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 11949 && !isVerticalScrollBarHidden(); 11950 11951 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 11952 final int width = mRight - mLeft; 11953 final int height = mBottom - mTop; 11954 11955 final ScrollBarDrawable scrollBar = cache.scrollBar; 11956 11957 final int scrollX = mScrollX; 11958 final int scrollY = mScrollY; 11959 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 11960 11961 int left; 11962 int top; 11963 int right; 11964 int bottom; 11965 11966 if (drawHorizontalScrollBar) { 11967 int size = scrollBar.getSize(false); 11968 if (size <= 0) { 11969 size = cache.scrollBarSize; 11970 } 11971 11972 scrollBar.setParameters(computeHorizontalScrollRange(), 11973 computeHorizontalScrollOffset(), 11974 computeHorizontalScrollExtent(), false); 11975 final int verticalScrollBarGap = drawVerticalScrollBar ? 11976 getVerticalScrollbarWidth() : 0; 11977 top = scrollY + height - size - (mUserPaddingBottom & inside); 11978 left = scrollX + (mPaddingLeft & inside); 11979 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 11980 bottom = top + size; 11981 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); 11982 if (invalidate) { 11983 invalidate(left, top, right, bottom); 11984 } 11985 } 11986 11987 if (drawVerticalScrollBar) { 11988 int size = scrollBar.getSize(true); 11989 if (size <= 0) { 11990 size = cache.scrollBarSize; 11991 } 11992 11993 scrollBar.setParameters(computeVerticalScrollRange(), 11994 computeVerticalScrollOffset(), 11995 computeVerticalScrollExtent(), true); 11996 int verticalScrollbarPosition = mVerticalScrollbarPosition; 11997 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 11998 verticalScrollbarPosition = isLayoutRtl() ? 11999 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 12000 } 12001 switch (verticalScrollbarPosition) { 12002 default: 12003 case SCROLLBAR_POSITION_RIGHT: 12004 left = scrollX + width - size - (mUserPaddingRight & inside); 12005 break; 12006 case SCROLLBAR_POSITION_LEFT: 12007 left = scrollX + (mUserPaddingLeft & inside); 12008 break; 12009 } 12010 top = scrollY + (mPaddingTop & inside); 12011 right = left + size; 12012 bottom = scrollY + height - (mUserPaddingBottom & inside); 12013 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); 12014 if (invalidate) { 12015 invalidate(left, top, right, bottom); 12016 } 12017 } 12018 } 12019 } 12020 } 12021 12022 /** 12023 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 12024 * FastScroller is visible. 12025 * @return whether to temporarily hide the vertical scrollbar 12026 * @hide 12027 */ 12028 protected boolean isVerticalScrollBarHidden() { 12029 return false; 12030 } 12031 12032 /** 12033 * <p>Draw the horizontal scrollbar if 12034 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 12035 * 12036 * @param canvas the canvas on which to draw the scrollbar 12037 * @param scrollBar the scrollbar's drawable 12038 * 12039 * @see #isHorizontalScrollBarEnabled() 12040 * @see #computeHorizontalScrollRange() 12041 * @see #computeHorizontalScrollExtent() 12042 * @see #computeHorizontalScrollOffset() 12043 * @see android.widget.ScrollBarDrawable 12044 * @hide 12045 */ 12046 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 12047 int l, int t, int r, int b) { 12048 scrollBar.setBounds(l, t, r, b); 12049 scrollBar.draw(canvas); 12050 } 12051 12052 /** 12053 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 12054 * returns true.</p> 12055 * 12056 * @param canvas the canvas on which to draw the scrollbar 12057 * @param scrollBar the scrollbar's drawable 12058 * 12059 * @see #isVerticalScrollBarEnabled() 12060 * @see #computeVerticalScrollRange() 12061 * @see #computeVerticalScrollExtent() 12062 * @see #computeVerticalScrollOffset() 12063 * @see android.widget.ScrollBarDrawable 12064 * @hide 12065 */ 12066 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 12067 int l, int t, int r, int b) { 12068 scrollBar.setBounds(l, t, r, b); 12069 scrollBar.draw(canvas); 12070 } 12071 12072 /** 12073 * Implement this to do your drawing. 12074 * 12075 * @param canvas the canvas on which the background will be drawn 12076 */ 12077 protected void onDraw(Canvas canvas) { 12078 } 12079 12080 /* 12081 * Caller is responsible for calling requestLayout if necessary. 12082 * (This allows addViewInLayout to not request a new layout.) 12083 */ 12084 void assignParent(ViewParent parent) { 12085 if (mParent == null) { 12086 mParent = parent; 12087 } else if (parent == null) { 12088 mParent = null; 12089 } else { 12090 throw new RuntimeException("view " + this + " being added, but" 12091 + " it already has a parent"); 12092 } 12093 } 12094 12095 /** 12096 * This is called when the view is attached to a window. At this point it 12097 * has a Surface and will start drawing. Note that this function is 12098 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 12099 * however it may be called any time before the first onDraw -- including 12100 * before or after {@link #onMeasure(int, int)}. 12101 * 12102 * @see #onDetachedFromWindow() 12103 */ 12104 protected void onAttachedToWindow() { 12105 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 12106 mParent.requestTransparentRegion(this); 12107 } 12108 12109 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) { 12110 initialAwakenScrollBars(); 12111 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH; 12112 } 12113 12114 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 12115 12116 jumpDrawablesToCurrentState(); 12117 12118 resetSubtreeAccessibilityStateChanged(); 12119 12120 if (isFocused()) { 12121 InputMethodManager imm = InputMethodManager.peekInstance(); 12122 imm.focusIn(this); 12123 } 12124 12125 if (mDisplayList != null) { 12126 mDisplayList.clearDirty(); 12127 } 12128 } 12129 12130 /** 12131 * Resolve all RTL related properties. 12132 * 12133 * @return true if resolution of RTL properties has been done 12134 * 12135 * @hide 12136 */ 12137 public boolean resolveRtlPropertiesIfNeeded() { 12138 if (!needRtlPropertiesResolution()) return false; 12139 12140 // Order is important here: LayoutDirection MUST be resolved first 12141 if (!isLayoutDirectionResolved()) { 12142 resolveLayoutDirection(); 12143 resolveLayoutParams(); 12144 } 12145 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 12146 if (!isTextDirectionResolved()) { 12147 resolveTextDirection(); 12148 } 12149 if (!isTextAlignmentResolved()) { 12150 resolveTextAlignment(); 12151 } 12152 // Should resolve Drawables before Padding because we need the layout direction of the 12153 // Drawable to correctly resolve Padding. 12154 if (!isDrawablesResolved()) { 12155 resolveDrawables(); 12156 } 12157 if (!isPaddingResolved()) { 12158 resolvePadding(); 12159 } 12160 onRtlPropertiesChanged(getLayoutDirection()); 12161 return true; 12162 } 12163 12164 /** 12165 * Reset resolution of all RTL related properties. 12166 * 12167 * @hide 12168 */ 12169 public void resetRtlProperties() { 12170 resetResolvedLayoutDirection(); 12171 resetResolvedTextDirection(); 12172 resetResolvedTextAlignment(); 12173 resetResolvedPadding(); 12174 resetResolvedDrawables(); 12175 } 12176 12177 /** 12178 * @see #onScreenStateChanged(int) 12179 */ 12180 void dispatchScreenStateChanged(int screenState) { 12181 onScreenStateChanged(screenState); 12182 } 12183 12184 /** 12185 * This method is called whenever the state of the screen this view is 12186 * attached to changes. A state change will usually occurs when the screen 12187 * turns on or off (whether it happens automatically or the user does it 12188 * manually.) 12189 * 12190 * @param screenState The new state of the screen. Can be either 12191 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 12192 */ 12193 public void onScreenStateChanged(int screenState) { 12194 } 12195 12196 /** 12197 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 12198 */ 12199 private boolean hasRtlSupport() { 12200 return mContext.getApplicationInfo().hasRtlSupport(); 12201 } 12202 12203 /** 12204 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 12205 * RTL not supported) 12206 */ 12207 private boolean isRtlCompatibilityMode() { 12208 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 12209 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 12210 } 12211 12212 /** 12213 * @return true if RTL properties need resolution. 12214 * 12215 */ 12216 private boolean needRtlPropertiesResolution() { 12217 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 12218 } 12219 12220 /** 12221 * Called when any RTL property (layout direction or text direction or text alignment) has 12222 * been changed. 12223 * 12224 * Subclasses need to override this method to take care of cached information that depends on the 12225 * resolved layout direction, or to inform child views that inherit their layout direction. 12226 * 12227 * The default implementation does nothing. 12228 * 12229 * @param layoutDirection the direction of the layout 12230 * 12231 * @see #LAYOUT_DIRECTION_LTR 12232 * @see #LAYOUT_DIRECTION_RTL 12233 */ 12234 public void onRtlPropertiesChanged(int layoutDirection) { 12235 } 12236 12237 /** 12238 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 12239 * that the parent directionality can and will be resolved before its children. 12240 * 12241 * @return true if resolution has been done, false otherwise. 12242 * 12243 * @hide 12244 */ 12245 public boolean resolveLayoutDirection() { 12246 // Clear any previous layout direction resolution 12247 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 12248 12249 if (hasRtlSupport()) { 12250 // Set resolved depending on layout direction 12251 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 12252 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 12253 case LAYOUT_DIRECTION_INHERIT: 12254 // We cannot resolve yet. LTR is by default and let the resolution happen again 12255 // later to get the correct resolved value 12256 if (!canResolveLayoutDirection()) return false; 12257 12258 // Parent has not yet resolved, LTR is still the default 12259 try { 12260 if (!mParent.isLayoutDirectionResolved()) return false; 12261 12262 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 12263 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12264 } 12265 } catch (AbstractMethodError e) { 12266 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 12267 " does not fully implement ViewParent", e); 12268 } 12269 break; 12270 case LAYOUT_DIRECTION_RTL: 12271 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12272 break; 12273 case LAYOUT_DIRECTION_LOCALE: 12274 if((LAYOUT_DIRECTION_RTL == 12275 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 12276 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12277 } 12278 break; 12279 default: 12280 // Nothing to do, LTR by default 12281 } 12282 } 12283 12284 // Set to resolved 12285 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 12286 return true; 12287 } 12288 12289 /** 12290 * Check if layout direction resolution can be done. 12291 * 12292 * @return true if layout direction resolution can be done otherwise return false. 12293 */ 12294 public boolean canResolveLayoutDirection() { 12295 switch (getRawLayoutDirection()) { 12296 case LAYOUT_DIRECTION_INHERIT: 12297 if (mParent != null) { 12298 try { 12299 return mParent.canResolveLayoutDirection(); 12300 } catch (AbstractMethodError e) { 12301 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 12302 " does not fully implement ViewParent", e); 12303 } 12304 } 12305 return false; 12306 12307 default: 12308 return true; 12309 } 12310 } 12311 12312 /** 12313 * Reset the resolved layout direction. Layout direction will be resolved during a call to 12314 * {@link #onMeasure(int, int)}. 12315 * 12316 * @hide 12317 */ 12318 public void resetResolvedLayoutDirection() { 12319 // Reset the current resolved bits 12320 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 12321 } 12322 12323 /** 12324 * @return true if the layout direction is inherited. 12325 * 12326 * @hide 12327 */ 12328 public boolean isLayoutDirectionInherited() { 12329 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 12330 } 12331 12332 /** 12333 * @return true if layout direction has been resolved. 12334 */ 12335 public boolean isLayoutDirectionResolved() { 12336 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 12337 } 12338 12339 /** 12340 * Return if padding has been resolved 12341 * 12342 * @hide 12343 */ 12344 boolean isPaddingResolved() { 12345 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 12346 } 12347 12348 /** 12349 * Resolves padding depending on layout direction, if applicable, and 12350 * recomputes internal padding values to adjust for scroll bars. 12351 * 12352 * @hide 12353 */ 12354 public void resolvePadding() { 12355 final int resolvedLayoutDirection = getLayoutDirection(); 12356 12357 if (!isRtlCompatibilityMode()) { 12358 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 12359 // If start / end padding are defined, they will be resolved (hence overriding) to 12360 // left / right or right / left depending on the resolved layout direction. 12361 // If start / end padding are not defined, use the left / right ones. 12362 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 12363 Rect padding = sThreadLocal.get(); 12364 if (padding == null) { 12365 padding = new Rect(); 12366 sThreadLocal.set(padding); 12367 } 12368 mBackground.getPadding(padding); 12369 if (!mLeftPaddingDefined) { 12370 mUserPaddingLeftInitial = padding.left; 12371 } 12372 if (!mRightPaddingDefined) { 12373 mUserPaddingRightInitial = padding.right; 12374 } 12375 } 12376 switch (resolvedLayoutDirection) { 12377 case LAYOUT_DIRECTION_RTL: 12378 if (mUserPaddingStart != UNDEFINED_PADDING) { 12379 mUserPaddingRight = mUserPaddingStart; 12380 } else { 12381 mUserPaddingRight = mUserPaddingRightInitial; 12382 } 12383 if (mUserPaddingEnd != UNDEFINED_PADDING) { 12384 mUserPaddingLeft = mUserPaddingEnd; 12385 } else { 12386 mUserPaddingLeft = mUserPaddingLeftInitial; 12387 } 12388 break; 12389 case LAYOUT_DIRECTION_LTR: 12390 default: 12391 if (mUserPaddingStart != UNDEFINED_PADDING) { 12392 mUserPaddingLeft = mUserPaddingStart; 12393 } else { 12394 mUserPaddingLeft = mUserPaddingLeftInitial; 12395 } 12396 if (mUserPaddingEnd != UNDEFINED_PADDING) { 12397 mUserPaddingRight = mUserPaddingEnd; 12398 } else { 12399 mUserPaddingRight = mUserPaddingRightInitial; 12400 } 12401 } 12402 12403 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 12404 } 12405 12406 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 12407 onRtlPropertiesChanged(resolvedLayoutDirection); 12408 12409 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 12410 } 12411 12412 /** 12413 * Reset the resolved layout direction. 12414 * 12415 * @hide 12416 */ 12417 public void resetResolvedPadding() { 12418 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 12419 } 12420 12421 /** 12422 * This is called when the view is detached from a window. At this point it 12423 * no longer has a surface for drawing. 12424 * 12425 * @see #onAttachedToWindow() 12426 */ 12427 protected void onDetachedFromWindow() { 12428 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 12429 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 12430 12431 removeUnsetPressCallback(); 12432 removeLongPressCallback(); 12433 removePerformClickCallback(); 12434 removeSendViewScrolledAccessibilityEventCallback(); 12435 12436 destroyDrawingCache(); 12437 destroyLayer(false); 12438 12439 cleanupDraw(); 12440 12441 mCurrentAnimation = null; 12442 } 12443 12444 private void cleanupDraw() { 12445 if (mAttachInfo != null) { 12446 if (mDisplayList != null) { 12447 mDisplayList.markDirty(); 12448 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList); 12449 } 12450 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 12451 } else { 12452 // Should never happen 12453 resetDisplayList(); 12454 } 12455 } 12456 12457 /** 12458 * This method ensures the hardware renderer is in a valid state 12459 * before executing the specified action. 12460 * 12461 * This method will attempt to set a valid state even if the window 12462 * the renderer is attached to was destroyed. 12463 * 12464 * This method is not guaranteed to work. If the hardware renderer 12465 * does not exist or cannot be put in a valid state, this method 12466 * will not executed the specified action. 12467 * 12468 * The specified action is executed synchronously. 12469 * 12470 * @param action The action to execute after the renderer is in a valid state 12471 * 12472 * @return True if the specified Runnable was executed, false otherwise 12473 * 12474 * @hide 12475 */ 12476 public boolean executeHardwareAction(Runnable action) { 12477 //noinspection SimplifiableIfStatement 12478 if (mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { 12479 return mAttachInfo.mHardwareRenderer.safelyRun(action); 12480 } 12481 return false; 12482 } 12483 12484 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 12485 } 12486 12487 /** 12488 * @return The number of times this view has been attached to a window 12489 */ 12490 protected int getWindowAttachCount() { 12491 return mWindowAttachCount; 12492 } 12493 12494 /** 12495 * Retrieve a unique token identifying the window this view is attached to. 12496 * @return Return the window's token for use in 12497 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 12498 */ 12499 public IBinder getWindowToken() { 12500 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 12501 } 12502 12503 /** 12504 * Retrieve the {@link WindowId} for the window this view is 12505 * currently attached to. 12506 */ 12507 public WindowId getWindowId() { 12508 if (mAttachInfo == null) { 12509 return null; 12510 } 12511 if (mAttachInfo.mWindowId == null) { 12512 try { 12513 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId( 12514 mAttachInfo.mWindowToken); 12515 mAttachInfo.mWindowId = new WindowId( 12516 mAttachInfo.mIWindowId); 12517 } catch (RemoteException e) { 12518 } 12519 } 12520 return mAttachInfo.mWindowId; 12521 } 12522 12523 /** 12524 * Retrieve a unique token identifying the top-level "real" window of 12525 * the window that this view is attached to. That is, this is like 12526 * {@link #getWindowToken}, except if the window this view in is a panel 12527 * window (attached to another containing window), then the token of 12528 * the containing window is returned instead. 12529 * 12530 * @return Returns the associated window token, either 12531 * {@link #getWindowToken()} or the containing window's token. 12532 */ 12533 public IBinder getApplicationWindowToken() { 12534 AttachInfo ai = mAttachInfo; 12535 if (ai != null) { 12536 IBinder appWindowToken = ai.mPanelParentWindowToken; 12537 if (appWindowToken == null) { 12538 appWindowToken = ai.mWindowToken; 12539 } 12540 return appWindowToken; 12541 } 12542 return null; 12543 } 12544 12545 /** 12546 * Gets the logical display to which the view's window has been attached. 12547 * 12548 * @return The logical display, or null if the view is not currently attached to a window. 12549 */ 12550 public Display getDisplay() { 12551 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 12552 } 12553 12554 /** 12555 * Retrieve private session object this view hierarchy is using to 12556 * communicate with the window manager. 12557 * @return the session object to communicate with the window manager 12558 */ 12559 /*package*/ IWindowSession getWindowSession() { 12560 return mAttachInfo != null ? mAttachInfo.mSession : null; 12561 } 12562 12563 /** 12564 * @param info the {@link android.view.View.AttachInfo} to associated with 12565 * this view 12566 */ 12567 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 12568 //System.out.println("Attached! " + this); 12569 mAttachInfo = info; 12570 if (mOverlay != null) { 12571 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 12572 } 12573 mWindowAttachCount++; 12574 // We will need to evaluate the drawable state at least once. 12575 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 12576 if (mFloatingTreeObserver != null) { 12577 info.mTreeObserver.merge(mFloatingTreeObserver); 12578 mFloatingTreeObserver = null; 12579 } 12580 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 12581 mAttachInfo.mScrollContainers.add(this); 12582 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 12583 } 12584 performCollectViewAttributes(mAttachInfo, visibility); 12585 onAttachedToWindow(); 12586 12587 ListenerInfo li = mListenerInfo; 12588 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 12589 li != null ? li.mOnAttachStateChangeListeners : null; 12590 if (listeners != null && listeners.size() > 0) { 12591 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 12592 // perform the dispatching. The iterator is a safe guard against listeners that 12593 // could mutate the list by calling the various add/remove methods. This prevents 12594 // the array from being modified while we iterate it. 12595 for (OnAttachStateChangeListener listener : listeners) { 12596 listener.onViewAttachedToWindow(this); 12597 } 12598 } 12599 12600 int vis = info.mWindowVisibility; 12601 if (vis != GONE) { 12602 onWindowVisibilityChanged(vis); 12603 } 12604 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 12605 // If nobody has evaluated the drawable state yet, then do it now. 12606 refreshDrawableState(); 12607 } 12608 needGlobalAttributesUpdate(false); 12609 } 12610 12611 void dispatchDetachedFromWindow() { 12612 AttachInfo info = mAttachInfo; 12613 if (info != null) { 12614 int vis = info.mWindowVisibility; 12615 if (vis != GONE) { 12616 onWindowVisibilityChanged(GONE); 12617 } 12618 } 12619 12620 onDetachedFromWindow(); 12621 12622 ListenerInfo li = mListenerInfo; 12623 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 12624 li != null ? li.mOnAttachStateChangeListeners : null; 12625 if (listeners != null && listeners.size() > 0) { 12626 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 12627 // perform the dispatching. The iterator is a safe guard against listeners that 12628 // could mutate the list by calling the various add/remove methods. This prevents 12629 // the array from being modified while we iterate it. 12630 for (OnAttachStateChangeListener listener : listeners) { 12631 listener.onViewDetachedFromWindow(this); 12632 } 12633 } 12634 12635 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 12636 mAttachInfo.mScrollContainers.remove(this); 12637 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 12638 } 12639 12640 mAttachInfo = null; 12641 if (mOverlay != null) { 12642 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 12643 } 12644 } 12645 12646 /** 12647 * Cancel any deferred high-level input events that were previously posted to the event queue. 12648 * 12649 * <p>Many views post high-level events such as click handlers to the event queue 12650 * to run deferred in order to preserve a desired user experience - clearing visible 12651 * pressed states before executing, etc. This method will abort any events of this nature 12652 * that are currently in flight.</p> 12653 * 12654 * <p>Custom views that generate their own high-level deferred input events should override 12655 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 12656 * 12657 * <p>This will also cancel pending input events for any child views.</p> 12658 * 12659 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 12660 * This will not impact newer events posted after this call that may occur as a result of 12661 * lower-level input events still waiting in the queue. If you are trying to prevent 12662 * double-submitted events for the duration of some sort of asynchronous transaction 12663 * you should also take other steps to protect against unexpected double inputs e.g. calling 12664 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 12665 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 12666 */ 12667 public final void cancelPendingInputEvents() { 12668 dispatchCancelPendingInputEvents(); 12669 } 12670 12671 /** 12672 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 12673 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 12674 */ 12675 void dispatchCancelPendingInputEvents() { 12676 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 12677 onCancelPendingInputEvents(); 12678 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 12679 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 12680 " did not call through to super.onCancelPendingInputEvents()"); 12681 } 12682 } 12683 12684 /** 12685 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 12686 * a parent view. 12687 * 12688 * <p>This method is responsible for removing any pending high-level input events that were 12689 * posted to the event queue to run later. Custom view classes that post their own deferred 12690 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 12691 * {@link android.os.Handler} should override this method, call 12692 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 12693 * </p> 12694 */ 12695 public void onCancelPendingInputEvents() { 12696 removePerformClickCallback(); 12697 cancelLongPress(); 12698 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 12699 } 12700 12701 /** 12702 * Store this view hierarchy's frozen state into the given container. 12703 * 12704 * @param container The SparseArray in which to save the view's state. 12705 * 12706 * @see #restoreHierarchyState(android.util.SparseArray) 12707 * @see #dispatchSaveInstanceState(android.util.SparseArray) 12708 * @see #onSaveInstanceState() 12709 */ 12710 public void saveHierarchyState(SparseArray<Parcelable> container) { 12711 dispatchSaveInstanceState(container); 12712 } 12713 12714 /** 12715 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 12716 * this view and its children. May be overridden to modify how freezing happens to a 12717 * view's children; for example, some views may want to not store state for their children. 12718 * 12719 * @param container The SparseArray in which to save the view's state. 12720 * 12721 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 12722 * @see #saveHierarchyState(android.util.SparseArray) 12723 * @see #onSaveInstanceState() 12724 */ 12725 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 12726 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 12727 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 12728 Parcelable state = onSaveInstanceState(); 12729 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 12730 throw new IllegalStateException( 12731 "Derived class did not call super.onSaveInstanceState()"); 12732 } 12733 if (state != null) { 12734 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 12735 // + ": " + state); 12736 container.put(mID, state); 12737 } 12738 } 12739 } 12740 12741 /** 12742 * Hook allowing a view to generate a representation of its internal state 12743 * that can later be used to create a new instance with that same state. 12744 * This state should only contain information that is not persistent or can 12745 * not be reconstructed later. For example, you will never store your 12746 * current position on screen because that will be computed again when a 12747 * new instance of the view is placed in its view hierarchy. 12748 * <p> 12749 * Some examples of things you may store here: the current cursor position 12750 * in a text view (but usually not the text itself since that is stored in a 12751 * content provider or other persistent storage), the currently selected 12752 * item in a list view. 12753 * 12754 * @return Returns a Parcelable object containing the view's current dynamic 12755 * state, or null if there is nothing interesting to save. The 12756 * default implementation returns null. 12757 * @see #onRestoreInstanceState(android.os.Parcelable) 12758 * @see #saveHierarchyState(android.util.SparseArray) 12759 * @see #dispatchSaveInstanceState(android.util.SparseArray) 12760 * @see #setSaveEnabled(boolean) 12761 */ 12762 protected Parcelable onSaveInstanceState() { 12763 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 12764 return BaseSavedState.EMPTY_STATE; 12765 } 12766 12767 /** 12768 * Restore this view hierarchy's frozen state from the given container. 12769 * 12770 * @param container The SparseArray which holds previously frozen states. 12771 * 12772 * @see #saveHierarchyState(android.util.SparseArray) 12773 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 12774 * @see #onRestoreInstanceState(android.os.Parcelable) 12775 */ 12776 public void restoreHierarchyState(SparseArray<Parcelable> container) { 12777 dispatchRestoreInstanceState(container); 12778 } 12779 12780 /** 12781 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 12782 * state for this view and its children. May be overridden to modify how restoring 12783 * happens to a view's children; for example, some views may want to not store state 12784 * for their children. 12785 * 12786 * @param container The SparseArray which holds previously saved state. 12787 * 12788 * @see #dispatchSaveInstanceState(android.util.SparseArray) 12789 * @see #restoreHierarchyState(android.util.SparseArray) 12790 * @see #onRestoreInstanceState(android.os.Parcelable) 12791 */ 12792 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 12793 if (mID != NO_ID) { 12794 Parcelable state = container.get(mID); 12795 if (state != null) { 12796 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 12797 // + ": " + state); 12798 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 12799 onRestoreInstanceState(state); 12800 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 12801 throw new IllegalStateException( 12802 "Derived class did not call super.onRestoreInstanceState()"); 12803 } 12804 } 12805 } 12806 } 12807 12808 /** 12809 * Hook allowing a view to re-apply a representation of its internal state that had previously 12810 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 12811 * null state. 12812 * 12813 * @param state The frozen state that had previously been returned by 12814 * {@link #onSaveInstanceState}. 12815 * 12816 * @see #onSaveInstanceState() 12817 * @see #restoreHierarchyState(android.util.SparseArray) 12818 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 12819 */ 12820 protected void onRestoreInstanceState(Parcelable state) { 12821 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 12822 if (state != BaseSavedState.EMPTY_STATE && state != null) { 12823 throw new IllegalArgumentException("Wrong state class, expecting View State but " 12824 + "received " + state.getClass().toString() + " instead. This usually happens " 12825 + "when two views of different type have the same id in the same hierarchy. " 12826 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 12827 + "other views do not use the same id."); 12828 } 12829 } 12830 12831 /** 12832 * <p>Return the time at which the drawing of the view hierarchy started.</p> 12833 * 12834 * @return the drawing start time in milliseconds 12835 */ 12836 public long getDrawingTime() { 12837 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 12838 } 12839 12840 /** 12841 * <p>Enables or disables the duplication of the parent's state into this view. When 12842 * duplication is enabled, this view gets its drawable state from its parent rather 12843 * than from its own internal properties.</p> 12844 * 12845 * <p>Note: in the current implementation, setting this property to true after the 12846 * view was added to a ViewGroup might have no effect at all. This property should 12847 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 12848 * 12849 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 12850 * property is enabled, an exception will be thrown.</p> 12851 * 12852 * <p>Note: if the child view uses and updates additionnal states which are unknown to the 12853 * parent, these states should not be affected by this method.</p> 12854 * 12855 * @param enabled True to enable duplication of the parent's drawable state, false 12856 * to disable it. 12857 * 12858 * @see #getDrawableState() 12859 * @see #isDuplicateParentStateEnabled() 12860 */ 12861 public void setDuplicateParentStateEnabled(boolean enabled) { 12862 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 12863 } 12864 12865 /** 12866 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 12867 * 12868 * @return True if this view's drawable state is duplicated from the parent, 12869 * false otherwise 12870 * 12871 * @see #getDrawableState() 12872 * @see #setDuplicateParentStateEnabled(boolean) 12873 */ 12874 public boolean isDuplicateParentStateEnabled() { 12875 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 12876 } 12877 12878 /** 12879 * <p>Specifies the type of layer backing this view. The layer can be 12880 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 12881 * {@link #LAYER_TYPE_HARDWARE}.</p> 12882 * 12883 * <p>A layer is associated with an optional {@link android.graphics.Paint} 12884 * instance that controls how the layer is composed on screen. The following 12885 * properties of the paint are taken into account when composing the layer:</p> 12886 * <ul> 12887 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 12888 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 12889 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 12890 * </ul> 12891 * 12892 * <p>If this view has an alpha value set to < 1.0 by calling 12893 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded 12894 * by this view's alpha value.</p> 12895 * 12896 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 12897 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 12898 * for more information on when and how to use layers.</p> 12899 * 12900 * @param layerType The type of layer to use with this view, must be one of 12901 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 12902 * {@link #LAYER_TYPE_HARDWARE} 12903 * @param paint The paint used to compose the layer. This argument is optional 12904 * and can be null. It is ignored when the layer type is 12905 * {@link #LAYER_TYPE_NONE} 12906 * 12907 * @see #getLayerType() 12908 * @see #LAYER_TYPE_NONE 12909 * @see #LAYER_TYPE_SOFTWARE 12910 * @see #LAYER_TYPE_HARDWARE 12911 * @see #setAlpha(float) 12912 * 12913 * @attr ref android.R.styleable#View_layerType 12914 */ 12915 public void setLayerType(int layerType, Paint paint) { 12916 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 12917 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 12918 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 12919 } 12920 12921 if (layerType == mLayerType) { 12922 if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) { 12923 mLayerPaint = paint == null ? new Paint() : paint; 12924 invalidateParentCaches(); 12925 invalidate(true); 12926 } 12927 return; 12928 } 12929 12930 // Destroy any previous software drawing cache if needed 12931 switch (mLayerType) { 12932 case LAYER_TYPE_HARDWARE: 12933 destroyLayer(false); 12934 // fall through - non-accelerated views may use software layer mechanism instead 12935 case LAYER_TYPE_SOFTWARE: 12936 destroyDrawingCache(); 12937 break; 12938 default: 12939 break; 12940 } 12941 12942 mLayerType = layerType; 12943 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE; 12944 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint); 12945 mLocalDirtyRect = layerDisabled ? null : new Rect(); 12946 12947 invalidateParentCaches(); 12948 invalidate(true); 12949 } 12950 12951 /** 12952 * Updates the {@link Paint} object used with the current layer (used only if the current 12953 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 12954 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 12955 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 12956 * ensure that the view gets redrawn immediately. 12957 * 12958 * <p>A layer is associated with an optional {@link android.graphics.Paint} 12959 * instance that controls how the layer is composed on screen. The following 12960 * properties of the paint are taken into account when composing the layer:</p> 12961 * <ul> 12962 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 12963 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 12964 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 12965 * </ul> 12966 * 12967 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 12968 * alpha value of the layer's paint is superceded by this view's alpha value.</p> 12969 * 12970 * @param paint The paint used to compose the layer. This argument is optional 12971 * and can be null. It is ignored when the layer type is 12972 * {@link #LAYER_TYPE_NONE} 12973 * 12974 * @see #setLayerType(int, android.graphics.Paint) 12975 */ 12976 public void setLayerPaint(Paint paint) { 12977 int layerType = getLayerType(); 12978 if (layerType != LAYER_TYPE_NONE) { 12979 mLayerPaint = paint == null ? new Paint() : paint; 12980 if (layerType == LAYER_TYPE_HARDWARE) { 12981 HardwareLayer layer = getHardwareLayer(); 12982 if (layer != null) { 12983 layer.setLayerPaint(paint); 12984 } 12985 invalidateViewProperty(false, false); 12986 } else { 12987 invalidate(); 12988 } 12989 } 12990 } 12991 12992 /** 12993 * Indicates whether this view has a static layer. A view with layer type 12994 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are 12995 * dynamic. 12996 */ 12997 boolean hasStaticLayer() { 12998 return true; 12999 } 13000 13001 /** 13002 * Indicates what type of layer is currently associated with this view. By default 13003 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 13004 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 13005 * for more information on the different types of layers. 13006 * 13007 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 13008 * {@link #LAYER_TYPE_HARDWARE} 13009 * 13010 * @see #setLayerType(int, android.graphics.Paint) 13011 * @see #buildLayer() 13012 * @see #LAYER_TYPE_NONE 13013 * @see #LAYER_TYPE_SOFTWARE 13014 * @see #LAYER_TYPE_HARDWARE 13015 */ 13016 public int getLayerType() { 13017 return mLayerType; 13018 } 13019 13020 /** 13021 * Forces this view's layer to be created and this view to be rendered 13022 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 13023 * invoking this method will have no effect. 13024 * 13025 * This method can for instance be used to render a view into its layer before 13026 * starting an animation. If this view is complex, rendering into the layer 13027 * before starting the animation will avoid skipping frames. 13028 * 13029 * @throws IllegalStateException If this view is not attached to a window 13030 * 13031 * @see #setLayerType(int, android.graphics.Paint) 13032 */ 13033 public void buildLayer() { 13034 if (mLayerType == LAYER_TYPE_NONE) return; 13035 13036 final AttachInfo attachInfo = mAttachInfo; 13037 if (attachInfo == null) { 13038 throw new IllegalStateException("This view must be attached to a window first"); 13039 } 13040 13041 switch (mLayerType) { 13042 case LAYER_TYPE_HARDWARE: 13043 if (attachInfo.mHardwareRenderer != null && 13044 attachInfo.mHardwareRenderer.isEnabled() && 13045 attachInfo.mHardwareRenderer.validate()) { 13046 getHardwareLayer(); 13047 // TODO: We need a better way to handle this case 13048 // If views have registered pre-draw listeners they need 13049 // to be notified before we build the layer. Those listeners 13050 // may however rely on other events to happen first so we 13051 // cannot just invoke them here until they don't cancel the 13052 // current frame 13053 if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) { 13054 attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates(); 13055 } 13056 } 13057 break; 13058 case LAYER_TYPE_SOFTWARE: 13059 buildDrawingCache(true); 13060 break; 13061 } 13062 } 13063 13064 /** 13065 * <p>Returns a hardware layer that can be used to draw this view again 13066 * without executing its draw method.</p> 13067 * 13068 * @return A HardwareLayer ready to render, or null if an error occurred. 13069 */ 13070 HardwareLayer getHardwareLayer() { 13071 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null || 13072 !mAttachInfo.mHardwareRenderer.isEnabled()) { 13073 return null; 13074 } 13075 13076 if (!mAttachInfo.mHardwareRenderer.validate()) return null; 13077 13078 final int width = mRight - mLeft; 13079 final int height = mBottom - mTop; 13080 13081 if (width == 0 || height == 0) { 13082 return null; 13083 } 13084 13085 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) { 13086 if (mHardwareLayer == null) { 13087 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer( 13088 width, height, isOpaque()); 13089 mLocalDirtyRect.set(0, 0, width, height); 13090 } else { 13091 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) { 13092 if (mHardwareLayer.resize(width, height)) { 13093 mLocalDirtyRect.set(0, 0, width, height); 13094 } 13095 } 13096 13097 // This should not be necessary but applications that change 13098 // the parameters of their background drawable without calling 13099 // this.setBackground(Drawable) can leave the view in a bad state 13100 // (for instance isOpaque() returns true, but the background is 13101 // not opaque.) 13102 computeOpaqueFlags(); 13103 13104 final boolean opaque = isOpaque(); 13105 if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) { 13106 mHardwareLayer.setOpaque(opaque); 13107 mLocalDirtyRect.set(0, 0, width, height); 13108 } 13109 } 13110 13111 // The layer is not valid if the underlying GPU resources cannot be allocated 13112 if (!mHardwareLayer.isValid()) { 13113 return null; 13114 } 13115 13116 mHardwareLayer.setLayerPaint(mLayerPaint); 13117 mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect); 13118 ViewRootImpl viewRoot = getViewRootImpl(); 13119 if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer); 13120 13121 mLocalDirtyRect.setEmpty(); 13122 } 13123 13124 return mHardwareLayer; 13125 } 13126 13127 /** 13128 * Destroys this View's hardware layer if possible. 13129 * 13130 * @return True if the layer was destroyed, false otherwise. 13131 * 13132 * @see #setLayerType(int, android.graphics.Paint) 13133 * @see #LAYER_TYPE_HARDWARE 13134 */ 13135 boolean destroyLayer(boolean valid) { 13136 if (mHardwareLayer != null) { 13137 AttachInfo info = mAttachInfo; 13138 if (info != null && info.mHardwareRenderer != null && 13139 info.mHardwareRenderer.isEnabled() && 13140 (valid || info.mHardwareRenderer.validate())) { 13141 13142 info.mHardwareRenderer.cancelLayerUpdate(mHardwareLayer); 13143 mHardwareLayer.destroy(); 13144 mHardwareLayer = null; 13145 13146 invalidate(true); 13147 invalidateParentCaches(); 13148 } 13149 return true; 13150 } 13151 return false; 13152 } 13153 13154 /** 13155 * Destroys all hardware rendering resources. This method is invoked 13156 * when the system needs to reclaim resources. Upon execution of this 13157 * method, you should free any OpenGL resources created by the view. 13158 * 13159 * Note: you <strong>must</strong> call 13160 * <code>super.destroyHardwareResources()</code> when overriding 13161 * this method. 13162 * 13163 * @hide 13164 */ 13165 protected void destroyHardwareResources() { 13166 resetDisplayList(); 13167 destroyLayer(true); 13168 } 13169 13170 /** 13171 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 13172 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 13173 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 13174 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 13175 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 13176 * null.</p> 13177 * 13178 * <p>Enabling the drawing cache is similar to 13179 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 13180 * acceleration is turned off. When hardware acceleration is turned on, enabling the 13181 * drawing cache has no effect on rendering because the system uses a different mechanism 13182 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 13183 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 13184 * for information on how to enable software and hardware layers.</p> 13185 * 13186 * <p>This API can be used to manually generate 13187 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 13188 * {@link #getDrawingCache()}.</p> 13189 * 13190 * @param enabled true to enable the drawing cache, false otherwise 13191 * 13192 * @see #isDrawingCacheEnabled() 13193 * @see #getDrawingCache() 13194 * @see #buildDrawingCache() 13195 * @see #setLayerType(int, android.graphics.Paint) 13196 */ 13197 public void setDrawingCacheEnabled(boolean enabled) { 13198 mCachingFailed = false; 13199 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 13200 } 13201 13202 /** 13203 * <p>Indicates whether the drawing cache is enabled for this view.</p> 13204 * 13205 * @return true if the drawing cache is enabled 13206 * 13207 * @see #setDrawingCacheEnabled(boolean) 13208 * @see #getDrawingCache() 13209 */ 13210 @ViewDebug.ExportedProperty(category = "drawing") 13211 public boolean isDrawingCacheEnabled() { 13212 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 13213 } 13214 13215 /** 13216 * Debugging utility which recursively outputs the dirty state of a view and its 13217 * descendants. 13218 * 13219 * @hide 13220 */ 13221 @SuppressWarnings({"UnusedDeclaration"}) 13222 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 13223 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) + 13224 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" + 13225 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) + 13226 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 13227 if (clear) { 13228 mPrivateFlags &= clearMask; 13229 } 13230 if (this instanceof ViewGroup) { 13231 ViewGroup parent = (ViewGroup) this; 13232 final int count = parent.getChildCount(); 13233 for (int i = 0; i < count; i++) { 13234 final View child = parent.getChildAt(i); 13235 child.outputDirtyFlags(indent + " ", clear, clearMask); 13236 } 13237 } 13238 } 13239 13240 /** 13241 * This method is used by ViewGroup to cause its children to restore or recreate their 13242 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 13243 * to recreate its own display list, which would happen if it went through the normal 13244 * draw/dispatchDraw mechanisms. 13245 * 13246 * @hide 13247 */ 13248 protected void dispatchGetDisplayList() {} 13249 13250 /** 13251 * A view that is not attached or hardware accelerated cannot create a display list. 13252 * This method checks these conditions and returns the appropriate result. 13253 * 13254 * @return true if view has the ability to create a display list, false otherwise. 13255 * 13256 * @hide 13257 */ 13258 public boolean canHaveDisplayList() { 13259 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 13260 } 13261 13262 /** 13263 * @return The {@link HardwareRenderer} associated with that view or null if 13264 * hardware rendering is not supported or this view is not attached 13265 * to a window. 13266 * 13267 * @hide 13268 */ 13269 public HardwareRenderer getHardwareRenderer() { 13270 if (mAttachInfo != null) { 13271 return mAttachInfo.mHardwareRenderer; 13272 } 13273 return null; 13274 } 13275 13276 /** 13277 * Returns a DisplayList. If the incoming displayList is null, one will be created. 13278 * Otherwise, the same display list will be returned (after having been rendered into 13279 * along the way, depending on the invalidation state of the view). 13280 * 13281 * @param displayList The previous version of this displayList, could be null. 13282 * @param isLayer Whether the requester of the display list is a layer. If so, 13283 * the view will avoid creating a layer inside the resulting display list. 13284 * @return A new or reused DisplayList object. 13285 */ 13286 private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) { 13287 if (!canHaveDisplayList()) { 13288 return null; 13289 } 13290 13291 if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || 13292 displayList == null || !displayList.isValid() || 13293 (!isLayer && mRecreateDisplayList))) { 13294 // Don't need to recreate the display list, just need to tell our 13295 // children to restore/recreate theirs 13296 if (displayList != null && displayList.isValid() && 13297 !isLayer && !mRecreateDisplayList) { 13298 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13299 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13300 dispatchGetDisplayList(); 13301 13302 return displayList; 13303 } 13304 13305 if (!isLayer) { 13306 // If we got here, we're recreating it. Mark it as such to ensure that 13307 // we copy in child display lists into ours in drawChild() 13308 mRecreateDisplayList = true; 13309 } 13310 if (displayList == null) { 13311 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(getClass().getName()); 13312 // If we're creating a new display list, make sure our parent gets invalidated 13313 // since they will need to recreate their display list to account for this 13314 // new child display list. 13315 invalidateParentCaches(); 13316 } 13317 13318 boolean caching = false; 13319 int width = mRight - mLeft; 13320 int height = mBottom - mTop; 13321 int layerType = getLayerType(); 13322 13323 final HardwareCanvas canvas = displayList.start(width, height); 13324 13325 try { 13326 if (!isLayer && layerType != LAYER_TYPE_NONE) { 13327 if (layerType == LAYER_TYPE_HARDWARE) { 13328 final HardwareLayer layer = getHardwareLayer(); 13329 if (layer != null && layer.isValid()) { 13330 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint); 13331 } else { 13332 canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint, 13333 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | 13334 Canvas.CLIP_TO_LAYER_SAVE_FLAG); 13335 } 13336 caching = true; 13337 } else { 13338 buildDrawingCache(true); 13339 Bitmap cache = getDrawingCache(true); 13340 if (cache != null) { 13341 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 13342 caching = true; 13343 } 13344 } 13345 } else { 13346 13347 computeScroll(); 13348 13349 canvas.translate(-mScrollX, -mScrollY); 13350 if (!isLayer) { 13351 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13352 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13353 } 13354 13355 // Fast path for layouts with no backgrounds 13356 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 13357 dispatchDraw(canvas); 13358 if (mOverlay != null && !mOverlay.isEmpty()) { 13359 mOverlay.getOverlayView().draw(canvas); 13360 } 13361 } else { 13362 draw(canvas); 13363 } 13364 } 13365 } finally { 13366 displayList.end(); 13367 displayList.setCaching(caching); 13368 if (isLayer) { 13369 displayList.setLeftTopRightBottom(0, 0, width, height); 13370 } else { 13371 setDisplayListProperties(displayList); 13372 } 13373 } 13374 } else if (!isLayer) { 13375 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13376 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13377 } 13378 13379 return displayList; 13380 } 13381 13382 /** 13383 * Get the DisplayList for the HardwareLayer 13384 * 13385 * @param layer The HardwareLayer whose DisplayList we want 13386 * @return A DisplayList fopr the specified HardwareLayer 13387 */ 13388 private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) { 13389 DisplayList displayList = getDisplayList(layer.getDisplayList(), true); 13390 layer.setDisplayList(displayList); 13391 return displayList; 13392 } 13393 13394 13395 /** 13396 * <p>Returns a display list that can be used to draw this view again 13397 * without executing its draw method.</p> 13398 * 13399 * @return A DisplayList ready to replay, or null if caching is not enabled. 13400 * 13401 * @hide 13402 */ 13403 public DisplayList getDisplayList() { 13404 mDisplayList = getDisplayList(mDisplayList, false); 13405 return mDisplayList; 13406 } 13407 13408 private void clearDisplayList() { 13409 if (mDisplayList != null) { 13410 mDisplayList.clear(); 13411 } 13412 } 13413 13414 private void resetDisplayList() { 13415 if (mDisplayList != null) { 13416 mDisplayList.reset(); 13417 } 13418 } 13419 13420 /** 13421 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 13422 * 13423 * @return A non-scaled bitmap representing this view or null if cache is disabled. 13424 * 13425 * @see #getDrawingCache(boolean) 13426 */ 13427 public Bitmap getDrawingCache() { 13428 return getDrawingCache(false); 13429 } 13430 13431 /** 13432 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 13433 * is null when caching is disabled. If caching is enabled and the cache is not ready, 13434 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 13435 * draw from the cache when the cache is enabled. To benefit from the cache, you must 13436 * request the drawing cache by calling this method and draw it on screen if the 13437 * returned bitmap is not null.</p> 13438 * 13439 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 13440 * this method will create a bitmap of the same size as this view. Because this bitmap 13441 * will be drawn scaled by the parent ViewGroup, the result on screen might show 13442 * scaling artifacts. To avoid such artifacts, you should call this method by setting 13443 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 13444 * size than the view. This implies that your application must be able to handle this 13445 * size.</p> 13446 * 13447 * @param autoScale Indicates whether the generated bitmap should be scaled based on 13448 * the current density of the screen when the application is in compatibility 13449 * mode. 13450 * 13451 * @return A bitmap representing this view or null if cache is disabled. 13452 * 13453 * @see #setDrawingCacheEnabled(boolean) 13454 * @see #isDrawingCacheEnabled() 13455 * @see #buildDrawingCache(boolean) 13456 * @see #destroyDrawingCache() 13457 */ 13458 public Bitmap getDrawingCache(boolean autoScale) { 13459 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 13460 return null; 13461 } 13462 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 13463 buildDrawingCache(autoScale); 13464 } 13465 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 13466 } 13467 13468 /** 13469 * <p>Frees the resources used by the drawing cache. If you call 13470 * {@link #buildDrawingCache()} manually without calling 13471 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 13472 * should cleanup the cache with this method afterwards.</p> 13473 * 13474 * @see #setDrawingCacheEnabled(boolean) 13475 * @see #buildDrawingCache() 13476 * @see #getDrawingCache() 13477 */ 13478 public void destroyDrawingCache() { 13479 if (mDrawingCache != null) { 13480 mDrawingCache.recycle(); 13481 mDrawingCache = null; 13482 } 13483 if (mUnscaledDrawingCache != null) { 13484 mUnscaledDrawingCache.recycle(); 13485 mUnscaledDrawingCache = null; 13486 } 13487 } 13488 13489 /** 13490 * Setting a solid background color for the drawing cache's bitmaps will improve 13491 * performance and memory usage. Note, though that this should only be used if this 13492 * view will always be drawn on top of a solid color. 13493 * 13494 * @param color The background color to use for the drawing cache's bitmap 13495 * 13496 * @see #setDrawingCacheEnabled(boolean) 13497 * @see #buildDrawingCache() 13498 * @see #getDrawingCache() 13499 */ 13500 public void setDrawingCacheBackgroundColor(int color) { 13501 if (color != mDrawingCacheBackgroundColor) { 13502 mDrawingCacheBackgroundColor = color; 13503 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 13504 } 13505 } 13506 13507 /** 13508 * @see #setDrawingCacheBackgroundColor(int) 13509 * 13510 * @return The background color to used for the drawing cache's bitmap 13511 */ 13512 public int getDrawingCacheBackgroundColor() { 13513 return mDrawingCacheBackgroundColor; 13514 } 13515 13516 /** 13517 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 13518 * 13519 * @see #buildDrawingCache(boolean) 13520 */ 13521 public void buildDrawingCache() { 13522 buildDrawingCache(false); 13523 } 13524 13525 /** 13526 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 13527 * 13528 * <p>If you call {@link #buildDrawingCache()} manually without calling 13529 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 13530 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 13531 * 13532 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 13533 * this method will create a bitmap of the same size as this view. Because this bitmap 13534 * will be drawn scaled by the parent ViewGroup, the result on screen might show 13535 * scaling artifacts. To avoid such artifacts, you should call this method by setting 13536 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 13537 * size than the view. This implies that your application must be able to handle this 13538 * size.</p> 13539 * 13540 * <p>You should avoid calling this method when hardware acceleration is enabled. If 13541 * you do not need the drawing cache bitmap, calling this method will increase memory 13542 * usage and cause the view to be rendered in software once, thus negatively impacting 13543 * performance.</p> 13544 * 13545 * @see #getDrawingCache() 13546 * @see #destroyDrawingCache() 13547 */ 13548 public void buildDrawingCache(boolean autoScale) { 13549 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 13550 mDrawingCache == null : mUnscaledDrawingCache == null)) { 13551 mCachingFailed = false; 13552 13553 int width = mRight - mLeft; 13554 int height = mBottom - mTop; 13555 13556 final AttachInfo attachInfo = mAttachInfo; 13557 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 13558 13559 if (autoScale && scalingRequired) { 13560 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 13561 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 13562 } 13563 13564 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 13565 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 13566 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 13567 13568 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 13569 final long drawingCacheSize = 13570 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 13571 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 13572 if (width > 0 && height > 0) { 13573 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs " 13574 + projectedBitmapSize + " bytes, only " 13575 + drawingCacheSize + " available"); 13576 } 13577 destroyDrawingCache(); 13578 mCachingFailed = true; 13579 return; 13580 } 13581 13582 boolean clear = true; 13583 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 13584 13585 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 13586 Bitmap.Config quality; 13587 if (!opaque) { 13588 // Never pick ARGB_4444 because it looks awful 13589 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 13590 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 13591 case DRAWING_CACHE_QUALITY_AUTO: 13592 case DRAWING_CACHE_QUALITY_LOW: 13593 case DRAWING_CACHE_QUALITY_HIGH: 13594 default: 13595 quality = Bitmap.Config.ARGB_8888; 13596 break; 13597 } 13598 } else { 13599 // Optimization for translucent windows 13600 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 13601 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 13602 } 13603 13604 // Try to cleanup memory 13605 if (bitmap != null) bitmap.recycle(); 13606 13607 try { 13608 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 13609 width, height, quality); 13610 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 13611 if (autoScale) { 13612 mDrawingCache = bitmap; 13613 } else { 13614 mUnscaledDrawingCache = bitmap; 13615 } 13616 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 13617 } catch (OutOfMemoryError e) { 13618 // If there is not enough memory to create the bitmap cache, just 13619 // ignore the issue as bitmap caches are not required to draw the 13620 // view hierarchy 13621 if (autoScale) { 13622 mDrawingCache = null; 13623 } else { 13624 mUnscaledDrawingCache = null; 13625 } 13626 mCachingFailed = true; 13627 return; 13628 } 13629 13630 clear = drawingCacheBackgroundColor != 0; 13631 } 13632 13633 Canvas canvas; 13634 if (attachInfo != null) { 13635 canvas = attachInfo.mCanvas; 13636 if (canvas == null) { 13637 canvas = new Canvas(); 13638 } 13639 canvas.setBitmap(bitmap); 13640 // Temporarily clobber the cached Canvas in case one of our children 13641 // is also using a drawing cache. Without this, the children would 13642 // steal the canvas by attaching their own bitmap to it and bad, bad 13643 // thing would happen (invisible views, corrupted drawings, etc.) 13644 attachInfo.mCanvas = null; 13645 } else { 13646 // This case should hopefully never or seldom happen 13647 canvas = new Canvas(bitmap); 13648 } 13649 13650 if (clear) { 13651 bitmap.eraseColor(drawingCacheBackgroundColor); 13652 } 13653 13654 computeScroll(); 13655 final int restoreCount = canvas.save(); 13656 13657 if (autoScale && scalingRequired) { 13658 final float scale = attachInfo.mApplicationScale; 13659 canvas.scale(scale, scale); 13660 } 13661 13662 canvas.translate(-mScrollX, -mScrollY); 13663 13664 mPrivateFlags |= PFLAG_DRAWN; 13665 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 13666 mLayerType != LAYER_TYPE_NONE) { 13667 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 13668 } 13669 13670 // Fast path for layouts with no backgrounds 13671 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 13672 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13673 dispatchDraw(canvas); 13674 if (mOverlay != null && !mOverlay.isEmpty()) { 13675 mOverlay.getOverlayView().draw(canvas); 13676 } 13677 } else { 13678 draw(canvas); 13679 } 13680 13681 canvas.restoreToCount(restoreCount); 13682 canvas.setBitmap(null); 13683 13684 if (attachInfo != null) { 13685 // Restore the cached Canvas for our siblings 13686 attachInfo.mCanvas = canvas; 13687 } 13688 } 13689 } 13690 13691 /** 13692 * Create a snapshot of the view into a bitmap. We should probably make 13693 * some form of this public, but should think about the API. 13694 */ 13695 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 13696 int width = mRight - mLeft; 13697 int height = mBottom - mTop; 13698 13699 final AttachInfo attachInfo = mAttachInfo; 13700 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 13701 width = (int) ((width * scale) + 0.5f); 13702 height = (int) ((height * scale) + 0.5f); 13703 13704 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 13705 width > 0 ? width : 1, height > 0 ? height : 1, quality); 13706 if (bitmap == null) { 13707 throw new OutOfMemoryError(); 13708 } 13709 13710 Resources resources = getResources(); 13711 if (resources != null) { 13712 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 13713 } 13714 13715 Canvas canvas; 13716 if (attachInfo != null) { 13717 canvas = attachInfo.mCanvas; 13718 if (canvas == null) { 13719 canvas = new Canvas(); 13720 } 13721 canvas.setBitmap(bitmap); 13722 // Temporarily clobber the cached Canvas in case one of our children 13723 // is also using a drawing cache. Without this, the children would 13724 // steal the canvas by attaching their own bitmap to it and bad, bad 13725 // things would happen (invisible views, corrupted drawings, etc.) 13726 attachInfo.mCanvas = null; 13727 } else { 13728 // This case should hopefully never or seldom happen 13729 canvas = new Canvas(bitmap); 13730 } 13731 13732 if ((backgroundColor & 0xff000000) != 0) { 13733 bitmap.eraseColor(backgroundColor); 13734 } 13735 13736 computeScroll(); 13737 final int restoreCount = canvas.save(); 13738 canvas.scale(scale, scale); 13739 canvas.translate(-mScrollX, -mScrollY); 13740 13741 // Temporarily remove the dirty mask 13742 int flags = mPrivateFlags; 13743 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13744 13745 // Fast path for layouts with no backgrounds 13746 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 13747 dispatchDraw(canvas); 13748 if (mOverlay != null && !mOverlay.isEmpty()) { 13749 mOverlay.getOverlayView().draw(canvas); 13750 } 13751 } else { 13752 draw(canvas); 13753 } 13754 13755 mPrivateFlags = flags; 13756 13757 canvas.restoreToCount(restoreCount); 13758 canvas.setBitmap(null); 13759 13760 if (attachInfo != null) { 13761 // Restore the cached Canvas for our siblings 13762 attachInfo.mCanvas = canvas; 13763 } 13764 13765 return bitmap; 13766 } 13767 13768 /** 13769 * Indicates whether this View is currently in edit mode. A View is usually 13770 * in edit mode when displayed within a developer tool. For instance, if 13771 * this View is being drawn by a visual user interface builder, this method 13772 * should return true. 13773 * 13774 * Subclasses should check the return value of this method to provide 13775 * different behaviors if their normal behavior might interfere with the 13776 * host environment. For instance: the class spawns a thread in its 13777 * constructor, the drawing code relies on device-specific features, etc. 13778 * 13779 * This method is usually checked in the drawing code of custom widgets. 13780 * 13781 * @return True if this View is in edit mode, false otherwise. 13782 */ 13783 public boolean isInEditMode() { 13784 return false; 13785 } 13786 13787 /** 13788 * If the View draws content inside its padding and enables fading edges, 13789 * it needs to support padding offsets. Padding offsets are added to the 13790 * fading edges to extend the length of the fade so that it covers pixels 13791 * drawn inside the padding. 13792 * 13793 * Subclasses of this class should override this method if they need 13794 * to draw content inside the padding. 13795 * 13796 * @return True if padding offset must be applied, false otherwise. 13797 * 13798 * @see #getLeftPaddingOffset() 13799 * @see #getRightPaddingOffset() 13800 * @see #getTopPaddingOffset() 13801 * @see #getBottomPaddingOffset() 13802 * 13803 * @since CURRENT 13804 */ 13805 protected boolean isPaddingOffsetRequired() { 13806 return false; 13807 } 13808 13809 /** 13810 * Amount by which to extend the left fading region. Called only when 13811 * {@link #isPaddingOffsetRequired()} returns true. 13812 * 13813 * @return The left padding offset in pixels. 13814 * 13815 * @see #isPaddingOffsetRequired() 13816 * 13817 * @since CURRENT 13818 */ 13819 protected int getLeftPaddingOffset() { 13820 return 0; 13821 } 13822 13823 /** 13824 * Amount by which to extend the right fading region. Called only when 13825 * {@link #isPaddingOffsetRequired()} returns true. 13826 * 13827 * @return The right padding offset in pixels. 13828 * 13829 * @see #isPaddingOffsetRequired() 13830 * 13831 * @since CURRENT 13832 */ 13833 protected int getRightPaddingOffset() { 13834 return 0; 13835 } 13836 13837 /** 13838 * Amount by which to extend the top fading region. Called only when 13839 * {@link #isPaddingOffsetRequired()} returns true. 13840 * 13841 * @return The top padding offset in pixels. 13842 * 13843 * @see #isPaddingOffsetRequired() 13844 * 13845 * @since CURRENT 13846 */ 13847 protected int getTopPaddingOffset() { 13848 return 0; 13849 } 13850 13851 /** 13852 * Amount by which to extend the bottom fading region. Called only when 13853 * {@link #isPaddingOffsetRequired()} returns true. 13854 * 13855 * @return The bottom padding offset in pixels. 13856 * 13857 * @see #isPaddingOffsetRequired() 13858 * 13859 * @since CURRENT 13860 */ 13861 protected int getBottomPaddingOffset() { 13862 return 0; 13863 } 13864 13865 /** 13866 * @hide 13867 * @param offsetRequired 13868 */ 13869 protected int getFadeTop(boolean offsetRequired) { 13870 int top = mPaddingTop; 13871 if (offsetRequired) top += getTopPaddingOffset(); 13872 return top; 13873 } 13874 13875 /** 13876 * @hide 13877 * @param offsetRequired 13878 */ 13879 protected int getFadeHeight(boolean offsetRequired) { 13880 int padding = mPaddingTop; 13881 if (offsetRequired) padding += getTopPaddingOffset(); 13882 return mBottom - mTop - mPaddingBottom - padding; 13883 } 13884 13885 /** 13886 * <p>Indicates whether this view is attached to a hardware accelerated 13887 * window or not.</p> 13888 * 13889 * <p>Even if this method returns true, it does not mean that every call 13890 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 13891 * accelerated {@link android.graphics.Canvas}. For instance, if this view 13892 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 13893 * window is hardware accelerated, 13894 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 13895 * return false, and this method will return true.</p> 13896 * 13897 * @return True if the view is attached to a window and the window is 13898 * hardware accelerated; false in any other case. 13899 */ 13900 public boolean isHardwareAccelerated() { 13901 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 13902 } 13903 13904 /** 13905 * Sets a rectangular area on this view to which the view will be clipped 13906 * when it is drawn. Setting the value to null will remove the clip bounds 13907 * and the view will draw normally, using its full bounds. 13908 * 13909 * @param clipBounds The rectangular area, in the local coordinates of 13910 * this view, to which future drawing operations will be clipped. 13911 */ 13912 public void setClipBounds(Rect clipBounds) { 13913 if (clipBounds != null) { 13914 if (clipBounds.equals(mClipBounds)) { 13915 return; 13916 } 13917 if (mClipBounds == null) { 13918 invalidate(); 13919 mClipBounds = new Rect(clipBounds); 13920 } else { 13921 invalidate(Math.min(mClipBounds.left, clipBounds.left), 13922 Math.min(mClipBounds.top, clipBounds.top), 13923 Math.max(mClipBounds.right, clipBounds.right), 13924 Math.max(mClipBounds.bottom, clipBounds.bottom)); 13925 mClipBounds.set(clipBounds); 13926 } 13927 } else { 13928 if (mClipBounds != null) { 13929 invalidate(); 13930 mClipBounds = null; 13931 } 13932 } 13933 } 13934 13935 /** 13936 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 13937 * 13938 * @return A copy of the current clip bounds if clip bounds are set, 13939 * otherwise null. 13940 */ 13941 public Rect getClipBounds() { 13942 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 13943 } 13944 13945 /** 13946 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 13947 * case of an active Animation being run on the view. 13948 */ 13949 private boolean drawAnimation(ViewGroup parent, long drawingTime, 13950 Animation a, boolean scalingRequired) { 13951 Transformation invalidationTransform; 13952 final int flags = parent.mGroupFlags; 13953 final boolean initialized = a.isInitialized(); 13954 if (!initialized) { 13955 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 13956 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 13957 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 13958 onAnimationStart(); 13959 } 13960 13961 final Transformation t = parent.getChildTransformation(); 13962 boolean more = a.getTransformation(drawingTime, t, 1f); 13963 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 13964 if (parent.mInvalidationTransformation == null) { 13965 parent.mInvalidationTransformation = new Transformation(); 13966 } 13967 invalidationTransform = parent.mInvalidationTransformation; 13968 a.getTransformation(drawingTime, invalidationTransform, 1f); 13969 } else { 13970 invalidationTransform = t; 13971 } 13972 13973 if (more) { 13974 if (!a.willChangeBounds()) { 13975 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 13976 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 13977 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 13978 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 13979 // The child need to draw an animation, potentially offscreen, so 13980 // make sure we do not cancel invalidate requests 13981 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 13982 parent.invalidate(mLeft, mTop, mRight, mBottom); 13983 } 13984 } else { 13985 if (parent.mInvalidateRegion == null) { 13986 parent.mInvalidateRegion = new RectF(); 13987 } 13988 final RectF region = parent.mInvalidateRegion; 13989 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 13990 invalidationTransform); 13991 13992 // The child need to draw an animation, potentially offscreen, so 13993 // make sure we do not cancel invalidate requests 13994 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 13995 13996 final int left = mLeft + (int) region.left; 13997 final int top = mTop + (int) region.top; 13998 parent.invalidate(left, top, left + (int) (region.width() + .5f), 13999 top + (int) (region.height() + .5f)); 14000 } 14001 } 14002 return more; 14003 } 14004 14005 /** 14006 * This method is called by getDisplayList() when a display list is created or re-rendered. 14007 * It sets or resets the current value of all properties on that display list (resetting is 14008 * necessary when a display list is being re-created, because we need to make sure that 14009 * previously-set transform values 14010 */ 14011 void setDisplayListProperties(DisplayList displayList) { 14012 if (displayList != null) { 14013 displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 14014 displayList.setHasOverlappingRendering(hasOverlappingRendering()); 14015 if (mParent instanceof ViewGroup) { 14016 displayList.setClipToBounds( 14017 (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); 14018 } 14019 float alpha = 1; 14020 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 14021 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 14022 ViewGroup parentVG = (ViewGroup) mParent; 14023 final Transformation t = parentVG.getChildTransformation(); 14024 if (parentVG.getChildStaticTransformation(this, t)) { 14025 final int transformType = t.getTransformationType(); 14026 if (transformType != Transformation.TYPE_IDENTITY) { 14027 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 14028 alpha = t.getAlpha(); 14029 } 14030 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 14031 displayList.setMatrix(t.getMatrix()); 14032 } 14033 } 14034 } 14035 } 14036 if (mTransformationInfo != null) { 14037 alpha *= getFinalAlpha(); 14038 if (alpha < 1) { 14039 final int multipliedAlpha = (int) (255 * alpha); 14040 if (onSetAlpha(multipliedAlpha)) { 14041 alpha = 1; 14042 } 14043 } 14044 displayList.setTransformationInfo(alpha, 14045 mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY, 14046 mTransformationInfo.mRotation, mTransformationInfo.mRotationX, 14047 mTransformationInfo.mRotationY, mTransformationInfo.mScaleX, 14048 mTransformationInfo.mScaleY); 14049 if (mTransformationInfo.mCamera == null) { 14050 mTransformationInfo.mCamera = new Camera(); 14051 mTransformationInfo.matrix3D = new Matrix(); 14052 } 14053 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ()); 14054 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) { 14055 displayList.setPivotX(getPivotX()); 14056 displayList.setPivotY(getPivotY()); 14057 } 14058 } else if (alpha < 1) { 14059 displayList.setAlpha(alpha); 14060 } 14061 } 14062 } 14063 14064 /** 14065 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 14066 * This draw() method is an implementation detail and is not intended to be overridden or 14067 * to be called from anywhere else other than ViewGroup.drawChild(). 14068 */ 14069 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 14070 boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 14071 boolean more = false; 14072 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 14073 final int flags = parent.mGroupFlags; 14074 14075 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) { 14076 parent.getChildTransformation().clear(); 14077 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14078 } 14079 14080 Transformation transformToApply = null; 14081 boolean concatMatrix = false; 14082 14083 boolean scalingRequired = false; 14084 boolean caching; 14085 int layerType = getLayerType(); 14086 14087 final boolean hardwareAccelerated = canvas.isHardwareAccelerated(); 14088 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 || 14089 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) { 14090 caching = true; 14091 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList 14092 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; 14093 } else { 14094 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated; 14095 } 14096 14097 final Animation a = getAnimation(); 14098 if (a != null) { 14099 more = drawAnimation(parent, drawingTime, a, scalingRequired); 14100 concatMatrix = a.willChangeTransformationMatrix(); 14101 if (concatMatrix) { 14102 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 14103 } 14104 transformToApply = parent.getChildTransformation(); 14105 } else { 14106 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == 14107 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) { 14108 // No longer animating: clear out old animation matrix 14109 mDisplayList.setAnimationMatrix(null); 14110 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 14111 } 14112 if (!useDisplayListProperties && 14113 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 14114 final Transformation t = parent.getChildTransformation(); 14115 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 14116 if (hasTransform) { 14117 final int transformType = t.getTransformationType(); 14118 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 14119 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 14120 } 14121 } 14122 } 14123 14124 concatMatrix |= !childHasIdentityMatrix; 14125 14126 // Sets the flag as early as possible to allow draw() implementations 14127 // to call invalidate() successfully when doing animations 14128 mPrivateFlags |= PFLAG_DRAWN; 14129 14130 if (!concatMatrix && 14131 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 14132 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 14133 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 14134 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 14135 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 14136 return more; 14137 } 14138 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 14139 14140 if (hardwareAccelerated) { 14141 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 14142 // retain the flag's value temporarily in the mRecreateDisplayList flag 14143 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED; 14144 mPrivateFlags &= ~PFLAG_INVALIDATED; 14145 } 14146 14147 DisplayList displayList = null; 14148 Bitmap cache = null; 14149 boolean hasDisplayList = false; 14150 if (caching) { 14151 if (!hardwareAccelerated) { 14152 if (layerType != LAYER_TYPE_NONE) { 14153 layerType = LAYER_TYPE_SOFTWARE; 14154 buildDrawingCache(true); 14155 } 14156 cache = getDrawingCache(true); 14157 } else { 14158 switch (layerType) { 14159 case LAYER_TYPE_SOFTWARE: 14160 if (useDisplayListProperties) { 14161 hasDisplayList = canHaveDisplayList(); 14162 } else { 14163 buildDrawingCache(true); 14164 cache = getDrawingCache(true); 14165 } 14166 break; 14167 case LAYER_TYPE_HARDWARE: 14168 if (useDisplayListProperties) { 14169 hasDisplayList = canHaveDisplayList(); 14170 } 14171 break; 14172 case LAYER_TYPE_NONE: 14173 // Delay getting the display list until animation-driven alpha values are 14174 // set up and possibly passed on to the view 14175 hasDisplayList = canHaveDisplayList(); 14176 break; 14177 } 14178 } 14179 } 14180 useDisplayListProperties &= hasDisplayList; 14181 if (useDisplayListProperties) { 14182 displayList = getDisplayList(); 14183 if (!displayList.isValid()) { 14184 // Uncommon, but possible. If a view is removed from the hierarchy during the call 14185 // to getDisplayList(), the display list will be marked invalid and we should not 14186 // try to use it again. 14187 displayList = null; 14188 hasDisplayList = false; 14189 useDisplayListProperties = false; 14190 } 14191 } 14192 14193 int sx = 0; 14194 int sy = 0; 14195 if (!hasDisplayList) { 14196 computeScroll(); 14197 sx = mScrollX; 14198 sy = mScrollY; 14199 } 14200 14201 final boolean hasNoCache = cache == null || hasDisplayList; 14202 final boolean offsetForScroll = cache == null && !hasDisplayList && 14203 layerType != LAYER_TYPE_HARDWARE; 14204 14205 int restoreTo = -1; 14206 if (!useDisplayListProperties || transformToApply != null) { 14207 restoreTo = canvas.save(); 14208 } 14209 if (offsetForScroll) { 14210 canvas.translate(mLeft - sx, mTop - sy); 14211 } else { 14212 if (!useDisplayListProperties) { 14213 canvas.translate(mLeft, mTop); 14214 } 14215 if (scalingRequired) { 14216 if (useDisplayListProperties) { 14217 // TODO: Might not need this if we put everything inside the DL 14218 restoreTo = canvas.save(); 14219 } 14220 // mAttachInfo cannot be null, otherwise scalingRequired == false 14221 final float scale = 1.0f / mAttachInfo.mApplicationScale; 14222 canvas.scale(scale, scale); 14223 } 14224 } 14225 14226 float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha()); 14227 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || 14228 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) { 14229 if (transformToApply != null || !childHasIdentityMatrix) { 14230 int transX = 0; 14231 int transY = 0; 14232 14233 if (offsetForScroll) { 14234 transX = -sx; 14235 transY = -sy; 14236 } 14237 14238 if (transformToApply != null) { 14239 if (concatMatrix) { 14240 if (useDisplayListProperties) { 14241 displayList.setAnimationMatrix(transformToApply.getMatrix()); 14242 } else { 14243 // Undo the scroll translation, apply the transformation matrix, 14244 // then redo the scroll translate to get the correct result. 14245 canvas.translate(-transX, -transY); 14246 canvas.concat(transformToApply.getMatrix()); 14247 canvas.translate(transX, transY); 14248 } 14249 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14250 } 14251 14252 float transformAlpha = transformToApply.getAlpha(); 14253 if (transformAlpha < 1) { 14254 alpha *= transformAlpha; 14255 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14256 } 14257 } 14258 14259 if (!childHasIdentityMatrix && !useDisplayListProperties) { 14260 canvas.translate(-transX, -transY); 14261 canvas.concat(getMatrix()); 14262 canvas.translate(transX, transY); 14263 } 14264 } 14265 14266 // Deal with alpha if it is or used to be <1 14267 if (alpha < 1 || 14268 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) { 14269 if (alpha < 1) { 14270 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 14271 } else { 14272 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 14273 } 14274 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14275 if (hasNoCache) { 14276 final int multipliedAlpha = (int) (255 * alpha); 14277 if (!onSetAlpha(multipliedAlpha)) { 14278 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 14279 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 || 14280 layerType != LAYER_TYPE_NONE) { 14281 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; 14282 } 14283 if (useDisplayListProperties) { 14284 displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 14285 } else if (layerType == LAYER_TYPE_NONE) { 14286 final int scrollX = hasDisplayList ? 0 : sx; 14287 final int scrollY = hasDisplayList ? 0 : sy; 14288 canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft, 14289 scrollY + mBottom - mTop, multipliedAlpha, layerFlags); 14290 } 14291 } else { 14292 // Alpha is handled by the child directly, clobber the layer's alpha 14293 mPrivateFlags |= PFLAG_ALPHA_SET; 14294 } 14295 } 14296 } 14297 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 14298 onSetAlpha(255); 14299 mPrivateFlags &= ~PFLAG_ALPHA_SET; 14300 } 14301 14302 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN && 14303 !useDisplayListProperties && cache == null) { 14304 if (offsetForScroll) { 14305 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop)); 14306 } else { 14307 if (!scalingRequired || cache == null) { 14308 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop); 14309 } else { 14310 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 14311 } 14312 } 14313 } 14314 14315 if (!useDisplayListProperties && hasDisplayList) { 14316 displayList = getDisplayList(); 14317 if (!displayList.isValid()) { 14318 // Uncommon, but possible. If a view is removed from the hierarchy during the call 14319 // to getDisplayList(), the display list will be marked invalid and we should not 14320 // try to use it again. 14321 displayList = null; 14322 hasDisplayList = false; 14323 } 14324 } 14325 14326 if (hasNoCache) { 14327 boolean layerRendered = false; 14328 if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) { 14329 final HardwareLayer layer = getHardwareLayer(); 14330 if (layer != null && layer.isValid()) { 14331 mLayerPaint.setAlpha((int) (alpha * 255)); 14332 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint); 14333 layerRendered = true; 14334 } else { 14335 final int scrollX = hasDisplayList ? 0 : sx; 14336 final int scrollY = hasDisplayList ? 0 : sy; 14337 canvas.saveLayer(scrollX, scrollY, 14338 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint, 14339 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); 14340 } 14341 } 14342 14343 if (!layerRendered) { 14344 if (!hasDisplayList) { 14345 // Fast path for layouts with no backgrounds 14346 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 14347 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14348 dispatchDraw(canvas); 14349 } else { 14350 draw(canvas); 14351 } 14352 } else { 14353 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14354 ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags); 14355 } 14356 } 14357 } else if (cache != null) { 14358 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14359 Paint cachePaint; 14360 14361 if (layerType == LAYER_TYPE_NONE) { 14362 cachePaint = parent.mCachePaint; 14363 if (cachePaint == null) { 14364 cachePaint = new Paint(); 14365 cachePaint.setDither(false); 14366 parent.mCachePaint = cachePaint; 14367 } 14368 if (alpha < 1) { 14369 cachePaint.setAlpha((int) (alpha * 255)); 14370 parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; 14371 } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) { 14372 cachePaint.setAlpha(255); 14373 parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; 14374 } 14375 } else { 14376 cachePaint = mLayerPaint; 14377 cachePaint.setAlpha((int) (alpha * 255)); 14378 } 14379 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 14380 } 14381 14382 if (restoreTo >= 0) { 14383 canvas.restoreToCount(restoreTo); 14384 } 14385 14386 if (a != null && !more) { 14387 if (!hardwareAccelerated && !a.getFillAfter()) { 14388 onSetAlpha(255); 14389 } 14390 parent.finishAnimatingView(this, a); 14391 } 14392 14393 if (more && hardwareAccelerated) { 14394 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 14395 // alpha animations should cause the child to recreate its display list 14396 invalidate(true); 14397 } 14398 } 14399 14400 mRecreateDisplayList = false; 14401 14402 return more; 14403 } 14404 14405 /** 14406 * Manually render this view (and all of its children) to the given Canvas. 14407 * The view must have already done a full layout before this function is 14408 * called. When implementing a view, implement 14409 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 14410 * If you do need to override this method, call the superclass version. 14411 * 14412 * @param canvas The Canvas to which the View is rendered. 14413 */ 14414 public void draw(Canvas canvas) { 14415 if (mClipBounds != null) { 14416 canvas.clipRect(mClipBounds); 14417 } 14418 final int privateFlags = mPrivateFlags; 14419 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 14420 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 14421 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 14422 14423 /* 14424 * Draw traversal performs several drawing steps which must be executed 14425 * in the appropriate order: 14426 * 14427 * 1. Draw the background 14428 * 2. If necessary, save the canvas' layers to prepare for fading 14429 * 3. Draw view's content 14430 * 4. Draw children 14431 * 5. If necessary, draw the fading edges and restore layers 14432 * 6. Draw decorations (scrollbars for instance) 14433 */ 14434 14435 // Step 1, draw the background, if needed 14436 int saveCount; 14437 14438 if (!dirtyOpaque) { 14439 final Drawable background = mBackground; 14440 if (background != null) { 14441 final int scrollX = mScrollX; 14442 final int scrollY = mScrollY; 14443 14444 if (mBackgroundSizeChanged) { 14445 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 14446 mBackgroundSizeChanged = false; 14447 } 14448 14449 if ((scrollX | scrollY) == 0) { 14450 background.draw(canvas); 14451 } else { 14452 canvas.translate(scrollX, scrollY); 14453 background.draw(canvas); 14454 canvas.translate(-scrollX, -scrollY); 14455 } 14456 } 14457 } 14458 14459 // skip step 2 & 5 if possible (common case) 14460 final int viewFlags = mViewFlags; 14461 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 14462 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 14463 if (!verticalEdges && !horizontalEdges) { 14464 // Step 3, draw the content 14465 if (!dirtyOpaque) onDraw(canvas); 14466 14467 // Step 4, draw the children 14468 dispatchDraw(canvas); 14469 14470 // Step 6, draw decorations (scrollbars) 14471 onDrawScrollBars(canvas); 14472 14473 if (mOverlay != null && !mOverlay.isEmpty()) { 14474 mOverlay.getOverlayView().dispatchDraw(canvas); 14475 } 14476 14477 // we're done... 14478 return; 14479 } 14480 14481 /* 14482 * Here we do the full fledged routine... 14483 * (this is an uncommon case where speed matters less, 14484 * this is why we repeat some of the tests that have been 14485 * done above) 14486 */ 14487 14488 boolean drawTop = false; 14489 boolean drawBottom = false; 14490 boolean drawLeft = false; 14491 boolean drawRight = false; 14492 14493 float topFadeStrength = 0.0f; 14494 float bottomFadeStrength = 0.0f; 14495 float leftFadeStrength = 0.0f; 14496 float rightFadeStrength = 0.0f; 14497 14498 // Step 2, save the canvas' layers 14499 int paddingLeft = mPaddingLeft; 14500 14501 final boolean offsetRequired = isPaddingOffsetRequired(); 14502 if (offsetRequired) { 14503 paddingLeft += getLeftPaddingOffset(); 14504 } 14505 14506 int left = mScrollX + paddingLeft; 14507 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 14508 int top = mScrollY + getFadeTop(offsetRequired); 14509 int bottom = top + getFadeHeight(offsetRequired); 14510 14511 if (offsetRequired) { 14512 right += getRightPaddingOffset(); 14513 bottom += getBottomPaddingOffset(); 14514 } 14515 14516 final ScrollabilityCache scrollabilityCache = mScrollCache; 14517 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 14518 int length = (int) fadeHeight; 14519 14520 // clip the fade length if top and bottom fades overlap 14521 // overlapping fades produce odd-looking artifacts 14522 if (verticalEdges && (top + length > bottom - length)) { 14523 length = (bottom - top) / 2; 14524 } 14525 14526 // also clip horizontal fades if necessary 14527 if (horizontalEdges && (left + length > right - length)) { 14528 length = (right - left) / 2; 14529 } 14530 14531 if (verticalEdges) { 14532 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 14533 drawTop = topFadeStrength * fadeHeight > 1.0f; 14534 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 14535 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 14536 } 14537 14538 if (horizontalEdges) { 14539 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 14540 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 14541 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 14542 drawRight = rightFadeStrength * fadeHeight > 1.0f; 14543 } 14544 14545 saveCount = canvas.getSaveCount(); 14546 14547 int solidColor = getSolidColor(); 14548 if (solidColor == 0) { 14549 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 14550 14551 if (drawTop) { 14552 canvas.saveLayer(left, top, right, top + length, null, flags); 14553 } 14554 14555 if (drawBottom) { 14556 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 14557 } 14558 14559 if (drawLeft) { 14560 canvas.saveLayer(left, top, left + length, bottom, null, flags); 14561 } 14562 14563 if (drawRight) { 14564 canvas.saveLayer(right - length, top, right, bottom, null, flags); 14565 } 14566 } else { 14567 scrollabilityCache.setFadeColor(solidColor); 14568 } 14569 14570 // Step 3, draw the content 14571 if (!dirtyOpaque) onDraw(canvas); 14572 14573 // Step 4, draw the children 14574 dispatchDraw(canvas); 14575 14576 // Step 5, draw the fade effect and restore layers 14577 final Paint p = scrollabilityCache.paint; 14578 final Matrix matrix = scrollabilityCache.matrix; 14579 final Shader fade = scrollabilityCache.shader; 14580 14581 if (drawTop) { 14582 matrix.setScale(1, fadeHeight * topFadeStrength); 14583 matrix.postTranslate(left, top); 14584 fade.setLocalMatrix(matrix); 14585 canvas.drawRect(left, top, right, top + length, p); 14586 } 14587 14588 if (drawBottom) { 14589 matrix.setScale(1, fadeHeight * bottomFadeStrength); 14590 matrix.postRotate(180); 14591 matrix.postTranslate(left, bottom); 14592 fade.setLocalMatrix(matrix); 14593 canvas.drawRect(left, bottom - length, right, bottom, p); 14594 } 14595 14596 if (drawLeft) { 14597 matrix.setScale(1, fadeHeight * leftFadeStrength); 14598 matrix.postRotate(-90); 14599 matrix.postTranslate(left, top); 14600 fade.setLocalMatrix(matrix); 14601 canvas.drawRect(left, top, left + length, bottom, p); 14602 } 14603 14604 if (drawRight) { 14605 matrix.setScale(1, fadeHeight * rightFadeStrength); 14606 matrix.postRotate(90); 14607 matrix.postTranslate(right, top); 14608 fade.setLocalMatrix(matrix); 14609 canvas.drawRect(right - length, top, right, bottom, p); 14610 } 14611 14612 canvas.restoreToCount(saveCount); 14613 14614 // Step 6, draw decorations (scrollbars) 14615 onDrawScrollBars(canvas); 14616 14617 if (mOverlay != null && !mOverlay.isEmpty()) { 14618 mOverlay.getOverlayView().dispatchDraw(canvas); 14619 } 14620 } 14621 14622 /** 14623 * Returns the overlay for this view, creating it if it does not yet exist. 14624 * Adding drawables to the overlay will cause them to be displayed whenever 14625 * the view itself is redrawn. Objects in the overlay should be actively 14626 * managed: remove them when they should not be displayed anymore. The 14627 * overlay will always have the same size as its host view. 14628 * 14629 * <p>Note: Overlays do not currently work correctly with {@link 14630 * SurfaceView} or {@link TextureView}; contents in overlays for these 14631 * types of views may not display correctly.</p> 14632 * 14633 * @return The ViewOverlay object for this view. 14634 * @see ViewOverlay 14635 */ 14636 public ViewOverlay getOverlay() { 14637 if (mOverlay == null) { 14638 mOverlay = new ViewOverlay(mContext, this); 14639 } 14640 return mOverlay; 14641 } 14642 14643 /** 14644 * Override this if your view is known to always be drawn on top of a solid color background, 14645 * and needs to draw fading edges. Returning a non-zero color enables the view system to 14646 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 14647 * should be set to 0xFF. 14648 * 14649 * @see #setVerticalFadingEdgeEnabled(boolean) 14650 * @see #setHorizontalFadingEdgeEnabled(boolean) 14651 * 14652 * @return The known solid color background for this view, or 0 if the color may vary 14653 */ 14654 @ViewDebug.ExportedProperty(category = "drawing") 14655 public int getSolidColor() { 14656 return 0; 14657 } 14658 14659 /** 14660 * Build a human readable string representation of the specified view flags. 14661 * 14662 * @param flags the view flags to convert to a string 14663 * @return a String representing the supplied flags 14664 */ 14665 private static String printFlags(int flags) { 14666 String output = ""; 14667 int numFlags = 0; 14668 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 14669 output += "TAKES_FOCUS"; 14670 numFlags++; 14671 } 14672 14673 switch (flags & VISIBILITY_MASK) { 14674 case INVISIBLE: 14675 if (numFlags > 0) { 14676 output += " "; 14677 } 14678 output += "INVISIBLE"; 14679 // USELESS HERE numFlags++; 14680 break; 14681 case GONE: 14682 if (numFlags > 0) { 14683 output += " "; 14684 } 14685 output += "GONE"; 14686 // USELESS HERE numFlags++; 14687 break; 14688 default: 14689 break; 14690 } 14691 return output; 14692 } 14693 14694 /** 14695 * Build a human readable string representation of the specified private 14696 * view flags. 14697 * 14698 * @param privateFlags the private view flags to convert to a string 14699 * @return a String representing the supplied flags 14700 */ 14701 private static String printPrivateFlags(int privateFlags) { 14702 String output = ""; 14703 int numFlags = 0; 14704 14705 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 14706 output += "WANTS_FOCUS"; 14707 numFlags++; 14708 } 14709 14710 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 14711 if (numFlags > 0) { 14712 output += " "; 14713 } 14714 output += "FOCUSED"; 14715 numFlags++; 14716 } 14717 14718 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 14719 if (numFlags > 0) { 14720 output += " "; 14721 } 14722 output += "SELECTED"; 14723 numFlags++; 14724 } 14725 14726 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 14727 if (numFlags > 0) { 14728 output += " "; 14729 } 14730 output += "IS_ROOT_NAMESPACE"; 14731 numFlags++; 14732 } 14733 14734 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 14735 if (numFlags > 0) { 14736 output += " "; 14737 } 14738 output += "HAS_BOUNDS"; 14739 numFlags++; 14740 } 14741 14742 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 14743 if (numFlags > 0) { 14744 output += " "; 14745 } 14746 output += "DRAWN"; 14747 // USELESS HERE numFlags++; 14748 } 14749 return output; 14750 } 14751 14752 /** 14753 * <p>Indicates whether or not this view's layout will be requested during 14754 * the next hierarchy layout pass.</p> 14755 * 14756 * @return true if the layout will be forced during next layout pass 14757 */ 14758 public boolean isLayoutRequested() { 14759 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 14760 } 14761 14762 /** 14763 * Return true if o is a ViewGroup that is laying out using optical bounds. 14764 * @hide 14765 */ 14766 public static boolean isLayoutModeOptical(Object o) { 14767 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 14768 } 14769 14770 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 14771 Insets parentInsets = mParent instanceof View ? 14772 ((View) mParent).getOpticalInsets() : Insets.NONE; 14773 Insets childInsets = getOpticalInsets(); 14774 return setFrame( 14775 left + parentInsets.left - childInsets.left, 14776 top + parentInsets.top - childInsets.top, 14777 right + parentInsets.left + childInsets.right, 14778 bottom + parentInsets.top + childInsets.bottom); 14779 } 14780 14781 /** 14782 * Assign a size and position to a view and all of its 14783 * descendants 14784 * 14785 * <p>This is the second phase of the layout mechanism. 14786 * (The first is measuring). In this phase, each parent calls 14787 * layout on all of its children to position them. 14788 * This is typically done using the child measurements 14789 * that were stored in the measure pass().</p> 14790 * 14791 * <p>Derived classes should not override this method. 14792 * Derived classes with children should override 14793 * onLayout. In that method, they should 14794 * call layout on each of their children.</p> 14795 * 14796 * @param l Left position, relative to parent 14797 * @param t Top position, relative to parent 14798 * @param r Right position, relative to parent 14799 * @param b Bottom position, relative to parent 14800 */ 14801 @SuppressWarnings({"unchecked"}) 14802 public void layout(int l, int t, int r, int b) { 14803 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 14804 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 14805 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 14806 } 14807 14808 int oldL = mLeft; 14809 int oldT = mTop; 14810 int oldB = mBottom; 14811 int oldR = mRight; 14812 14813 boolean changed = isLayoutModeOptical(mParent) ? 14814 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 14815 14816 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 14817 onLayout(changed, l, t, r, b); 14818 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 14819 14820 ListenerInfo li = mListenerInfo; 14821 if (li != null && li.mOnLayoutChangeListeners != null) { 14822 ArrayList<OnLayoutChangeListener> listenersCopy = 14823 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 14824 int numListeners = listenersCopy.size(); 14825 for (int i = 0; i < numListeners; ++i) { 14826 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 14827 } 14828 } 14829 } 14830 14831 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 14832 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 14833 } 14834 14835 /** 14836 * Called from layout when this view should 14837 * assign a size and position to each of its children. 14838 * 14839 * Derived classes with children should override 14840 * this method and call layout on each of 14841 * their children. 14842 * @param changed This is a new size or position for this view 14843 * @param left Left position, relative to parent 14844 * @param top Top position, relative to parent 14845 * @param right Right position, relative to parent 14846 * @param bottom Bottom position, relative to parent 14847 */ 14848 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 14849 } 14850 14851 /** 14852 * Assign a size and position to this view. 14853 * 14854 * This is called from layout. 14855 * 14856 * @param left Left position, relative to parent 14857 * @param top Top position, relative to parent 14858 * @param right Right position, relative to parent 14859 * @param bottom Bottom position, relative to parent 14860 * @return true if the new size and position are different than the 14861 * previous ones 14862 * {@hide} 14863 */ 14864 protected boolean setFrame(int left, int top, int right, int bottom) { 14865 boolean changed = false; 14866 14867 if (DBG) { 14868 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 14869 + right + "," + bottom + ")"); 14870 } 14871 14872 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 14873 changed = true; 14874 14875 // Remember our drawn bit 14876 int drawn = mPrivateFlags & PFLAG_DRAWN; 14877 14878 int oldWidth = mRight - mLeft; 14879 int oldHeight = mBottom - mTop; 14880 int newWidth = right - left; 14881 int newHeight = bottom - top; 14882 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 14883 14884 // Invalidate our old position 14885 invalidate(sizeChanged); 14886 14887 mLeft = left; 14888 mTop = top; 14889 mRight = right; 14890 mBottom = bottom; 14891 if (mDisplayList != null) { 14892 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 14893 } 14894 14895 mPrivateFlags |= PFLAG_HAS_BOUNDS; 14896 14897 14898 if (sizeChanged) { 14899 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) { 14900 // A change in dimension means an auto-centered pivot point changes, too 14901 if (mTransformationInfo != null) { 14902 mTransformationInfo.mMatrixDirty = true; 14903 } 14904 } 14905 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 14906 } 14907 14908 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { 14909 // If we are visible, force the DRAWN bit to on so that 14910 // this invalidate will go through (at least to our parent). 14911 // This is because someone may have invalidated this view 14912 // before this call to setFrame came in, thereby clearing 14913 // the DRAWN bit. 14914 mPrivateFlags |= PFLAG_DRAWN; 14915 invalidate(sizeChanged); 14916 // parent display list may need to be recreated based on a change in the bounds 14917 // of any child 14918 invalidateParentCaches(); 14919 } 14920 14921 // Reset drawn bit to original value (invalidate turns it off) 14922 mPrivateFlags |= drawn; 14923 14924 mBackgroundSizeChanged = true; 14925 14926 notifySubtreeAccessibilityStateChangedIfNeeded(); 14927 } 14928 return changed; 14929 } 14930 14931 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 14932 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 14933 if (mOverlay != null) { 14934 mOverlay.getOverlayView().setRight(newWidth); 14935 mOverlay.getOverlayView().setBottom(newHeight); 14936 } 14937 } 14938 14939 /** 14940 * Finalize inflating a view from XML. This is called as the last phase 14941 * of inflation, after all child views have been added. 14942 * 14943 * <p>Even if the subclass overrides onFinishInflate, they should always be 14944 * sure to call the super method, so that we get called. 14945 */ 14946 protected void onFinishInflate() { 14947 } 14948 14949 /** 14950 * Returns the resources associated with this view. 14951 * 14952 * @return Resources object. 14953 */ 14954 public Resources getResources() { 14955 return mResources; 14956 } 14957 14958 /** 14959 * Invalidates the specified Drawable. 14960 * 14961 * @param drawable the drawable to invalidate 14962 */ 14963 public void invalidateDrawable(Drawable drawable) { 14964 if (verifyDrawable(drawable)) { 14965 final Rect dirty = drawable.getBounds(); 14966 final int scrollX = mScrollX; 14967 final int scrollY = mScrollY; 14968 14969 invalidate(dirty.left + scrollX, dirty.top + scrollY, 14970 dirty.right + scrollX, dirty.bottom + scrollY); 14971 } 14972 } 14973 14974 /** 14975 * Schedules an action on a drawable to occur at a specified time. 14976 * 14977 * @param who the recipient of the action 14978 * @param what the action to run on the drawable 14979 * @param when the time at which the action must occur. Uses the 14980 * {@link SystemClock#uptimeMillis} timebase. 14981 */ 14982 public void scheduleDrawable(Drawable who, Runnable what, long when) { 14983 if (verifyDrawable(who) && what != null) { 14984 final long delay = when - SystemClock.uptimeMillis(); 14985 if (mAttachInfo != null) { 14986 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 14987 Choreographer.CALLBACK_ANIMATION, what, who, 14988 Choreographer.subtractFrameDelay(delay)); 14989 } else { 14990 ViewRootImpl.getRunQueue().postDelayed(what, delay); 14991 } 14992 } 14993 } 14994 14995 /** 14996 * Cancels a scheduled action on a drawable. 14997 * 14998 * @param who the recipient of the action 14999 * @param what the action to cancel 15000 */ 15001 public void unscheduleDrawable(Drawable who, Runnable what) { 15002 if (verifyDrawable(who) && what != null) { 15003 if (mAttachInfo != null) { 15004 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 15005 Choreographer.CALLBACK_ANIMATION, what, who); 15006 } else { 15007 ViewRootImpl.getRunQueue().removeCallbacks(what); 15008 } 15009 } 15010 } 15011 15012 /** 15013 * Unschedule any events associated with the given Drawable. This can be 15014 * used when selecting a new Drawable into a view, so that the previous 15015 * one is completely unscheduled. 15016 * 15017 * @param who The Drawable to unschedule. 15018 * 15019 * @see #drawableStateChanged 15020 */ 15021 public void unscheduleDrawable(Drawable who) { 15022 if (mAttachInfo != null && who != null) { 15023 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 15024 Choreographer.CALLBACK_ANIMATION, null, who); 15025 } 15026 } 15027 15028 /** 15029 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 15030 * that the View directionality can and will be resolved before its Drawables. 15031 * 15032 * Will call {@link View#onResolveDrawables} when resolution is done. 15033 * 15034 * @hide 15035 */ 15036 protected void resolveDrawables() { 15037 // Drawables resolution may need to happen before resolving the layout direction (which is 15038 // done only during the measure() call). 15039 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 15040 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 15041 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 15042 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 15043 // direction to be resolved as its resolved value will be the same as its raw value. 15044 if (!isLayoutDirectionResolved() && 15045 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 15046 return; 15047 } 15048 15049 final int layoutDirection = isLayoutDirectionResolved() ? 15050 getLayoutDirection() : getRawLayoutDirection(); 15051 15052 if (mBackground != null) { 15053 mBackground.setLayoutDirection(layoutDirection); 15054 } 15055 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 15056 onResolveDrawables(layoutDirection); 15057 } 15058 15059 /** 15060 * Called when layout direction has been resolved. 15061 * 15062 * The default implementation does nothing. 15063 * 15064 * @param layoutDirection The resolved layout direction. 15065 * 15066 * @see #LAYOUT_DIRECTION_LTR 15067 * @see #LAYOUT_DIRECTION_RTL 15068 * 15069 * @hide 15070 */ 15071 public void onResolveDrawables(int layoutDirection) { 15072 } 15073 15074 /** 15075 * @hide 15076 */ 15077 protected void resetResolvedDrawables() { 15078 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 15079 } 15080 15081 private boolean isDrawablesResolved() { 15082 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 15083 } 15084 15085 /** 15086 * If your view subclass is displaying its own Drawable objects, it should 15087 * override this function and return true for any Drawable it is 15088 * displaying. This allows animations for those drawables to be 15089 * scheduled. 15090 * 15091 * <p>Be sure to call through to the super class when overriding this 15092 * function. 15093 * 15094 * @param who The Drawable to verify. Return true if it is one you are 15095 * displaying, else return the result of calling through to the 15096 * super class. 15097 * 15098 * @return boolean If true than the Drawable is being displayed in the 15099 * view; else false and it is not allowed to animate. 15100 * 15101 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 15102 * @see #drawableStateChanged() 15103 */ 15104 protected boolean verifyDrawable(Drawable who) { 15105 return who == mBackground; 15106 } 15107 15108 /** 15109 * This function is called whenever the state of the view changes in such 15110 * a way that it impacts the state of drawables being shown. 15111 * 15112 * <p>Be sure to call through to the superclass when overriding this 15113 * function. 15114 * 15115 * @see Drawable#setState(int[]) 15116 */ 15117 protected void drawableStateChanged() { 15118 Drawable d = mBackground; 15119 if (d != null && d.isStateful()) { 15120 d.setState(getDrawableState()); 15121 } 15122 } 15123 15124 /** 15125 * Call this to force a view to update its drawable state. This will cause 15126 * drawableStateChanged to be called on this view. Views that are interested 15127 * in the new state should call getDrawableState. 15128 * 15129 * @see #drawableStateChanged 15130 * @see #getDrawableState 15131 */ 15132 public void refreshDrawableState() { 15133 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 15134 drawableStateChanged(); 15135 15136 ViewParent parent = mParent; 15137 if (parent != null) { 15138 parent.childDrawableStateChanged(this); 15139 } 15140 } 15141 15142 /** 15143 * Return an array of resource IDs of the drawable states representing the 15144 * current state of the view. 15145 * 15146 * @return The current drawable state 15147 * 15148 * @see Drawable#setState(int[]) 15149 * @see #drawableStateChanged() 15150 * @see #onCreateDrawableState(int) 15151 */ 15152 public final int[] getDrawableState() { 15153 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 15154 return mDrawableState; 15155 } else { 15156 mDrawableState = onCreateDrawableState(0); 15157 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 15158 return mDrawableState; 15159 } 15160 } 15161 15162 /** 15163 * Generate the new {@link android.graphics.drawable.Drawable} state for 15164 * this view. This is called by the view 15165 * system when the cached Drawable state is determined to be invalid. To 15166 * retrieve the current state, you should use {@link #getDrawableState}. 15167 * 15168 * @param extraSpace if non-zero, this is the number of extra entries you 15169 * would like in the returned array in which you can place your own 15170 * states. 15171 * 15172 * @return Returns an array holding the current {@link Drawable} state of 15173 * the view. 15174 * 15175 * @see #mergeDrawableStates(int[], int[]) 15176 */ 15177 protected int[] onCreateDrawableState(int extraSpace) { 15178 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 15179 mParent instanceof View) { 15180 return ((View) mParent).onCreateDrawableState(extraSpace); 15181 } 15182 15183 int[] drawableState; 15184 15185 int privateFlags = mPrivateFlags; 15186 15187 int viewStateIndex = 0; 15188 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED; 15189 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED; 15190 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED; 15191 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED; 15192 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED; 15193 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED; 15194 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 15195 HardwareRenderer.isAvailable()) { 15196 // This is set if HW acceleration is requested, even if the current 15197 // process doesn't allow it. This is just to allow app preview 15198 // windows to better match their app. 15199 viewStateIndex |= VIEW_STATE_ACCELERATED; 15200 } 15201 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED; 15202 15203 final int privateFlags2 = mPrivateFlags2; 15204 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT; 15205 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED; 15206 15207 drawableState = VIEW_STATE_SETS[viewStateIndex]; 15208 15209 //noinspection ConstantIfStatement 15210 if (false) { 15211 Log.i("View", "drawableStateIndex=" + viewStateIndex); 15212 Log.i("View", toString() 15213 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 15214 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 15215 + " fo=" + hasFocus() 15216 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 15217 + " wf=" + hasWindowFocus() 15218 + ": " + Arrays.toString(drawableState)); 15219 } 15220 15221 if (extraSpace == 0) { 15222 return drawableState; 15223 } 15224 15225 final int[] fullState; 15226 if (drawableState != null) { 15227 fullState = new int[drawableState.length + extraSpace]; 15228 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 15229 } else { 15230 fullState = new int[extraSpace]; 15231 } 15232 15233 return fullState; 15234 } 15235 15236 /** 15237 * Merge your own state values in <var>additionalState</var> into the base 15238 * state values <var>baseState</var> that were returned by 15239 * {@link #onCreateDrawableState(int)}. 15240 * 15241 * @param baseState The base state values returned by 15242 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 15243 * own additional state values. 15244 * 15245 * @param additionalState The additional state values you would like 15246 * added to <var>baseState</var>; this array is not modified. 15247 * 15248 * @return As a convenience, the <var>baseState</var> array you originally 15249 * passed into the function is returned. 15250 * 15251 * @see #onCreateDrawableState(int) 15252 */ 15253 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 15254 final int N = baseState.length; 15255 int i = N - 1; 15256 while (i >= 0 && baseState[i] == 0) { 15257 i--; 15258 } 15259 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 15260 return baseState; 15261 } 15262 15263 /** 15264 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 15265 * on all Drawable objects associated with this view. 15266 */ 15267 public void jumpDrawablesToCurrentState() { 15268 if (mBackground != null) { 15269 mBackground.jumpToCurrentState(); 15270 } 15271 } 15272 15273 /** 15274 * Sets the background color for this view. 15275 * @param color the color of the background 15276 */ 15277 @RemotableViewMethod 15278 public void setBackgroundColor(int color) { 15279 if (mBackground instanceof ColorDrawable) { 15280 ((ColorDrawable) mBackground.mutate()).setColor(color); 15281 computeOpaqueFlags(); 15282 mBackgroundResource = 0; 15283 } else { 15284 setBackground(new ColorDrawable(color)); 15285 } 15286 } 15287 15288 /** 15289 * Set the background to a given resource. The resource should refer to 15290 * a Drawable object or 0 to remove the background. 15291 * @param resid The identifier of the resource. 15292 * 15293 * @attr ref android.R.styleable#View_background 15294 */ 15295 @RemotableViewMethod 15296 public void setBackgroundResource(int resid) { 15297 if (resid != 0 && resid == mBackgroundResource) { 15298 return; 15299 } 15300 15301 Drawable d= null; 15302 if (resid != 0) { 15303 d = mResources.getDrawable(resid); 15304 } 15305 setBackground(d); 15306 15307 mBackgroundResource = resid; 15308 } 15309 15310 /** 15311 * Set the background to a given Drawable, or remove the background. If the 15312 * background has padding, this View's padding is set to the background's 15313 * padding. However, when a background is removed, this View's padding isn't 15314 * touched. If setting the padding is desired, please use 15315 * {@link #setPadding(int, int, int, int)}. 15316 * 15317 * @param background The Drawable to use as the background, or null to remove the 15318 * background 15319 */ 15320 public void setBackground(Drawable background) { 15321 //noinspection deprecation 15322 setBackgroundDrawable(background); 15323 } 15324 15325 /** 15326 * @deprecated use {@link #setBackground(Drawable)} instead 15327 */ 15328 @Deprecated 15329 public void setBackgroundDrawable(Drawable background) { 15330 computeOpaqueFlags(); 15331 15332 if (background == mBackground) { 15333 return; 15334 } 15335 15336 boolean requestLayout = false; 15337 15338 mBackgroundResource = 0; 15339 15340 /* 15341 * Regardless of whether we're setting a new background or not, we want 15342 * to clear the previous drawable. 15343 */ 15344 if (mBackground != null) { 15345 mBackground.setCallback(null); 15346 unscheduleDrawable(mBackground); 15347 } 15348 15349 if (background != null) { 15350 Rect padding = sThreadLocal.get(); 15351 if (padding == null) { 15352 padding = new Rect(); 15353 sThreadLocal.set(padding); 15354 } 15355 resetResolvedDrawables(); 15356 background.setLayoutDirection(getLayoutDirection()); 15357 if (background.getPadding(padding)) { 15358 resetResolvedPadding(); 15359 switch (background.getLayoutDirection()) { 15360 case LAYOUT_DIRECTION_RTL: 15361 mUserPaddingLeftInitial = padding.right; 15362 mUserPaddingRightInitial = padding.left; 15363 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 15364 break; 15365 case LAYOUT_DIRECTION_LTR: 15366 default: 15367 mUserPaddingLeftInitial = padding.left; 15368 mUserPaddingRightInitial = padding.right; 15369 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 15370 } 15371 mLeftPaddingDefined = false; 15372 mRightPaddingDefined = false; 15373 } 15374 15375 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 15376 // if it has a different minimum size, we should layout again 15377 if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() || 15378 mBackground.getMinimumWidth() != background.getMinimumWidth()) { 15379 requestLayout = true; 15380 } 15381 15382 background.setCallback(this); 15383 if (background.isStateful()) { 15384 background.setState(getDrawableState()); 15385 } 15386 background.setVisible(getVisibility() == VISIBLE, false); 15387 mBackground = background; 15388 15389 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 15390 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 15391 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; 15392 requestLayout = true; 15393 } 15394 } else { 15395 /* Remove the background */ 15396 mBackground = null; 15397 15398 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) { 15399 /* 15400 * This view ONLY drew the background before and we're removing 15401 * the background, so now it won't draw anything 15402 * (hence we SKIP_DRAW) 15403 */ 15404 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND; 15405 mPrivateFlags |= PFLAG_SKIP_DRAW; 15406 } 15407 15408 /* 15409 * When the background is set, we try to apply its padding to this 15410 * View. When the background is removed, we don't touch this View's 15411 * padding. This is noted in the Javadocs. Hence, we don't need to 15412 * requestLayout(), the invalidate() below is sufficient. 15413 */ 15414 15415 // The old background's minimum size could have affected this 15416 // View's layout, so let's requestLayout 15417 requestLayout = true; 15418 } 15419 15420 computeOpaqueFlags(); 15421 15422 if (requestLayout) { 15423 requestLayout(); 15424 } 15425 15426 mBackgroundSizeChanged = true; 15427 invalidate(true); 15428 } 15429 15430 /** 15431 * Gets the background drawable 15432 * 15433 * @return The drawable used as the background for this view, if any. 15434 * 15435 * @see #setBackground(Drawable) 15436 * 15437 * @attr ref android.R.styleable#View_background 15438 */ 15439 public Drawable getBackground() { 15440 return mBackground; 15441 } 15442 15443 /** 15444 * Sets the padding. The view may add on the space required to display 15445 * the scrollbars, depending on the style and visibility of the scrollbars. 15446 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 15447 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 15448 * from the values set in this call. 15449 * 15450 * @attr ref android.R.styleable#View_padding 15451 * @attr ref android.R.styleable#View_paddingBottom 15452 * @attr ref android.R.styleable#View_paddingLeft 15453 * @attr ref android.R.styleable#View_paddingRight 15454 * @attr ref android.R.styleable#View_paddingTop 15455 * @param left the left padding in pixels 15456 * @param top the top padding in pixels 15457 * @param right the right padding in pixels 15458 * @param bottom the bottom padding in pixels 15459 */ 15460 public void setPadding(int left, int top, int right, int bottom) { 15461 resetResolvedPadding(); 15462 15463 mUserPaddingStart = UNDEFINED_PADDING; 15464 mUserPaddingEnd = UNDEFINED_PADDING; 15465 15466 mUserPaddingLeftInitial = left; 15467 mUserPaddingRightInitial = right; 15468 15469 mLeftPaddingDefined = true; 15470 mRightPaddingDefined = true; 15471 15472 internalSetPadding(left, top, right, bottom); 15473 } 15474 15475 /** 15476 * @hide 15477 */ 15478 protected void internalSetPadding(int left, int top, int right, int bottom) { 15479 mUserPaddingLeft = left; 15480 mUserPaddingRight = right; 15481 mUserPaddingBottom = bottom; 15482 15483 final int viewFlags = mViewFlags; 15484 boolean changed = false; 15485 15486 // Common case is there are no scroll bars. 15487 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 15488 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 15489 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 15490 ? 0 : getVerticalScrollbarWidth(); 15491 switch (mVerticalScrollbarPosition) { 15492 case SCROLLBAR_POSITION_DEFAULT: 15493 if (isLayoutRtl()) { 15494 left += offset; 15495 } else { 15496 right += offset; 15497 } 15498 break; 15499 case SCROLLBAR_POSITION_RIGHT: 15500 right += offset; 15501 break; 15502 case SCROLLBAR_POSITION_LEFT: 15503 left += offset; 15504 break; 15505 } 15506 } 15507 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 15508 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 15509 ? 0 : getHorizontalScrollbarHeight(); 15510 } 15511 } 15512 15513 if (mPaddingLeft != left) { 15514 changed = true; 15515 mPaddingLeft = left; 15516 } 15517 if (mPaddingTop != top) { 15518 changed = true; 15519 mPaddingTop = top; 15520 } 15521 if (mPaddingRight != right) { 15522 changed = true; 15523 mPaddingRight = right; 15524 } 15525 if (mPaddingBottom != bottom) { 15526 changed = true; 15527 mPaddingBottom = bottom; 15528 } 15529 15530 if (changed) { 15531 requestLayout(); 15532 } 15533 } 15534 15535 /** 15536 * Sets the relative padding. The view may add on the space required to display 15537 * the scrollbars, depending on the style and visibility of the scrollbars. 15538 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 15539 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 15540 * from the values set in this call. 15541 * 15542 * @attr ref android.R.styleable#View_padding 15543 * @attr ref android.R.styleable#View_paddingBottom 15544 * @attr ref android.R.styleable#View_paddingStart 15545 * @attr ref android.R.styleable#View_paddingEnd 15546 * @attr ref android.R.styleable#View_paddingTop 15547 * @param start the start padding in pixels 15548 * @param top the top padding in pixels 15549 * @param end the end padding in pixels 15550 * @param bottom the bottom padding in pixels 15551 */ 15552 public void setPaddingRelative(int start, int top, int end, int bottom) { 15553 resetResolvedPadding(); 15554 15555 mUserPaddingStart = start; 15556 mUserPaddingEnd = end; 15557 mLeftPaddingDefined = true; 15558 mRightPaddingDefined = true; 15559 15560 switch(getLayoutDirection()) { 15561 case LAYOUT_DIRECTION_RTL: 15562 mUserPaddingLeftInitial = end; 15563 mUserPaddingRightInitial = start; 15564 internalSetPadding(end, top, start, bottom); 15565 break; 15566 case LAYOUT_DIRECTION_LTR: 15567 default: 15568 mUserPaddingLeftInitial = start; 15569 mUserPaddingRightInitial = end; 15570 internalSetPadding(start, top, end, bottom); 15571 } 15572 } 15573 15574 /** 15575 * Returns the top padding of this view. 15576 * 15577 * @return the top padding in pixels 15578 */ 15579 public int getPaddingTop() { 15580 return mPaddingTop; 15581 } 15582 15583 /** 15584 * Returns the bottom padding of this view. If there are inset and enabled 15585 * scrollbars, this value may include the space required to display the 15586 * scrollbars as well. 15587 * 15588 * @return the bottom padding in pixels 15589 */ 15590 public int getPaddingBottom() { 15591 return mPaddingBottom; 15592 } 15593 15594 /** 15595 * Returns the left padding of this view. If there are inset and enabled 15596 * scrollbars, this value may include the space required to display the 15597 * scrollbars as well. 15598 * 15599 * @return the left padding in pixels 15600 */ 15601 public int getPaddingLeft() { 15602 if (!isPaddingResolved()) { 15603 resolvePadding(); 15604 } 15605 return mPaddingLeft; 15606 } 15607 15608 /** 15609 * Returns the start padding of this view depending on its resolved layout direction. 15610 * If there are inset and enabled scrollbars, this value may include the space 15611 * required to display the scrollbars as well. 15612 * 15613 * @return the start padding in pixels 15614 */ 15615 public int getPaddingStart() { 15616 if (!isPaddingResolved()) { 15617 resolvePadding(); 15618 } 15619 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 15620 mPaddingRight : mPaddingLeft; 15621 } 15622 15623 /** 15624 * Returns the right padding of this view. If there are inset and enabled 15625 * scrollbars, this value may include the space required to display the 15626 * scrollbars as well. 15627 * 15628 * @return the right padding in pixels 15629 */ 15630 public int getPaddingRight() { 15631 if (!isPaddingResolved()) { 15632 resolvePadding(); 15633 } 15634 return mPaddingRight; 15635 } 15636 15637 /** 15638 * Returns the end padding of this view depending on its resolved layout direction. 15639 * If there are inset and enabled scrollbars, this value may include the space 15640 * required to display the scrollbars as well. 15641 * 15642 * @return the end padding in pixels 15643 */ 15644 public int getPaddingEnd() { 15645 if (!isPaddingResolved()) { 15646 resolvePadding(); 15647 } 15648 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 15649 mPaddingLeft : mPaddingRight; 15650 } 15651 15652 /** 15653 * Return if the padding as been set thru relative values 15654 * {@link #setPaddingRelative(int, int, int, int)} or thru 15655 * @attr ref android.R.styleable#View_paddingStart or 15656 * @attr ref android.R.styleable#View_paddingEnd 15657 * 15658 * @return true if the padding is relative or false if it is not. 15659 */ 15660 public boolean isPaddingRelative() { 15661 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 15662 } 15663 15664 Insets computeOpticalInsets() { 15665 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 15666 } 15667 15668 /** 15669 * @hide 15670 */ 15671 public void resetPaddingToInitialValues() { 15672 if (isRtlCompatibilityMode()) { 15673 mPaddingLeft = mUserPaddingLeftInitial; 15674 mPaddingRight = mUserPaddingRightInitial; 15675 return; 15676 } 15677 if (isLayoutRtl()) { 15678 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 15679 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 15680 } else { 15681 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 15682 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 15683 } 15684 } 15685 15686 /** 15687 * @hide 15688 */ 15689 public Insets getOpticalInsets() { 15690 if (mLayoutInsets == null) { 15691 mLayoutInsets = computeOpticalInsets(); 15692 } 15693 return mLayoutInsets; 15694 } 15695 15696 /** 15697 * Changes the selection state of this view. A view can be selected or not. 15698 * Note that selection is not the same as focus. Views are typically 15699 * selected in the context of an AdapterView like ListView or GridView; 15700 * the selected view is the view that is highlighted. 15701 * 15702 * @param selected true if the view must be selected, false otherwise 15703 */ 15704 public void setSelected(boolean selected) { 15705 //noinspection DoubleNegation 15706 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 15707 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 15708 if (!selected) resetPressedState(); 15709 invalidate(true); 15710 refreshDrawableState(); 15711 dispatchSetSelected(selected); 15712 notifyViewAccessibilityStateChangedIfNeeded( 15713 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 15714 } 15715 } 15716 15717 /** 15718 * Dispatch setSelected to all of this View's children. 15719 * 15720 * @see #setSelected(boolean) 15721 * 15722 * @param selected The new selected state 15723 */ 15724 protected void dispatchSetSelected(boolean selected) { 15725 } 15726 15727 /** 15728 * Indicates the selection state of this view. 15729 * 15730 * @return true if the view is selected, false otherwise 15731 */ 15732 @ViewDebug.ExportedProperty 15733 public boolean isSelected() { 15734 return (mPrivateFlags & PFLAG_SELECTED) != 0; 15735 } 15736 15737 /** 15738 * Changes the activated state of this view. A view can be activated or not. 15739 * Note that activation is not the same as selection. Selection is 15740 * a transient property, representing the view (hierarchy) the user is 15741 * currently interacting with. Activation is a longer-term state that the 15742 * user can move views in and out of. For example, in a list view with 15743 * single or multiple selection enabled, the views in the current selection 15744 * set are activated. (Um, yeah, we are deeply sorry about the terminology 15745 * here.) The activated state is propagated down to children of the view it 15746 * is set on. 15747 * 15748 * @param activated true if the view must be activated, false otherwise 15749 */ 15750 public void setActivated(boolean activated) { 15751 //noinspection DoubleNegation 15752 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 15753 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 15754 invalidate(true); 15755 refreshDrawableState(); 15756 dispatchSetActivated(activated); 15757 } 15758 } 15759 15760 /** 15761 * Dispatch setActivated to all of this View's children. 15762 * 15763 * @see #setActivated(boolean) 15764 * 15765 * @param activated The new activated state 15766 */ 15767 protected void dispatchSetActivated(boolean activated) { 15768 } 15769 15770 /** 15771 * Indicates the activation state of this view. 15772 * 15773 * @return true if the view is activated, false otherwise 15774 */ 15775 @ViewDebug.ExportedProperty 15776 public boolean isActivated() { 15777 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 15778 } 15779 15780 /** 15781 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 15782 * observer can be used to get notifications when global events, like 15783 * layout, happen. 15784 * 15785 * The returned ViewTreeObserver observer is not guaranteed to remain 15786 * valid for the lifetime of this View. If the caller of this method keeps 15787 * a long-lived reference to ViewTreeObserver, it should always check for 15788 * the return value of {@link ViewTreeObserver#isAlive()}. 15789 * 15790 * @return The ViewTreeObserver for this view's hierarchy. 15791 */ 15792 public ViewTreeObserver getViewTreeObserver() { 15793 if (mAttachInfo != null) { 15794 return mAttachInfo.mTreeObserver; 15795 } 15796 if (mFloatingTreeObserver == null) { 15797 mFloatingTreeObserver = new ViewTreeObserver(); 15798 } 15799 return mFloatingTreeObserver; 15800 } 15801 15802 /** 15803 * <p>Finds the topmost view in the current view hierarchy.</p> 15804 * 15805 * @return the topmost view containing this view 15806 */ 15807 public View getRootView() { 15808 if (mAttachInfo != null) { 15809 final View v = mAttachInfo.mRootView; 15810 if (v != null) { 15811 return v; 15812 } 15813 } 15814 15815 View parent = this; 15816 15817 while (parent.mParent != null && parent.mParent instanceof View) { 15818 parent = (View) parent.mParent; 15819 } 15820 15821 return parent; 15822 } 15823 15824 /** 15825 * Transforms a motion event from view-local coordinates to on-screen 15826 * coordinates. 15827 * 15828 * @param ev the view-local motion event 15829 * @return false if the transformation could not be applied 15830 * @hide 15831 */ 15832 public boolean toGlobalMotionEvent(MotionEvent ev) { 15833 final AttachInfo info = mAttachInfo; 15834 if (info == null) { 15835 return false; 15836 } 15837 15838 transformMotionEventToGlobal(ev); 15839 ev.offsetLocation(info.mWindowLeft, info.mWindowTop); 15840 return true; 15841 } 15842 15843 /** 15844 * Transforms a motion event from on-screen coordinates to view-local 15845 * coordinates. 15846 * 15847 * @param ev the on-screen motion event 15848 * @return false if the transformation could not be applied 15849 * @hide 15850 */ 15851 public boolean toLocalMotionEvent(MotionEvent ev) { 15852 final AttachInfo info = mAttachInfo; 15853 if (info == null) { 15854 return false; 15855 } 15856 15857 ev.offsetLocation(-info.mWindowLeft, -info.mWindowTop); 15858 transformMotionEventToLocal(ev); 15859 return true; 15860 } 15861 15862 /** 15863 * Recursive helper method that applies transformations in post-order. 15864 * 15865 * @param ev the on-screen motion event 15866 */ 15867 private void transformMotionEventToLocal(MotionEvent ev) { 15868 final ViewParent parent = mParent; 15869 if (parent instanceof View) { 15870 final View vp = (View) parent; 15871 vp.transformMotionEventToLocal(ev); 15872 ev.offsetLocation(vp.mScrollX, vp.mScrollY); 15873 } else if (parent instanceof ViewRootImpl) { 15874 final ViewRootImpl vr = (ViewRootImpl) parent; 15875 ev.offsetLocation(0, vr.mCurScrollY); 15876 } 15877 15878 ev.offsetLocation(-mLeft, -mTop); 15879 15880 if (!hasIdentityMatrix()) { 15881 ev.transform(getInverseMatrix()); 15882 } 15883 } 15884 15885 /** 15886 * Recursive helper method that applies transformations in pre-order. 15887 * 15888 * @param ev the on-screen motion event 15889 */ 15890 private void transformMotionEventToGlobal(MotionEvent ev) { 15891 if (!hasIdentityMatrix()) { 15892 ev.transform(getMatrix()); 15893 } 15894 15895 ev.offsetLocation(mLeft, mTop); 15896 15897 final ViewParent parent = mParent; 15898 if (parent instanceof View) { 15899 final View vp = (View) parent; 15900 ev.offsetLocation(-vp.mScrollX, -vp.mScrollY); 15901 vp.transformMotionEventToGlobal(ev); 15902 } else if (parent instanceof ViewRootImpl) { 15903 final ViewRootImpl vr = (ViewRootImpl) parent; 15904 ev.offsetLocation(0, -vr.mCurScrollY); 15905 } 15906 } 15907 15908 /** 15909 * <p>Computes the coordinates of this view on the screen. The argument 15910 * must be an array of two integers. After the method returns, the array 15911 * contains the x and y location in that order.</p> 15912 * 15913 * @param location an array of two integers in which to hold the coordinates 15914 */ 15915 public void getLocationOnScreen(int[] location) { 15916 getLocationInWindow(location); 15917 15918 final AttachInfo info = mAttachInfo; 15919 if (info != null) { 15920 location[0] += info.mWindowLeft; 15921 location[1] += info.mWindowTop; 15922 } 15923 } 15924 15925 /** 15926 * <p>Computes the coordinates of this view in its window. The argument 15927 * must be an array of two integers. After the method returns, the array 15928 * contains the x and y location in that order.</p> 15929 * 15930 * @param location an array of two integers in which to hold the coordinates 15931 */ 15932 public void getLocationInWindow(int[] location) { 15933 if (location == null || location.length < 2) { 15934 throw new IllegalArgumentException("location must be an array of two integers"); 15935 } 15936 15937 if (mAttachInfo == null) { 15938 // When the view is not attached to a window, this method does not make sense 15939 location[0] = location[1] = 0; 15940 return; 15941 } 15942 15943 float[] position = mAttachInfo.mTmpTransformLocation; 15944 position[0] = position[1] = 0.0f; 15945 15946 if (!hasIdentityMatrix()) { 15947 getMatrix().mapPoints(position); 15948 } 15949 15950 position[0] += mLeft; 15951 position[1] += mTop; 15952 15953 ViewParent viewParent = mParent; 15954 while (viewParent instanceof View) { 15955 final View view = (View) viewParent; 15956 15957 position[0] -= view.mScrollX; 15958 position[1] -= view.mScrollY; 15959 15960 if (!view.hasIdentityMatrix()) { 15961 view.getMatrix().mapPoints(position); 15962 } 15963 15964 position[0] += view.mLeft; 15965 position[1] += view.mTop; 15966 15967 viewParent = view.mParent; 15968 } 15969 15970 if (viewParent instanceof ViewRootImpl) { 15971 // *cough* 15972 final ViewRootImpl vr = (ViewRootImpl) viewParent; 15973 position[1] -= vr.mCurScrollY; 15974 } 15975 15976 location[0] = (int) (position[0] + 0.5f); 15977 location[1] = (int) (position[1] + 0.5f); 15978 } 15979 15980 /** 15981 * {@hide} 15982 * @param id the id of the view to be found 15983 * @return the view of the specified id, null if cannot be found 15984 */ 15985 protected View findViewTraversal(int id) { 15986 if (id == mID) { 15987 return this; 15988 } 15989 return null; 15990 } 15991 15992 /** 15993 * {@hide} 15994 * @param tag the tag of the view to be found 15995 * @return the view of specified tag, null if cannot be found 15996 */ 15997 protected View findViewWithTagTraversal(Object tag) { 15998 if (tag != null && tag.equals(mTag)) { 15999 return this; 16000 } 16001 return null; 16002 } 16003 16004 /** 16005 * {@hide} 16006 * @param predicate The predicate to evaluate. 16007 * @param childToSkip If not null, ignores this child during the recursive traversal. 16008 * @return The first view that matches the predicate or null. 16009 */ 16010 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 16011 if (predicate.apply(this)) { 16012 return this; 16013 } 16014 return null; 16015 } 16016 16017 /** 16018 * Look for a child view with the given id. If this view has the given 16019 * id, return this view. 16020 * 16021 * @param id The id to search for. 16022 * @return The view that has the given id in the hierarchy or null 16023 */ 16024 public final View findViewById(int id) { 16025 if (id < 0) { 16026 return null; 16027 } 16028 return findViewTraversal(id); 16029 } 16030 16031 /** 16032 * Finds a view by its unuque and stable accessibility id. 16033 * 16034 * @param accessibilityId The searched accessibility id. 16035 * @return The found view. 16036 */ 16037 final View findViewByAccessibilityId(int accessibilityId) { 16038 if (accessibilityId < 0) { 16039 return null; 16040 } 16041 return findViewByAccessibilityIdTraversal(accessibilityId); 16042 } 16043 16044 /** 16045 * Performs the traversal to find a view by its unuque and stable accessibility id. 16046 * 16047 * <strong>Note:</strong>This method does not stop at the root namespace 16048 * boundary since the user can touch the screen at an arbitrary location 16049 * potentially crossing the root namespace bounday which will send an 16050 * accessibility event to accessibility services and they should be able 16051 * to obtain the event source. Also accessibility ids are guaranteed to be 16052 * unique in the window. 16053 * 16054 * @param accessibilityId The accessibility id. 16055 * @return The found view. 16056 * 16057 * @hide 16058 */ 16059 public View findViewByAccessibilityIdTraversal(int accessibilityId) { 16060 if (getAccessibilityViewId() == accessibilityId) { 16061 return this; 16062 } 16063 return null; 16064 } 16065 16066 /** 16067 * Look for a child view with the given tag. If this view has the given 16068 * tag, return this view. 16069 * 16070 * @param tag The tag to search for, using "tag.equals(getTag())". 16071 * @return The View that has the given tag in the hierarchy or null 16072 */ 16073 public final View findViewWithTag(Object tag) { 16074 if (tag == null) { 16075 return null; 16076 } 16077 return findViewWithTagTraversal(tag); 16078 } 16079 16080 /** 16081 * {@hide} 16082 * Look for a child view that matches the specified predicate. 16083 * If this view matches the predicate, return this view. 16084 * 16085 * @param predicate The predicate to evaluate. 16086 * @return The first view that matches the predicate or null. 16087 */ 16088 public final View findViewByPredicate(Predicate<View> predicate) { 16089 return findViewByPredicateTraversal(predicate, null); 16090 } 16091 16092 /** 16093 * {@hide} 16094 * Look for a child view that matches the specified predicate, 16095 * starting with the specified view and its descendents and then 16096 * recusively searching the ancestors and siblings of that view 16097 * until this view is reached. 16098 * 16099 * This method is useful in cases where the predicate does not match 16100 * a single unique view (perhaps multiple views use the same id) 16101 * and we are trying to find the view that is "closest" in scope to the 16102 * starting view. 16103 * 16104 * @param start The view to start from. 16105 * @param predicate The predicate to evaluate. 16106 * @return The first view that matches the predicate or null. 16107 */ 16108 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 16109 View childToSkip = null; 16110 for (;;) { 16111 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 16112 if (view != null || start == this) { 16113 return view; 16114 } 16115 16116 ViewParent parent = start.getParent(); 16117 if (parent == null || !(parent instanceof View)) { 16118 return null; 16119 } 16120 16121 childToSkip = start; 16122 start = (View) parent; 16123 } 16124 } 16125 16126 /** 16127 * Sets the identifier for this view. The identifier does not have to be 16128 * unique in this view's hierarchy. The identifier should be a positive 16129 * number. 16130 * 16131 * @see #NO_ID 16132 * @see #getId() 16133 * @see #findViewById(int) 16134 * 16135 * @param id a number used to identify the view 16136 * 16137 * @attr ref android.R.styleable#View_id 16138 */ 16139 public void setId(int id) { 16140 mID = id; 16141 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 16142 mID = generateViewId(); 16143 } 16144 } 16145 16146 /** 16147 * {@hide} 16148 * 16149 * @param isRoot true if the view belongs to the root namespace, false 16150 * otherwise 16151 */ 16152 public void setIsRootNamespace(boolean isRoot) { 16153 if (isRoot) { 16154 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 16155 } else { 16156 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 16157 } 16158 } 16159 16160 /** 16161 * {@hide} 16162 * 16163 * @return true if the view belongs to the root namespace, false otherwise 16164 */ 16165 public boolean isRootNamespace() { 16166 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 16167 } 16168 16169 /** 16170 * Returns this view's identifier. 16171 * 16172 * @return a positive integer used to identify the view or {@link #NO_ID} 16173 * if the view has no ID 16174 * 16175 * @see #setId(int) 16176 * @see #findViewById(int) 16177 * @attr ref android.R.styleable#View_id 16178 */ 16179 @ViewDebug.CapturedViewProperty 16180 public int getId() { 16181 return mID; 16182 } 16183 16184 /** 16185 * Returns this view's tag. 16186 * 16187 * @return the Object stored in this view as a tag 16188 * 16189 * @see #setTag(Object) 16190 * @see #getTag(int) 16191 */ 16192 @ViewDebug.ExportedProperty 16193 public Object getTag() { 16194 return mTag; 16195 } 16196 16197 /** 16198 * Sets the tag associated with this view. A tag can be used to mark 16199 * a view in its hierarchy and does not have to be unique within the 16200 * hierarchy. Tags can also be used to store data within a view without 16201 * resorting to another data structure. 16202 * 16203 * @param tag an Object to tag the view with 16204 * 16205 * @see #getTag() 16206 * @see #setTag(int, Object) 16207 */ 16208 public void setTag(final Object tag) { 16209 mTag = tag; 16210 } 16211 16212 /** 16213 * Returns the tag associated with this view and the specified key. 16214 * 16215 * @param key The key identifying the tag 16216 * 16217 * @return the Object stored in this view as a tag 16218 * 16219 * @see #setTag(int, Object) 16220 * @see #getTag() 16221 */ 16222 public Object getTag(int key) { 16223 if (mKeyedTags != null) return mKeyedTags.get(key); 16224 return null; 16225 } 16226 16227 /** 16228 * Sets a tag associated with this view and a key. A tag can be used 16229 * to mark a view in its hierarchy and does not have to be unique within 16230 * the hierarchy. Tags can also be used to store data within a view 16231 * without resorting to another data structure. 16232 * 16233 * The specified key should be an id declared in the resources of the 16234 * application to ensure it is unique (see the <a 16235 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 16236 * Keys identified as belonging to 16237 * the Android framework or not associated with any package will cause 16238 * an {@link IllegalArgumentException} to be thrown. 16239 * 16240 * @param key The key identifying the tag 16241 * @param tag An Object to tag the view with 16242 * 16243 * @throws IllegalArgumentException If they specified key is not valid 16244 * 16245 * @see #setTag(Object) 16246 * @see #getTag(int) 16247 */ 16248 public void setTag(int key, final Object tag) { 16249 // If the package id is 0x00 or 0x01, it's either an undefined package 16250 // or a framework id 16251 if ((key >>> 24) < 2) { 16252 throw new IllegalArgumentException("The key must be an application-specific " 16253 + "resource id."); 16254 } 16255 16256 setKeyedTag(key, tag); 16257 } 16258 16259 /** 16260 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 16261 * framework id. 16262 * 16263 * @hide 16264 */ 16265 public void setTagInternal(int key, Object tag) { 16266 if ((key >>> 24) != 0x1) { 16267 throw new IllegalArgumentException("The key must be a framework-specific " 16268 + "resource id."); 16269 } 16270 16271 setKeyedTag(key, tag); 16272 } 16273 16274 private void setKeyedTag(int key, Object tag) { 16275 if (mKeyedTags == null) { 16276 mKeyedTags = new SparseArray<Object>(2); 16277 } 16278 16279 mKeyedTags.put(key, tag); 16280 } 16281 16282 /** 16283 * Prints information about this view in the log output, with the tag 16284 * {@link #VIEW_LOG_TAG}. 16285 * 16286 * @hide 16287 */ 16288 public void debug() { 16289 debug(0); 16290 } 16291 16292 /** 16293 * Prints information about this view in the log output, with the tag 16294 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 16295 * indentation defined by the <code>depth</code>. 16296 * 16297 * @param depth the indentation level 16298 * 16299 * @hide 16300 */ 16301 protected void debug(int depth) { 16302 String output = debugIndent(depth - 1); 16303 16304 output += "+ " + this; 16305 int id = getId(); 16306 if (id != -1) { 16307 output += " (id=" + id + ")"; 16308 } 16309 Object tag = getTag(); 16310 if (tag != null) { 16311 output += " (tag=" + tag + ")"; 16312 } 16313 Log.d(VIEW_LOG_TAG, output); 16314 16315 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 16316 output = debugIndent(depth) + " FOCUSED"; 16317 Log.d(VIEW_LOG_TAG, output); 16318 } 16319 16320 output = debugIndent(depth); 16321 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 16322 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 16323 + "} "; 16324 Log.d(VIEW_LOG_TAG, output); 16325 16326 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 16327 || mPaddingBottom != 0) { 16328 output = debugIndent(depth); 16329 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 16330 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 16331 Log.d(VIEW_LOG_TAG, output); 16332 } 16333 16334 output = debugIndent(depth); 16335 output += "mMeasureWidth=" + mMeasuredWidth + 16336 " mMeasureHeight=" + mMeasuredHeight; 16337 Log.d(VIEW_LOG_TAG, output); 16338 16339 output = debugIndent(depth); 16340 if (mLayoutParams == null) { 16341 output += "BAD! no layout params"; 16342 } else { 16343 output = mLayoutParams.debug(output); 16344 } 16345 Log.d(VIEW_LOG_TAG, output); 16346 16347 output = debugIndent(depth); 16348 output += "flags={"; 16349 output += View.printFlags(mViewFlags); 16350 output += "}"; 16351 Log.d(VIEW_LOG_TAG, output); 16352 16353 output = debugIndent(depth); 16354 output += "privateFlags={"; 16355 output += View.printPrivateFlags(mPrivateFlags); 16356 output += "}"; 16357 Log.d(VIEW_LOG_TAG, output); 16358 } 16359 16360 /** 16361 * Creates a string of whitespaces used for indentation. 16362 * 16363 * @param depth the indentation level 16364 * @return a String containing (depth * 2 + 3) * 2 white spaces 16365 * 16366 * @hide 16367 */ 16368 protected static String debugIndent(int depth) { 16369 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 16370 for (int i = 0; i < (depth * 2) + 3; i++) { 16371 spaces.append(' ').append(' '); 16372 } 16373 return spaces.toString(); 16374 } 16375 16376 /** 16377 * <p>Return the offset of the widget's text baseline from the widget's top 16378 * boundary. If this widget does not support baseline alignment, this 16379 * method returns -1. </p> 16380 * 16381 * @return the offset of the baseline within the widget's bounds or -1 16382 * if baseline alignment is not supported 16383 */ 16384 @ViewDebug.ExportedProperty(category = "layout") 16385 public int getBaseline() { 16386 return -1; 16387 } 16388 16389 /** 16390 * Returns whether the view hierarchy is currently undergoing a layout pass. This 16391 * information is useful to avoid situations such as calling {@link #requestLayout()} during 16392 * a layout pass. 16393 * 16394 * @return whether the view hierarchy is currently undergoing a layout pass 16395 */ 16396 public boolean isInLayout() { 16397 ViewRootImpl viewRoot = getViewRootImpl(); 16398 return (viewRoot != null && viewRoot.isInLayout()); 16399 } 16400 16401 /** 16402 * Call this when something has changed which has invalidated the 16403 * layout of this view. This will schedule a layout pass of the view 16404 * tree. This should not be called while the view hierarchy is currently in a layout 16405 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 16406 * end of the current layout pass (and then layout will run again) or after the current 16407 * frame is drawn and the next layout occurs. 16408 * 16409 * <p>Subclasses which override this method should call the superclass method to 16410 * handle possible request-during-layout errors correctly.</p> 16411 */ 16412 public void requestLayout() { 16413 if (mMeasureCache != null) mMeasureCache.clear(); 16414 16415 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 16416 // Only trigger request-during-layout logic if this is the view requesting it, 16417 // not the views in its parent hierarchy 16418 ViewRootImpl viewRoot = getViewRootImpl(); 16419 if (viewRoot != null && viewRoot.isInLayout()) { 16420 if (!viewRoot.requestLayoutDuringLayout(this)) { 16421 return; 16422 } 16423 } 16424 mAttachInfo.mViewRequestingLayout = this; 16425 } 16426 16427 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 16428 mPrivateFlags |= PFLAG_INVALIDATED; 16429 16430 if (mParent != null && !mParent.isLayoutRequested()) { 16431 mParent.requestLayout(); 16432 } 16433 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 16434 mAttachInfo.mViewRequestingLayout = null; 16435 } 16436 } 16437 16438 /** 16439 * Forces this view to be laid out during the next layout pass. 16440 * This method does not call requestLayout() or forceLayout() 16441 * on the parent. 16442 */ 16443 public void forceLayout() { 16444 if (mMeasureCache != null) mMeasureCache.clear(); 16445 16446 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 16447 mPrivateFlags |= PFLAG_INVALIDATED; 16448 } 16449 16450 /** 16451 * <p> 16452 * This is called to find out how big a view should be. The parent 16453 * supplies constraint information in the width and height parameters. 16454 * </p> 16455 * 16456 * <p> 16457 * The actual measurement work of a view is performed in 16458 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 16459 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 16460 * </p> 16461 * 16462 * 16463 * @param widthMeasureSpec Horizontal space requirements as imposed by the 16464 * parent 16465 * @param heightMeasureSpec Vertical space requirements as imposed by the 16466 * parent 16467 * 16468 * @see #onMeasure(int, int) 16469 */ 16470 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 16471 boolean optical = isLayoutModeOptical(this); 16472 if (optical != isLayoutModeOptical(mParent)) { 16473 Insets insets = getOpticalInsets(); 16474 int oWidth = insets.left + insets.right; 16475 int oHeight = insets.top + insets.bottom; 16476 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 16477 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 16478 } 16479 16480 // Suppress sign extension for the low bytes 16481 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 16482 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 16483 16484 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || 16485 widthMeasureSpec != mOldWidthMeasureSpec || 16486 heightMeasureSpec != mOldHeightMeasureSpec) { 16487 16488 // first clears the measured dimension flag 16489 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 16490 16491 resolveRtlPropertiesIfNeeded(); 16492 16493 int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : 16494 mMeasureCache.indexOfKey(key); 16495 if (cacheIndex < 0 || sIgnoreMeasureCache) { 16496 // measure ourselves, this should set the measured dimension flag back 16497 onMeasure(widthMeasureSpec, heightMeasureSpec); 16498 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 16499 } else { 16500 long value = mMeasureCache.valueAt(cacheIndex); 16501 // Casting a long to int drops the high 32 bits, no mask needed 16502 setMeasuredDimension((int) (value >> 32), (int) value); 16503 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 16504 } 16505 16506 // flag not set, setMeasuredDimension() was not invoked, we raise 16507 // an exception to warn the developer 16508 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 16509 throw new IllegalStateException("onMeasure() did not set the" 16510 + " measured dimension by calling" 16511 + " setMeasuredDimension()"); 16512 } 16513 16514 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 16515 } 16516 16517 mOldWidthMeasureSpec = widthMeasureSpec; 16518 mOldHeightMeasureSpec = heightMeasureSpec; 16519 16520 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 16521 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 16522 } 16523 16524 /** 16525 * <p> 16526 * Measure the view and its content to determine the measured width and the 16527 * measured height. This method is invoked by {@link #measure(int, int)} and 16528 * should be overriden by subclasses to provide accurate and efficient 16529 * measurement of their contents. 16530 * </p> 16531 * 16532 * <p> 16533 * <strong>CONTRACT:</strong> When overriding this method, you 16534 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 16535 * measured width and height of this view. Failure to do so will trigger an 16536 * <code>IllegalStateException</code>, thrown by 16537 * {@link #measure(int, int)}. Calling the superclass' 16538 * {@link #onMeasure(int, int)} is a valid use. 16539 * </p> 16540 * 16541 * <p> 16542 * The base class implementation of measure defaults to the background size, 16543 * unless a larger size is allowed by the MeasureSpec. Subclasses should 16544 * override {@link #onMeasure(int, int)} to provide better measurements of 16545 * their content. 16546 * </p> 16547 * 16548 * <p> 16549 * If this method is overridden, it is the subclass's responsibility to make 16550 * sure the measured height and width are at least the view's minimum height 16551 * and width ({@link #getSuggestedMinimumHeight()} and 16552 * {@link #getSuggestedMinimumWidth()}). 16553 * </p> 16554 * 16555 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 16556 * The requirements are encoded with 16557 * {@link android.view.View.MeasureSpec}. 16558 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 16559 * The requirements are encoded with 16560 * {@link android.view.View.MeasureSpec}. 16561 * 16562 * @see #getMeasuredWidth() 16563 * @see #getMeasuredHeight() 16564 * @see #setMeasuredDimension(int, int) 16565 * @see #getSuggestedMinimumHeight() 16566 * @see #getSuggestedMinimumWidth() 16567 * @see android.view.View.MeasureSpec#getMode(int) 16568 * @see android.view.View.MeasureSpec#getSize(int) 16569 */ 16570 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 16571 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 16572 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 16573 } 16574 16575 /** 16576 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 16577 * measured width and measured height. Failing to do so will trigger an 16578 * exception at measurement time.</p> 16579 * 16580 * @param measuredWidth The measured width of this view. May be a complex 16581 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16582 * {@link #MEASURED_STATE_TOO_SMALL}. 16583 * @param measuredHeight The measured height of this view. May be a complex 16584 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16585 * {@link #MEASURED_STATE_TOO_SMALL}. 16586 */ 16587 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 16588 boolean optical = isLayoutModeOptical(this); 16589 if (optical != isLayoutModeOptical(mParent)) { 16590 Insets insets = getOpticalInsets(); 16591 int opticalWidth = insets.left + insets.right; 16592 int opticalHeight = insets.top + insets.bottom; 16593 16594 measuredWidth += optical ? opticalWidth : -opticalWidth; 16595 measuredHeight += optical ? opticalHeight : -opticalHeight; 16596 } 16597 mMeasuredWidth = measuredWidth; 16598 mMeasuredHeight = measuredHeight; 16599 16600 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 16601 } 16602 16603 /** 16604 * Merge two states as returned by {@link #getMeasuredState()}. 16605 * @param curState The current state as returned from a view or the result 16606 * of combining multiple views. 16607 * @param newState The new view state to combine. 16608 * @return Returns a new integer reflecting the combination of the two 16609 * states. 16610 */ 16611 public static int combineMeasuredStates(int curState, int newState) { 16612 return curState | newState; 16613 } 16614 16615 /** 16616 * Version of {@link #resolveSizeAndState(int, int, int)} 16617 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 16618 */ 16619 public static int resolveSize(int size, int measureSpec) { 16620 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 16621 } 16622 16623 /** 16624 * Utility to reconcile a desired size and state, with constraints imposed 16625 * by a MeasureSpec. Will take the desired size, unless a different size 16626 * is imposed by the constraints. The returned value is a compound integer, 16627 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 16628 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting 16629 * size is smaller than the size the view wants to be. 16630 * 16631 * @param size How big the view wants to be 16632 * @param measureSpec Constraints imposed by the parent 16633 * @return Size information bit mask as defined by 16634 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 16635 */ 16636 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 16637 int result = size; 16638 int specMode = MeasureSpec.getMode(measureSpec); 16639 int specSize = MeasureSpec.getSize(measureSpec); 16640 switch (specMode) { 16641 case MeasureSpec.UNSPECIFIED: 16642 result = size; 16643 break; 16644 case MeasureSpec.AT_MOST: 16645 if (specSize < size) { 16646 result = specSize | MEASURED_STATE_TOO_SMALL; 16647 } else { 16648 result = size; 16649 } 16650 break; 16651 case MeasureSpec.EXACTLY: 16652 result = specSize; 16653 break; 16654 } 16655 return result | (childMeasuredState&MEASURED_STATE_MASK); 16656 } 16657 16658 /** 16659 * Utility to return a default size. Uses the supplied size if the 16660 * MeasureSpec imposed no constraints. Will get larger if allowed 16661 * by the MeasureSpec. 16662 * 16663 * @param size Default size for this view 16664 * @param measureSpec Constraints imposed by the parent 16665 * @return The size this view should be. 16666 */ 16667 public static int getDefaultSize(int size, int measureSpec) { 16668 int result = size; 16669 int specMode = MeasureSpec.getMode(measureSpec); 16670 int specSize = MeasureSpec.getSize(measureSpec); 16671 16672 switch (specMode) { 16673 case MeasureSpec.UNSPECIFIED: 16674 result = size; 16675 break; 16676 case MeasureSpec.AT_MOST: 16677 case MeasureSpec.EXACTLY: 16678 result = specSize; 16679 break; 16680 } 16681 return result; 16682 } 16683 16684 /** 16685 * Returns the suggested minimum height that the view should use. This 16686 * returns the maximum of the view's minimum height 16687 * and the background's minimum height 16688 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 16689 * <p> 16690 * When being used in {@link #onMeasure(int, int)}, the caller should still 16691 * ensure the returned height is within the requirements of the parent. 16692 * 16693 * @return The suggested minimum height of the view. 16694 */ 16695 protected int getSuggestedMinimumHeight() { 16696 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 16697 16698 } 16699 16700 /** 16701 * Returns the suggested minimum width that the view should use. This 16702 * returns the maximum of the view's minimum width) 16703 * and the background's minimum width 16704 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 16705 * <p> 16706 * When being used in {@link #onMeasure(int, int)}, the caller should still 16707 * ensure the returned width is within the requirements of the parent. 16708 * 16709 * @return The suggested minimum width of the view. 16710 */ 16711 protected int getSuggestedMinimumWidth() { 16712 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 16713 } 16714 16715 /** 16716 * Returns the minimum height of the view. 16717 * 16718 * @return the minimum height the view will try to be. 16719 * 16720 * @see #setMinimumHeight(int) 16721 * 16722 * @attr ref android.R.styleable#View_minHeight 16723 */ 16724 public int getMinimumHeight() { 16725 return mMinHeight; 16726 } 16727 16728 /** 16729 * Sets the minimum height of the view. It is not guaranteed the view will 16730 * be able to achieve this minimum height (for example, if its parent layout 16731 * constrains it with less available height). 16732 * 16733 * @param minHeight The minimum height the view will try to be. 16734 * 16735 * @see #getMinimumHeight() 16736 * 16737 * @attr ref android.R.styleable#View_minHeight 16738 */ 16739 public void setMinimumHeight(int minHeight) { 16740 mMinHeight = minHeight; 16741 requestLayout(); 16742 } 16743 16744 /** 16745 * Returns the minimum width of the view. 16746 * 16747 * @return the minimum width the view will try to be. 16748 * 16749 * @see #setMinimumWidth(int) 16750 * 16751 * @attr ref android.R.styleable#View_minWidth 16752 */ 16753 public int getMinimumWidth() { 16754 return mMinWidth; 16755 } 16756 16757 /** 16758 * Sets the minimum width of the view. It is not guaranteed the view will 16759 * be able to achieve this minimum width (for example, if its parent layout 16760 * constrains it with less available width). 16761 * 16762 * @param minWidth The minimum width the view will try to be. 16763 * 16764 * @see #getMinimumWidth() 16765 * 16766 * @attr ref android.R.styleable#View_minWidth 16767 */ 16768 public void setMinimumWidth(int minWidth) { 16769 mMinWidth = minWidth; 16770 requestLayout(); 16771 16772 } 16773 16774 /** 16775 * Get the animation currently associated with this view. 16776 * 16777 * @return The animation that is currently playing or 16778 * scheduled to play for this view. 16779 */ 16780 public Animation getAnimation() { 16781 return mCurrentAnimation; 16782 } 16783 16784 /** 16785 * Start the specified animation now. 16786 * 16787 * @param animation the animation to start now 16788 */ 16789 public void startAnimation(Animation animation) { 16790 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 16791 setAnimation(animation); 16792 invalidateParentCaches(); 16793 invalidate(true); 16794 } 16795 16796 /** 16797 * Cancels any animations for this view. 16798 */ 16799 public void clearAnimation() { 16800 if (mCurrentAnimation != null) { 16801 mCurrentAnimation.detach(); 16802 } 16803 mCurrentAnimation = null; 16804 invalidateParentIfNeeded(); 16805 } 16806 16807 /** 16808 * Sets the next animation to play for this view. 16809 * If you want the animation to play immediately, use 16810 * {@link #startAnimation(android.view.animation.Animation)} instead. 16811 * This method provides allows fine-grained 16812 * control over the start time and invalidation, but you 16813 * must make sure that 1) the animation has a start time set, and 16814 * 2) the view's parent (which controls animations on its children) 16815 * will be invalidated when the animation is supposed to 16816 * start. 16817 * 16818 * @param animation The next animation, or null. 16819 */ 16820 public void setAnimation(Animation animation) { 16821 mCurrentAnimation = animation; 16822 16823 if (animation != null) { 16824 // If the screen is off assume the animation start time is now instead of 16825 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 16826 // would cause the animation to start when the screen turns back on 16827 if (mAttachInfo != null && !mAttachInfo.mScreenOn && 16828 animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 16829 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 16830 } 16831 animation.reset(); 16832 } 16833 } 16834 16835 /** 16836 * Invoked by a parent ViewGroup to notify the start of the animation 16837 * currently associated with this view. If you override this method, 16838 * always call super.onAnimationStart(); 16839 * 16840 * @see #setAnimation(android.view.animation.Animation) 16841 * @see #getAnimation() 16842 */ 16843 protected void onAnimationStart() { 16844 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 16845 } 16846 16847 /** 16848 * Invoked by a parent ViewGroup to notify the end of the animation 16849 * currently associated with this view. If you override this method, 16850 * always call super.onAnimationEnd(); 16851 * 16852 * @see #setAnimation(android.view.animation.Animation) 16853 * @see #getAnimation() 16854 */ 16855 protected void onAnimationEnd() { 16856 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 16857 } 16858 16859 /** 16860 * Invoked if there is a Transform that involves alpha. Subclass that can 16861 * draw themselves with the specified alpha should return true, and then 16862 * respect that alpha when their onDraw() is called. If this returns false 16863 * then the view may be redirected to draw into an offscreen buffer to 16864 * fulfill the request, which will look fine, but may be slower than if the 16865 * subclass handles it internally. The default implementation returns false. 16866 * 16867 * @param alpha The alpha (0..255) to apply to the view's drawing 16868 * @return true if the view can draw with the specified alpha. 16869 */ 16870 protected boolean onSetAlpha(int alpha) { 16871 return false; 16872 } 16873 16874 /** 16875 * This is used by the RootView to perform an optimization when 16876 * the view hierarchy contains one or several SurfaceView. 16877 * SurfaceView is always considered transparent, but its children are not, 16878 * therefore all View objects remove themselves from the global transparent 16879 * region (passed as a parameter to this function). 16880 * 16881 * @param region The transparent region for this ViewAncestor (window). 16882 * 16883 * @return Returns true if the effective visibility of the view at this 16884 * point is opaque, regardless of the transparent region; returns false 16885 * if it is possible for underlying windows to be seen behind the view. 16886 * 16887 * {@hide} 16888 */ 16889 public boolean gatherTransparentRegion(Region region) { 16890 final AttachInfo attachInfo = mAttachInfo; 16891 if (region != null && attachInfo != null) { 16892 final int pflags = mPrivateFlags; 16893 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 16894 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 16895 // remove it from the transparent region. 16896 final int[] location = attachInfo.mTransparentLocation; 16897 getLocationInWindow(location); 16898 region.op(location[0], location[1], location[0] + mRight - mLeft, 16899 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 16900 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) { 16901 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable 16902 // exists, so we remove the background drawable's non-transparent 16903 // parts from this transparent region. 16904 applyDrawableToTransparentRegion(mBackground, region); 16905 } 16906 } 16907 return true; 16908 } 16909 16910 /** 16911 * Play a sound effect for this view. 16912 * 16913 * <p>The framework will play sound effects for some built in actions, such as 16914 * clicking, but you may wish to play these effects in your widget, 16915 * for instance, for internal navigation. 16916 * 16917 * <p>The sound effect will only be played if sound effects are enabled by the user, and 16918 * {@link #isSoundEffectsEnabled()} is true. 16919 * 16920 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 16921 */ 16922 public void playSoundEffect(int soundConstant) { 16923 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 16924 return; 16925 } 16926 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 16927 } 16928 16929 /** 16930 * BZZZTT!!1! 16931 * 16932 * <p>Provide haptic feedback to the user for this view. 16933 * 16934 * <p>The framework will provide haptic feedback for some built in actions, 16935 * such as long presses, but you may wish to provide feedback for your 16936 * own widget. 16937 * 16938 * <p>The feedback will only be performed if 16939 * {@link #isHapticFeedbackEnabled()} is true. 16940 * 16941 * @param feedbackConstant One of the constants defined in 16942 * {@link HapticFeedbackConstants} 16943 */ 16944 public boolean performHapticFeedback(int feedbackConstant) { 16945 return performHapticFeedback(feedbackConstant, 0); 16946 } 16947 16948 /** 16949 * BZZZTT!!1! 16950 * 16951 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 16952 * 16953 * @param feedbackConstant One of the constants defined in 16954 * {@link HapticFeedbackConstants} 16955 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 16956 */ 16957 public boolean performHapticFeedback(int feedbackConstant, int flags) { 16958 if (mAttachInfo == null) { 16959 return false; 16960 } 16961 //noinspection SimplifiableIfStatement 16962 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 16963 && !isHapticFeedbackEnabled()) { 16964 return false; 16965 } 16966 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 16967 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 16968 } 16969 16970 /** 16971 * Request that the visibility of the status bar or other screen/window 16972 * decorations be changed. 16973 * 16974 * <p>This method is used to put the over device UI into temporary modes 16975 * where the user's attention is focused more on the application content, 16976 * by dimming or hiding surrounding system affordances. This is typically 16977 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 16978 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 16979 * to be placed behind the action bar (and with these flags other system 16980 * affordances) so that smooth transitions between hiding and showing them 16981 * can be done. 16982 * 16983 * <p>Two representative examples of the use of system UI visibility is 16984 * implementing a content browsing application (like a magazine reader) 16985 * and a video playing application. 16986 * 16987 * <p>The first code shows a typical implementation of a View in a content 16988 * browsing application. In this implementation, the application goes 16989 * into a content-oriented mode by hiding the status bar and action bar, 16990 * and putting the navigation elements into lights out mode. The user can 16991 * then interact with content while in this mode. Such an application should 16992 * provide an easy way for the user to toggle out of the mode (such as to 16993 * check information in the status bar or access notifications). In the 16994 * implementation here, this is done simply by tapping on the content. 16995 * 16996 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 16997 * content} 16998 * 16999 * <p>This second code sample shows a typical implementation of a View 17000 * in a video playing application. In this situation, while the video is 17001 * playing the application would like to go into a complete full-screen mode, 17002 * to use as much of the display as possible for the video. When in this state 17003 * the user can not interact with the application; the system intercepts 17004 * touching on the screen to pop the UI out of full screen mode. See 17005 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 17006 * 17007 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 17008 * content} 17009 * 17010 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 17011 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 17012 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 17013 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 17014 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 17015 */ 17016 public void setSystemUiVisibility(int visibility) { 17017 if (visibility != mSystemUiVisibility) { 17018 mSystemUiVisibility = visibility; 17019 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 17020 mParent.recomputeViewAttributes(this); 17021 } 17022 } 17023 } 17024 17025 /** 17026 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 17027 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 17028 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 17029 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 17030 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 17031 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 17032 */ 17033 public int getSystemUiVisibility() { 17034 return mSystemUiVisibility; 17035 } 17036 17037 /** 17038 * Returns the current system UI visibility that is currently set for 17039 * the entire window. This is the combination of the 17040 * {@link #setSystemUiVisibility(int)} values supplied by all of the 17041 * views in the window. 17042 */ 17043 public int getWindowSystemUiVisibility() { 17044 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 17045 } 17046 17047 /** 17048 * Override to find out when the window's requested system UI visibility 17049 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 17050 * This is different from the callbacks received through 17051 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 17052 * in that this is only telling you about the local request of the window, 17053 * not the actual values applied by the system. 17054 */ 17055 public void onWindowSystemUiVisibilityChanged(int visible) { 17056 } 17057 17058 /** 17059 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 17060 * the view hierarchy. 17061 */ 17062 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 17063 onWindowSystemUiVisibilityChanged(visible); 17064 } 17065 17066 /** 17067 * Set a listener to receive callbacks when the visibility of the system bar changes. 17068 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 17069 */ 17070 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 17071 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 17072 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 17073 mParent.recomputeViewAttributes(this); 17074 } 17075 } 17076 17077 /** 17078 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 17079 * the view hierarchy. 17080 */ 17081 public void dispatchSystemUiVisibilityChanged(int visibility) { 17082 ListenerInfo li = mListenerInfo; 17083 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 17084 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 17085 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 17086 } 17087 } 17088 17089 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 17090 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 17091 if (val != mSystemUiVisibility) { 17092 setSystemUiVisibility(val); 17093 return true; 17094 } 17095 return false; 17096 } 17097 17098 /** @hide */ 17099 public void setDisabledSystemUiVisibility(int flags) { 17100 if (mAttachInfo != null) { 17101 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 17102 mAttachInfo.mDisabledSystemUiVisibility = flags; 17103 if (mParent != null) { 17104 mParent.recomputeViewAttributes(this); 17105 } 17106 } 17107 } 17108 } 17109 17110 /** 17111 * Creates an image that the system displays during the drag and drop 17112 * operation. This is called a "drag shadow". The default implementation 17113 * for a DragShadowBuilder based on a View returns an image that has exactly the same 17114 * appearance as the given View. The default also positions the center of the drag shadow 17115 * directly under the touch point. If no View is provided (the constructor with no parameters 17116 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 17117 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the 17118 * default is an invisible drag shadow. 17119 * <p> 17120 * You are not required to use the View you provide to the constructor as the basis of the 17121 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 17122 * anything you want as the drag shadow. 17123 * </p> 17124 * <p> 17125 * You pass a DragShadowBuilder object to the system when you start the drag. The system 17126 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 17127 * size and position of the drag shadow. It uses this data to construct a 17128 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 17129 * so that your application can draw the shadow image in the Canvas. 17130 * </p> 17131 * 17132 * <div class="special reference"> 17133 * <h3>Developer Guides</h3> 17134 * <p>For a guide to implementing drag and drop features, read the 17135 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 17136 * </div> 17137 */ 17138 public static class DragShadowBuilder { 17139 private final WeakReference<View> mView; 17140 17141 /** 17142 * Constructs a shadow image builder based on a View. By default, the resulting drag 17143 * shadow will have the same appearance and dimensions as the View, with the touch point 17144 * over the center of the View. 17145 * @param view A View. Any View in scope can be used. 17146 */ 17147 public DragShadowBuilder(View view) { 17148 mView = new WeakReference<View>(view); 17149 } 17150 17151 /** 17152 * Construct a shadow builder object with no associated View. This 17153 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 17154 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 17155 * to supply the drag shadow's dimensions and appearance without 17156 * reference to any View object. If they are not overridden, then the result is an 17157 * invisible drag shadow. 17158 */ 17159 public DragShadowBuilder() { 17160 mView = new WeakReference<View>(null); 17161 } 17162 17163 /** 17164 * Returns the View object that had been passed to the 17165 * {@link #View.DragShadowBuilder(View)} 17166 * constructor. If that View parameter was {@code null} or if the 17167 * {@link #View.DragShadowBuilder()} 17168 * constructor was used to instantiate the builder object, this method will return 17169 * null. 17170 * 17171 * @return The View object associate with this builder object. 17172 */ 17173 @SuppressWarnings({"JavadocReference"}) 17174 final public View getView() { 17175 return mView.get(); 17176 } 17177 17178 /** 17179 * Provides the metrics for the shadow image. These include the dimensions of 17180 * the shadow image, and the point within that shadow that should 17181 * be centered under the touch location while dragging. 17182 * <p> 17183 * The default implementation sets the dimensions of the shadow to be the 17184 * same as the dimensions of the View itself and centers the shadow under 17185 * the touch point. 17186 * </p> 17187 * 17188 * @param shadowSize A {@link android.graphics.Point} containing the width and height 17189 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 17190 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 17191 * image. 17192 * 17193 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the 17194 * shadow image that should be underneath the touch point during the drag and drop 17195 * operation. Your application must set {@link android.graphics.Point#x} to the 17196 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 17197 */ 17198 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 17199 final View view = mView.get(); 17200 if (view != null) { 17201 shadowSize.set(view.getWidth(), view.getHeight()); 17202 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 17203 } else { 17204 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 17205 } 17206 } 17207 17208 /** 17209 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 17210 * based on the dimensions it received from the 17211 * {@link #onProvideShadowMetrics(Point, Point)} callback. 17212 * 17213 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 17214 */ 17215 public void onDrawShadow(Canvas canvas) { 17216 final View view = mView.get(); 17217 if (view != null) { 17218 view.draw(canvas); 17219 } else { 17220 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 17221 } 17222 } 17223 } 17224 17225 /** 17226 * Starts a drag and drop operation. When your application calls this method, it passes a 17227 * {@link android.view.View.DragShadowBuilder} object to the system. The 17228 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 17229 * to get metrics for the drag shadow, and then calls the object's 17230 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 17231 * <p> 17232 * Once the system has the drag shadow, it begins the drag and drop operation by sending 17233 * drag events to all the View objects in your application that are currently visible. It does 17234 * this either by calling the View object's drag listener (an implementation of 17235 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 17236 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 17237 * Both are passed a {@link android.view.DragEvent} object that has a 17238 * {@link android.view.DragEvent#getAction()} value of 17239 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 17240 * </p> 17241 * <p> 17242 * Your application can invoke startDrag() on any attached View object. The View object does not 17243 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to 17244 * be related to the View the user selected for dragging. 17245 * </p> 17246 * @param data A {@link android.content.ClipData} object pointing to the data to be 17247 * transferred by the drag and drop operation. 17248 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 17249 * drag shadow. 17250 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 17251 * drop operation. This Object is put into every DragEvent object sent by the system during the 17252 * current drag. 17253 * <p> 17254 * myLocalState is a lightweight mechanism for the sending information from the dragged View 17255 * to the target Views. For example, it can contain flags that differentiate between a 17256 * a copy operation and a move operation. 17257 * </p> 17258 * @param flags Flags that control the drag and drop operation. No flags are currently defined, 17259 * so the parameter should be set to 0. 17260 * @return {@code true} if the method completes successfully, or 17261 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 17262 * do a drag, and so no drag operation is in progress. 17263 */ 17264 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 17265 Object myLocalState, int flags) { 17266 if (ViewDebug.DEBUG_DRAG) { 17267 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags); 17268 } 17269 boolean okay = false; 17270 17271 Point shadowSize = new Point(); 17272 Point shadowTouchPoint = new Point(); 17273 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 17274 17275 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 17276 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 17277 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 17278 } 17279 17280 if (ViewDebug.DEBUG_DRAG) { 17281 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 17282 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 17283 } 17284 Surface surface = new Surface(); 17285 try { 17286 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 17287 flags, shadowSize.x, shadowSize.y, surface); 17288 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token 17289 + " surface=" + surface); 17290 if (token != null) { 17291 Canvas canvas = surface.lockCanvas(null); 17292 try { 17293 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 17294 shadowBuilder.onDrawShadow(canvas); 17295 } finally { 17296 surface.unlockCanvasAndPost(canvas); 17297 } 17298 17299 final ViewRootImpl root = getViewRootImpl(); 17300 17301 // Cache the local state object for delivery with DragEvents 17302 root.setLocalDragState(myLocalState); 17303 17304 // repurpose 'shadowSize' for the last touch point 17305 root.getLastTouchPoint(shadowSize); 17306 17307 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token, 17308 shadowSize.x, shadowSize.y, 17309 shadowTouchPoint.x, shadowTouchPoint.y, data); 17310 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 17311 17312 // Off and running! Release our local surface instance; the drag 17313 // shadow surface is now managed by the system process. 17314 surface.release(); 17315 } 17316 } catch (Exception e) { 17317 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 17318 surface.destroy(); 17319 } 17320 17321 return okay; 17322 } 17323 17324 /** 17325 * Handles drag events sent by the system following a call to 17326 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}. 17327 *<p> 17328 * When the system calls this method, it passes a 17329 * {@link android.view.DragEvent} object. A call to 17330 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 17331 * in DragEvent. The method uses these to determine what is happening in the drag and drop 17332 * operation. 17333 * @param event The {@link android.view.DragEvent} sent by the system. 17334 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 17335 * in DragEvent, indicating the type of drag event represented by this object. 17336 * @return {@code true} if the method was successful, otherwise {@code false}. 17337 * <p> 17338 * The method should return {@code true} in response to an action type of 17339 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 17340 * operation. 17341 * </p> 17342 * <p> 17343 * The method should also return {@code true} in response to an action type of 17344 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 17345 * {@code false} if it didn't. 17346 * </p> 17347 */ 17348 public boolean onDragEvent(DragEvent event) { 17349 return false; 17350 } 17351 17352 /** 17353 * Detects if this View is enabled and has a drag event listener. 17354 * If both are true, then it calls the drag event listener with the 17355 * {@link android.view.DragEvent} it received. If the drag event listener returns 17356 * {@code true}, then dispatchDragEvent() returns {@code true}. 17357 * <p> 17358 * For all other cases, the method calls the 17359 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 17360 * method and returns its result. 17361 * </p> 17362 * <p> 17363 * This ensures that a drag event is always consumed, even if the View does not have a drag 17364 * event listener. However, if the View has a listener and the listener returns true, then 17365 * onDragEvent() is not called. 17366 * </p> 17367 */ 17368 public boolean dispatchDragEvent(DragEvent event) { 17369 ListenerInfo li = mListenerInfo; 17370 //noinspection SimplifiableIfStatement 17371 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 17372 && li.mOnDragListener.onDrag(this, event)) { 17373 return true; 17374 } 17375 return onDragEvent(event); 17376 } 17377 17378 boolean canAcceptDrag() { 17379 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 17380 } 17381 17382 /** 17383 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 17384 * it is ever exposed at all. 17385 * @hide 17386 */ 17387 public void onCloseSystemDialogs(String reason) { 17388 } 17389 17390 /** 17391 * Given a Drawable whose bounds have been set to draw into this view, 17392 * update a Region being computed for 17393 * {@link #gatherTransparentRegion(android.graphics.Region)} so 17394 * that any non-transparent parts of the Drawable are removed from the 17395 * given transparent region. 17396 * 17397 * @param dr The Drawable whose transparency is to be applied to the region. 17398 * @param region A Region holding the current transparency information, 17399 * where any parts of the region that are set are considered to be 17400 * transparent. On return, this region will be modified to have the 17401 * transparency information reduced by the corresponding parts of the 17402 * Drawable that are not transparent. 17403 * {@hide} 17404 */ 17405 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 17406 if (DBG) { 17407 Log.i("View", "Getting transparent region for: " + this); 17408 } 17409 final Region r = dr.getTransparentRegion(); 17410 final Rect db = dr.getBounds(); 17411 final AttachInfo attachInfo = mAttachInfo; 17412 if (r != null && attachInfo != null) { 17413 final int w = getRight()-getLeft(); 17414 final int h = getBottom()-getTop(); 17415 if (db.left > 0) { 17416 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 17417 r.op(0, 0, db.left, h, Region.Op.UNION); 17418 } 17419 if (db.right < w) { 17420 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 17421 r.op(db.right, 0, w, h, Region.Op.UNION); 17422 } 17423 if (db.top > 0) { 17424 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 17425 r.op(0, 0, w, db.top, Region.Op.UNION); 17426 } 17427 if (db.bottom < h) { 17428 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 17429 r.op(0, db.bottom, w, h, Region.Op.UNION); 17430 } 17431 final int[] location = attachInfo.mTransparentLocation; 17432 getLocationInWindow(location); 17433 r.translate(location[0], location[1]); 17434 region.op(r, Region.Op.INTERSECT); 17435 } else { 17436 region.op(db, Region.Op.DIFFERENCE); 17437 } 17438 } 17439 17440 private void checkForLongClick(int delayOffset) { 17441 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 17442 mHasPerformedLongPress = false; 17443 17444 if (mPendingCheckForLongPress == null) { 17445 mPendingCheckForLongPress = new CheckForLongPress(); 17446 } 17447 mPendingCheckForLongPress.rememberWindowAttachCount(); 17448 postDelayed(mPendingCheckForLongPress, 17449 ViewConfiguration.getLongPressTimeout() - delayOffset); 17450 } 17451 } 17452 17453 /** 17454 * Inflate a view from an XML resource. This convenience method wraps the {@link 17455 * LayoutInflater} class, which provides a full range of options for view inflation. 17456 * 17457 * @param context The Context object for your activity or application. 17458 * @param resource The resource ID to inflate 17459 * @param root A view group that will be the parent. Used to properly inflate the 17460 * layout_* parameters. 17461 * @see LayoutInflater 17462 */ 17463 public static View inflate(Context context, int resource, ViewGroup root) { 17464 LayoutInflater factory = LayoutInflater.from(context); 17465 return factory.inflate(resource, root); 17466 } 17467 17468 /** 17469 * Scroll the view with standard behavior for scrolling beyond the normal 17470 * content boundaries. Views that call this method should override 17471 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 17472 * results of an over-scroll operation. 17473 * 17474 * Views can use this method to handle any touch or fling-based scrolling. 17475 * 17476 * @param deltaX Change in X in pixels 17477 * @param deltaY Change in Y in pixels 17478 * @param scrollX Current X scroll value in pixels before applying deltaX 17479 * @param scrollY Current Y scroll value in pixels before applying deltaY 17480 * @param scrollRangeX Maximum content scroll range along the X axis 17481 * @param scrollRangeY Maximum content scroll range along the Y axis 17482 * @param maxOverScrollX Number of pixels to overscroll by in either direction 17483 * along the X axis. 17484 * @param maxOverScrollY Number of pixels to overscroll by in either direction 17485 * along the Y axis. 17486 * @param isTouchEvent true if this scroll operation is the result of a touch event. 17487 * @return true if scrolling was clamped to an over-scroll boundary along either 17488 * axis, false otherwise. 17489 */ 17490 @SuppressWarnings({"UnusedParameters"}) 17491 protected boolean overScrollBy(int deltaX, int deltaY, 17492 int scrollX, int scrollY, 17493 int scrollRangeX, int scrollRangeY, 17494 int maxOverScrollX, int maxOverScrollY, 17495 boolean isTouchEvent) { 17496 final int overScrollMode = mOverScrollMode; 17497 final boolean canScrollHorizontal = 17498 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 17499 final boolean canScrollVertical = 17500 computeVerticalScrollRange() > computeVerticalScrollExtent(); 17501 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 17502 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 17503 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 17504 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 17505 17506 int newScrollX = scrollX + deltaX; 17507 if (!overScrollHorizontal) { 17508 maxOverScrollX = 0; 17509 } 17510 17511 int newScrollY = scrollY + deltaY; 17512 if (!overScrollVertical) { 17513 maxOverScrollY = 0; 17514 } 17515 17516 // Clamp values if at the limits and record 17517 final int left = -maxOverScrollX; 17518 final int right = maxOverScrollX + scrollRangeX; 17519 final int top = -maxOverScrollY; 17520 final int bottom = maxOverScrollY + scrollRangeY; 17521 17522 boolean clampedX = false; 17523 if (newScrollX > right) { 17524 newScrollX = right; 17525 clampedX = true; 17526 } else if (newScrollX < left) { 17527 newScrollX = left; 17528 clampedX = true; 17529 } 17530 17531 boolean clampedY = false; 17532 if (newScrollY > bottom) { 17533 newScrollY = bottom; 17534 clampedY = true; 17535 } else if (newScrollY < top) { 17536 newScrollY = top; 17537 clampedY = true; 17538 } 17539 17540 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 17541 17542 return clampedX || clampedY; 17543 } 17544 17545 /** 17546 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 17547 * respond to the results of an over-scroll operation. 17548 * 17549 * @param scrollX New X scroll value in pixels 17550 * @param scrollY New Y scroll value in pixels 17551 * @param clampedX True if scrollX was clamped to an over-scroll boundary 17552 * @param clampedY True if scrollY was clamped to an over-scroll boundary 17553 */ 17554 protected void onOverScrolled(int scrollX, int scrollY, 17555 boolean clampedX, boolean clampedY) { 17556 // Intentionally empty. 17557 } 17558 17559 /** 17560 * Returns the over-scroll mode for this view. The result will be 17561 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 17562 * (allow over-scrolling only if the view content is larger than the container), 17563 * or {@link #OVER_SCROLL_NEVER}. 17564 * 17565 * @return This view's over-scroll mode. 17566 */ 17567 public int getOverScrollMode() { 17568 return mOverScrollMode; 17569 } 17570 17571 /** 17572 * Set the over-scroll mode for this view. Valid over-scroll modes are 17573 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 17574 * (allow over-scrolling only if the view content is larger than the container), 17575 * or {@link #OVER_SCROLL_NEVER}. 17576 * 17577 * Setting the over-scroll mode of a view will have an effect only if the 17578 * view is capable of scrolling. 17579 * 17580 * @param overScrollMode The new over-scroll mode for this view. 17581 */ 17582 public void setOverScrollMode(int overScrollMode) { 17583 if (overScrollMode != OVER_SCROLL_ALWAYS && 17584 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 17585 overScrollMode != OVER_SCROLL_NEVER) { 17586 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 17587 } 17588 mOverScrollMode = overScrollMode; 17589 } 17590 17591 /** 17592 * Gets a scale factor that determines the distance the view should scroll 17593 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 17594 * @return The vertical scroll scale factor. 17595 * @hide 17596 */ 17597 protected float getVerticalScrollFactor() { 17598 if (mVerticalScrollFactor == 0) { 17599 TypedValue outValue = new TypedValue(); 17600 if (!mContext.getTheme().resolveAttribute( 17601 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 17602 throw new IllegalStateException( 17603 "Expected theme to define listPreferredItemHeight."); 17604 } 17605 mVerticalScrollFactor = outValue.getDimension( 17606 mContext.getResources().getDisplayMetrics()); 17607 } 17608 return mVerticalScrollFactor; 17609 } 17610 17611 /** 17612 * Gets a scale factor that determines the distance the view should scroll 17613 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 17614 * @return The horizontal scroll scale factor. 17615 * @hide 17616 */ 17617 protected float getHorizontalScrollFactor() { 17618 // TODO: Should use something else. 17619 return getVerticalScrollFactor(); 17620 } 17621 17622 /** 17623 * Return the value specifying the text direction or policy that was set with 17624 * {@link #setTextDirection(int)}. 17625 * 17626 * @return the defined text direction. It can be one of: 17627 * 17628 * {@link #TEXT_DIRECTION_INHERIT}, 17629 * {@link #TEXT_DIRECTION_FIRST_STRONG} 17630 * {@link #TEXT_DIRECTION_ANY_RTL}, 17631 * {@link #TEXT_DIRECTION_LTR}, 17632 * {@link #TEXT_DIRECTION_RTL}, 17633 * {@link #TEXT_DIRECTION_LOCALE} 17634 * 17635 * @attr ref android.R.styleable#View_textDirection 17636 * 17637 * @hide 17638 */ 17639 @ViewDebug.ExportedProperty(category = "text", mapping = { 17640 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 17641 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 17642 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 17643 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 17644 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 17645 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE") 17646 }) 17647 public int getRawTextDirection() { 17648 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 17649 } 17650 17651 /** 17652 * Set the text direction. 17653 * 17654 * @param textDirection the direction to set. Should be one of: 17655 * 17656 * {@link #TEXT_DIRECTION_INHERIT}, 17657 * {@link #TEXT_DIRECTION_FIRST_STRONG} 17658 * {@link #TEXT_DIRECTION_ANY_RTL}, 17659 * {@link #TEXT_DIRECTION_LTR}, 17660 * {@link #TEXT_DIRECTION_RTL}, 17661 * {@link #TEXT_DIRECTION_LOCALE} 17662 * 17663 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 17664 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 17665 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 17666 * 17667 * @attr ref android.R.styleable#View_textDirection 17668 */ 17669 public void setTextDirection(int textDirection) { 17670 if (getRawTextDirection() != textDirection) { 17671 // Reset the current text direction and the resolved one 17672 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 17673 resetResolvedTextDirection(); 17674 // Set the new text direction 17675 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 17676 // Do resolution 17677 resolveTextDirection(); 17678 // Notify change 17679 onRtlPropertiesChanged(getLayoutDirection()); 17680 // Refresh 17681 requestLayout(); 17682 invalidate(true); 17683 } 17684 } 17685 17686 /** 17687 * Return the resolved text direction. 17688 * 17689 * @return the resolved text direction. Returns one of: 17690 * 17691 * {@link #TEXT_DIRECTION_FIRST_STRONG} 17692 * {@link #TEXT_DIRECTION_ANY_RTL}, 17693 * {@link #TEXT_DIRECTION_LTR}, 17694 * {@link #TEXT_DIRECTION_RTL}, 17695 * {@link #TEXT_DIRECTION_LOCALE} 17696 * 17697 * @attr ref android.R.styleable#View_textDirection 17698 */ 17699 @ViewDebug.ExportedProperty(category = "text", mapping = { 17700 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 17701 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 17702 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 17703 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 17704 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 17705 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE") 17706 }) 17707 public int getTextDirection() { 17708 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 17709 } 17710 17711 /** 17712 * Resolve the text direction. 17713 * 17714 * @return true if resolution has been done, false otherwise. 17715 * 17716 * @hide 17717 */ 17718 public boolean resolveTextDirection() { 17719 // Reset any previous text direction resolution 17720 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 17721 17722 if (hasRtlSupport()) { 17723 // Set resolved text direction flag depending on text direction flag 17724 final int textDirection = getRawTextDirection(); 17725 switch(textDirection) { 17726 case TEXT_DIRECTION_INHERIT: 17727 if (!canResolveTextDirection()) { 17728 // We cannot do the resolution if there is no parent, so use the default one 17729 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17730 // Resolution will need to happen again later 17731 return false; 17732 } 17733 17734 // Parent has not yet resolved, so we still return the default 17735 try { 17736 if (!mParent.isTextDirectionResolved()) { 17737 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17738 // Resolution will need to happen again later 17739 return false; 17740 } 17741 } catch (AbstractMethodError e) { 17742 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 17743 " does not fully implement ViewParent", e); 17744 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 17745 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17746 return true; 17747 } 17748 17749 // Set current resolved direction to the same value as the parent's one 17750 int parentResolvedDirection; 17751 try { 17752 parentResolvedDirection = mParent.getTextDirection(); 17753 } catch (AbstractMethodError e) { 17754 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 17755 " does not fully implement ViewParent", e); 17756 parentResolvedDirection = TEXT_DIRECTION_LTR; 17757 } 17758 switch (parentResolvedDirection) { 17759 case TEXT_DIRECTION_FIRST_STRONG: 17760 case TEXT_DIRECTION_ANY_RTL: 17761 case TEXT_DIRECTION_LTR: 17762 case TEXT_DIRECTION_RTL: 17763 case TEXT_DIRECTION_LOCALE: 17764 mPrivateFlags2 |= 17765 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 17766 break; 17767 default: 17768 // Default resolved direction is "first strong" heuristic 17769 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17770 } 17771 break; 17772 case TEXT_DIRECTION_FIRST_STRONG: 17773 case TEXT_DIRECTION_ANY_RTL: 17774 case TEXT_DIRECTION_LTR: 17775 case TEXT_DIRECTION_RTL: 17776 case TEXT_DIRECTION_LOCALE: 17777 // Resolved direction is the same as text direction 17778 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 17779 break; 17780 default: 17781 // Default resolved direction is "first strong" heuristic 17782 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17783 } 17784 } else { 17785 // Default resolved direction is "first strong" heuristic 17786 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17787 } 17788 17789 // Set to resolved 17790 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 17791 return true; 17792 } 17793 17794 /** 17795 * Check if text direction resolution can be done. 17796 * 17797 * @return true if text direction resolution can be done otherwise return false. 17798 */ 17799 public boolean canResolveTextDirection() { 17800 switch (getRawTextDirection()) { 17801 case TEXT_DIRECTION_INHERIT: 17802 if (mParent != null) { 17803 try { 17804 return mParent.canResolveTextDirection(); 17805 } catch (AbstractMethodError e) { 17806 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 17807 " does not fully implement ViewParent", e); 17808 } 17809 } 17810 return false; 17811 17812 default: 17813 return true; 17814 } 17815 } 17816 17817 /** 17818 * Reset resolved text direction. Text direction will be resolved during a call to 17819 * {@link #onMeasure(int, int)}. 17820 * 17821 * @hide 17822 */ 17823 public void resetResolvedTextDirection() { 17824 // Reset any previous text direction resolution 17825 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 17826 // Set to default value 17827 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 17828 } 17829 17830 /** 17831 * @return true if text direction is inherited. 17832 * 17833 * @hide 17834 */ 17835 public boolean isTextDirectionInherited() { 17836 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 17837 } 17838 17839 /** 17840 * @return true if text direction is resolved. 17841 */ 17842 public boolean isTextDirectionResolved() { 17843 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 17844 } 17845 17846 /** 17847 * Return the value specifying the text alignment or policy that was set with 17848 * {@link #setTextAlignment(int)}. 17849 * 17850 * @return the defined text alignment. It can be one of: 17851 * 17852 * {@link #TEXT_ALIGNMENT_INHERIT}, 17853 * {@link #TEXT_ALIGNMENT_GRAVITY}, 17854 * {@link #TEXT_ALIGNMENT_CENTER}, 17855 * {@link #TEXT_ALIGNMENT_TEXT_START}, 17856 * {@link #TEXT_ALIGNMENT_TEXT_END}, 17857 * {@link #TEXT_ALIGNMENT_VIEW_START}, 17858 * {@link #TEXT_ALIGNMENT_VIEW_END} 17859 * 17860 * @attr ref android.R.styleable#View_textAlignment 17861 * 17862 * @hide 17863 */ 17864 @ViewDebug.ExportedProperty(category = "text", mapping = { 17865 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 17866 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 17867 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 17868 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 17869 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 17870 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 17871 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 17872 }) 17873 public int getRawTextAlignment() { 17874 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 17875 } 17876 17877 /** 17878 * Set the text alignment. 17879 * 17880 * @param textAlignment The text alignment to set. Should be one of 17881 * 17882 * {@link #TEXT_ALIGNMENT_INHERIT}, 17883 * {@link #TEXT_ALIGNMENT_GRAVITY}, 17884 * {@link #TEXT_ALIGNMENT_CENTER}, 17885 * {@link #TEXT_ALIGNMENT_TEXT_START}, 17886 * {@link #TEXT_ALIGNMENT_TEXT_END}, 17887 * {@link #TEXT_ALIGNMENT_VIEW_START}, 17888 * {@link #TEXT_ALIGNMENT_VIEW_END} 17889 * 17890 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 17891 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 17892 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 17893 * 17894 * @attr ref android.R.styleable#View_textAlignment 17895 */ 17896 public void setTextAlignment(int textAlignment) { 17897 if (textAlignment != getRawTextAlignment()) { 17898 // Reset the current and resolved text alignment 17899 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 17900 resetResolvedTextAlignment(); 17901 // Set the new text alignment 17902 mPrivateFlags2 |= 17903 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 17904 // Do resolution 17905 resolveTextAlignment(); 17906 // Notify change 17907 onRtlPropertiesChanged(getLayoutDirection()); 17908 // Refresh 17909 requestLayout(); 17910 invalidate(true); 17911 } 17912 } 17913 17914 /** 17915 * Return the resolved text alignment. 17916 * 17917 * @return the resolved text alignment. Returns one of: 17918 * 17919 * {@link #TEXT_ALIGNMENT_GRAVITY}, 17920 * {@link #TEXT_ALIGNMENT_CENTER}, 17921 * {@link #TEXT_ALIGNMENT_TEXT_START}, 17922 * {@link #TEXT_ALIGNMENT_TEXT_END}, 17923 * {@link #TEXT_ALIGNMENT_VIEW_START}, 17924 * {@link #TEXT_ALIGNMENT_VIEW_END} 17925 * 17926 * @attr ref android.R.styleable#View_textAlignment 17927 */ 17928 @ViewDebug.ExportedProperty(category = "text", mapping = { 17929 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 17930 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 17931 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 17932 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 17933 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 17934 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 17935 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 17936 }) 17937 public int getTextAlignment() { 17938 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 17939 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 17940 } 17941 17942 /** 17943 * Resolve the text alignment. 17944 * 17945 * @return true if resolution has been done, false otherwise. 17946 * 17947 * @hide 17948 */ 17949 public boolean resolveTextAlignment() { 17950 // Reset any previous text alignment resolution 17951 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 17952 17953 if (hasRtlSupport()) { 17954 // Set resolved text alignment flag depending on text alignment flag 17955 final int textAlignment = getRawTextAlignment(); 17956 switch (textAlignment) { 17957 case TEXT_ALIGNMENT_INHERIT: 17958 // Check if we can resolve the text alignment 17959 if (!canResolveTextAlignment()) { 17960 // We cannot do the resolution if there is no parent so use the default 17961 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 17962 // Resolution will need to happen again later 17963 return false; 17964 } 17965 17966 // Parent has not yet resolved, so we still return the default 17967 try { 17968 if (!mParent.isTextAlignmentResolved()) { 17969 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 17970 // Resolution will need to happen again later 17971 return false; 17972 } 17973 } catch (AbstractMethodError e) { 17974 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 17975 " does not fully implement ViewParent", e); 17976 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 17977 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 17978 return true; 17979 } 17980 17981 int parentResolvedTextAlignment; 17982 try { 17983 parentResolvedTextAlignment = mParent.getTextAlignment(); 17984 } catch (AbstractMethodError e) { 17985 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 17986 " does not fully implement ViewParent", e); 17987 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 17988 } 17989 switch (parentResolvedTextAlignment) { 17990 case TEXT_ALIGNMENT_GRAVITY: 17991 case TEXT_ALIGNMENT_TEXT_START: 17992 case TEXT_ALIGNMENT_TEXT_END: 17993 case TEXT_ALIGNMENT_CENTER: 17994 case TEXT_ALIGNMENT_VIEW_START: 17995 case TEXT_ALIGNMENT_VIEW_END: 17996 // Resolved text alignment is the same as the parent resolved 17997 // text alignment 17998 mPrivateFlags2 |= 17999 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 18000 break; 18001 default: 18002 // Use default resolved text alignment 18003 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18004 } 18005 break; 18006 case TEXT_ALIGNMENT_GRAVITY: 18007 case TEXT_ALIGNMENT_TEXT_START: 18008 case TEXT_ALIGNMENT_TEXT_END: 18009 case TEXT_ALIGNMENT_CENTER: 18010 case TEXT_ALIGNMENT_VIEW_START: 18011 case TEXT_ALIGNMENT_VIEW_END: 18012 // Resolved text alignment is the same as text alignment 18013 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 18014 break; 18015 default: 18016 // Use default resolved text alignment 18017 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18018 } 18019 } else { 18020 // Use default resolved text alignment 18021 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18022 } 18023 18024 // Set the resolved 18025 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 18026 return true; 18027 } 18028 18029 /** 18030 * Check if text alignment resolution can be done. 18031 * 18032 * @return true if text alignment resolution can be done otherwise return false. 18033 */ 18034 public boolean canResolveTextAlignment() { 18035 switch (getRawTextAlignment()) { 18036 case TEXT_DIRECTION_INHERIT: 18037 if (mParent != null) { 18038 try { 18039 return mParent.canResolveTextAlignment(); 18040 } catch (AbstractMethodError e) { 18041 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18042 " does not fully implement ViewParent", e); 18043 } 18044 } 18045 return false; 18046 18047 default: 18048 return true; 18049 } 18050 } 18051 18052 /** 18053 * Reset resolved text alignment. Text alignment will be resolved during a call to 18054 * {@link #onMeasure(int, int)}. 18055 * 18056 * @hide 18057 */ 18058 public void resetResolvedTextAlignment() { 18059 // Reset any previous text alignment resolution 18060 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 18061 // Set to default 18062 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18063 } 18064 18065 /** 18066 * @return true if text alignment is inherited. 18067 * 18068 * @hide 18069 */ 18070 public boolean isTextAlignmentInherited() { 18071 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 18072 } 18073 18074 /** 18075 * @return true if text alignment is resolved. 18076 */ 18077 public boolean isTextAlignmentResolved() { 18078 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 18079 } 18080 18081 /** 18082 * Generate a value suitable for use in {@link #setId(int)}. 18083 * This value will not collide with ID values generated at build time by aapt for R.id. 18084 * 18085 * @return a generated ID value 18086 */ 18087 public static int generateViewId() { 18088 for (;;) { 18089 final int result = sNextGeneratedId.get(); 18090 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 18091 int newValue = result + 1; 18092 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 18093 if (sNextGeneratedId.compareAndSet(result, newValue)) { 18094 return result; 18095 } 18096 } 18097 } 18098 18099 // 18100 // Properties 18101 // 18102 /** 18103 * A Property wrapper around the <code>alpha</code> functionality handled by the 18104 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 18105 */ 18106 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 18107 @Override 18108 public void setValue(View object, float value) { 18109 object.setAlpha(value); 18110 } 18111 18112 @Override 18113 public Float get(View object) { 18114 return object.getAlpha(); 18115 } 18116 }; 18117 18118 /** 18119 * A Property wrapper around the <code>translationX</code> functionality handled by the 18120 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 18121 */ 18122 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 18123 @Override 18124 public void setValue(View object, float value) { 18125 object.setTranslationX(value); 18126 } 18127 18128 @Override 18129 public Float get(View object) { 18130 return object.getTranslationX(); 18131 } 18132 }; 18133 18134 /** 18135 * A Property wrapper around the <code>translationY</code> functionality handled by the 18136 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 18137 */ 18138 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 18139 @Override 18140 public void setValue(View object, float value) { 18141 object.setTranslationY(value); 18142 } 18143 18144 @Override 18145 public Float get(View object) { 18146 return object.getTranslationY(); 18147 } 18148 }; 18149 18150 /** 18151 * A Property wrapper around the <code>x</code> functionality handled by the 18152 * {@link View#setX(float)} and {@link View#getX()} methods. 18153 */ 18154 public static final Property<View, Float> X = new FloatProperty<View>("x") { 18155 @Override 18156 public void setValue(View object, float value) { 18157 object.setX(value); 18158 } 18159 18160 @Override 18161 public Float get(View object) { 18162 return object.getX(); 18163 } 18164 }; 18165 18166 /** 18167 * A Property wrapper around the <code>y</code> functionality handled by the 18168 * {@link View#setY(float)} and {@link View#getY()} methods. 18169 */ 18170 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 18171 @Override 18172 public void setValue(View object, float value) { 18173 object.setY(value); 18174 } 18175 18176 @Override 18177 public Float get(View object) { 18178 return object.getY(); 18179 } 18180 }; 18181 18182 /** 18183 * A Property wrapper around the <code>rotation</code> functionality handled by the 18184 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 18185 */ 18186 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 18187 @Override 18188 public void setValue(View object, float value) { 18189 object.setRotation(value); 18190 } 18191 18192 @Override 18193 public Float get(View object) { 18194 return object.getRotation(); 18195 } 18196 }; 18197 18198 /** 18199 * A Property wrapper around the <code>rotationX</code> functionality handled by the 18200 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 18201 */ 18202 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 18203 @Override 18204 public void setValue(View object, float value) { 18205 object.setRotationX(value); 18206 } 18207 18208 @Override 18209 public Float get(View object) { 18210 return object.getRotationX(); 18211 } 18212 }; 18213 18214 /** 18215 * A Property wrapper around the <code>rotationY</code> functionality handled by the 18216 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 18217 */ 18218 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 18219 @Override 18220 public void setValue(View object, float value) { 18221 object.setRotationY(value); 18222 } 18223 18224 @Override 18225 public Float get(View object) { 18226 return object.getRotationY(); 18227 } 18228 }; 18229 18230 /** 18231 * A Property wrapper around the <code>scaleX</code> functionality handled by the 18232 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 18233 */ 18234 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 18235 @Override 18236 public void setValue(View object, float value) { 18237 object.setScaleX(value); 18238 } 18239 18240 @Override 18241 public Float get(View object) { 18242 return object.getScaleX(); 18243 } 18244 }; 18245 18246 /** 18247 * A Property wrapper around the <code>scaleY</code> functionality handled by the 18248 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 18249 */ 18250 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 18251 @Override 18252 public void setValue(View object, float value) { 18253 object.setScaleY(value); 18254 } 18255 18256 @Override 18257 public Float get(View object) { 18258 return object.getScaleY(); 18259 } 18260 }; 18261 18262 /** 18263 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 18264 * Each MeasureSpec represents a requirement for either the width or the height. 18265 * A MeasureSpec is comprised of a size and a mode. There are three possible 18266 * modes: 18267 * <dl> 18268 * <dt>UNSPECIFIED</dt> 18269 * <dd> 18270 * The parent has not imposed any constraint on the child. It can be whatever size 18271 * it wants. 18272 * </dd> 18273 * 18274 * <dt>EXACTLY</dt> 18275 * <dd> 18276 * The parent has determined an exact size for the child. The child is going to be 18277 * given those bounds regardless of how big it wants to be. 18278 * </dd> 18279 * 18280 * <dt>AT_MOST</dt> 18281 * <dd> 18282 * The child can be as large as it wants up to the specified size. 18283 * </dd> 18284 * </dl> 18285 * 18286 * MeasureSpecs are implemented as ints to reduce object allocation. This class 18287 * is provided to pack and unpack the <size, mode> tuple into the int. 18288 */ 18289 public static class MeasureSpec { 18290 private static final int MODE_SHIFT = 30; 18291 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 18292 18293 /** 18294 * Measure specification mode: The parent has not imposed any constraint 18295 * on the child. It can be whatever size it wants. 18296 */ 18297 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 18298 18299 /** 18300 * Measure specification mode: The parent has determined an exact size 18301 * for the child. The child is going to be given those bounds regardless 18302 * of how big it wants to be. 18303 */ 18304 public static final int EXACTLY = 1 << MODE_SHIFT; 18305 18306 /** 18307 * Measure specification mode: The child can be as large as it wants up 18308 * to the specified size. 18309 */ 18310 public static final int AT_MOST = 2 << MODE_SHIFT; 18311 18312 /** 18313 * Creates a measure specification based on the supplied size and mode. 18314 * 18315 * The mode must always be one of the following: 18316 * <ul> 18317 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 18318 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 18319 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 18320 * </ul> 18321 * 18322 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 18323 * implementation was such that the order of arguments did not matter 18324 * and overflow in either value could impact the resulting MeasureSpec. 18325 * {@link android.widget.RelativeLayout} was affected by this bug. 18326 * Apps targeting API levels greater than 17 will get the fixed, more strict 18327 * behavior.</p> 18328 * 18329 * @param size the size of the measure specification 18330 * @param mode the mode of the measure specification 18331 * @return the measure specification based on size and mode 18332 */ 18333 public static int makeMeasureSpec(int size, int mode) { 18334 if (sUseBrokenMakeMeasureSpec) { 18335 return size + mode; 18336 } else { 18337 return (size & ~MODE_MASK) | (mode & MODE_MASK); 18338 } 18339 } 18340 18341 /** 18342 * Extracts the mode from the supplied measure specification. 18343 * 18344 * @param measureSpec the measure specification to extract the mode from 18345 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 18346 * {@link android.view.View.MeasureSpec#AT_MOST} or 18347 * {@link android.view.View.MeasureSpec#EXACTLY} 18348 */ 18349 public static int getMode(int measureSpec) { 18350 return (measureSpec & MODE_MASK); 18351 } 18352 18353 /** 18354 * Extracts the size from the supplied measure specification. 18355 * 18356 * @param measureSpec the measure specification to extract the size from 18357 * @return the size in pixels defined in the supplied measure specification 18358 */ 18359 public static int getSize(int measureSpec) { 18360 return (measureSpec & ~MODE_MASK); 18361 } 18362 18363 static int adjust(int measureSpec, int delta) { 18364 return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec)); 18365 } 18366 18367 /** 18368 * Returns a String representation of the specified measure 18369 * specification. 18370 * 18371 * @param measureSpec the measure specification to convert to a String 18372 * @return a String with the following format: "MeasureSpec: MODE SIZE" 18373 */ 18374 public static String toString(int measureSpec) { 18375 int mode = getMode(measureSpec); 18376 int size = getSize(measureSpec); 18377 18378 StringBuilder sb = new StringBuilder("MeasureSpec: "); 18379 18380 if (mode == UNSPECIFIED) 18381 sb.append("UNSPECIFIED "); 18382 else if (mode == EXACTLY) 18383 sb.append("EXACTLY "); 18384 else if (mode == AT_MOST) 18385 sb.append("AT_MOST "); 18386 else 18387 sb.append(mode).append(" "); 18388 18389 sb.append(size); 18390 return sb.toString(); 18391 } 18392 } 18393 18394 class CheckForLongPress implements Runnable { 18395 18396 private int mOriginalWindowAttachCount; 18397 18398 public void run() { 18399 if (isPressed() && (mParent != null) 18400 && mOriginalWindowAttachCount == mWindowAttachCount) { 18401 if (performLongClick()) { 18402 mHasPerformedLongPress = true; 18403 } 18404 } 18405 } 18406 18407 public void rememberWindowAttachCount() { 18408 mOriginalWindowAttachCount = mWindowAttachCount; 18409 } 18410 } 18411 18412 private final class CheckForTap implements Runnable { 18413 public void run() { 18414 mPrivateFlags &= ~PFLAG_PREPRESSED; 18415 setPressed(true); 18416 checkForLongClick(ViewConfiguration.getTapTimeout()); 18417 } 18418 } 18419 18420 private final class PerformClick implements Runnable { 18421 public void run() { 18422 performClick(); 18423 } 18424 } 18425 18426 /** @hide */ 18427 public void hackTurnOffWindowResizeAnim(boolean off) { 18428 mAttachInfo.mTurnOffWindowResizeAnim = off; 18429 } 18430 18431 /** 18432 * This method returns a ViewPropertyAnimator object, which can be used to animate 18433 * specific properties on this View. 18434 * 18435 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 18436 */ 18437 public ViewPropertyAnimator animate() { 18438 if (mAnimator == null) { 18439 mAnimator = new ViewPropertyAnimator(this); 18440 } 18441 return mAnimator; 18442 } 18443 18444 /** 18445 * Interface definition for a callback to be invoked when a hardware key event is 18446 * dispatched to this view. The callback will be invoked before the key event is 18447 * given to the view. This is only useful for hardware keyboards; a software input 18448 * method has no obligation to trigger this listener. 18449 */ 18450 public interface OnKeyListener { 18451 /** 18452 * Called when a hardware key is dispatched to a view. This allows listeners to 18453 * get a chance to respond before the target view. 18454 * <p>Key presses in software keyboards will generally NOT trigger this method, 18455 * although some may elect to do so in some situations. Do not assume a 18456 * software input method has to be key-based; even if it is, it may use key presses 18457 * in a different way than you expect, so there is no way to reliably catch soft 18458 * input key presses. 18459 * 18460 * @param v The view the key has been dispatched to. 18461 * @param keyCode The code for the physical key that was pressed 18462 * @param event The KeyEvent object containing full information about 18463 * the event. 18464 * @return True if the listener has consumed the event, false otherwise. 18465 */ 18466 boolean onKey(View v, int keyCode, KeyEvent event); 18467 } 18468 18469 /** 18470 * Interface definition for a callback to be invoked when a touch event is 18471 * dispatched to this view. The callback will be invoked before the touch 18472 * event is given to the view. 18473 */ 18474 public interface OnTouchListener { 18475 /** 18476 * Called when a touch event is dispatched to a view. This allows listeners to 18477 * get a chance to respond before the target view. 18478 * 18479 * @param v The view the touch event has been dispatched to. 18480 * @param event The MotionEvent object containing full information about 18481 * the event. 18482 * @return True if the listener has consumed the event, false otherwise. 18483 */ 18484 boolean onTouch(View v, MotionEvent event); 18485 } 18486 18487 /** 18488 * Interface definition for a callback to be invoked when a hover event is 18489 * dispatched to this view. The callback will be invoked before the hover 18490 * event is given to the view. 18491 */ 18492 public interface OnHoverListener { 18493 /** 18494 * Called when a hover event is dispatched to a view. This allows listeners to 18495 * get a chance to respond before the target view. 18496 * 18497 * @param v The view the hover event has been dispatched to. 18498 * @param event The MotionEvent object containing full information about 18499 * the event. 18500 * @return True if the listener has consumed the event, false otherwise. 18501 */ 18502 boolean onHover(View v, MotionEvent event); 18503 } 18504 18505 /** 18506 * Interface definition for a callback to be invoked when a generic motion event is 18507 * dispatched to this view. The callback will be invoked before the generic motion 18508 * event is given to the view. 18509 */ 18510 public interface OnGenericMotionListener { 18511 /** 18512 * Called when a generic motion event is dispatched to a view. This allows listeners to 18513 * get a chance to respond before the target view. 18514 * 18515 * @param v The view the generic motion event has been dispatched to. 18516 * @param event The MotionEvent object containing full information about 18517 * the event. 18518 * @return True if the listener has consumed the event, false otherwise. 18519 */ 18520 boolean onGenericMotion(View v, MotionEvent event); 18521 } 18522 18523 /** 18524 * Interface definition for a callback to be invoked when a view has been clicked and held. 18525 */ 18526 public interface OnLongClickListener { 18527 /** 18528 * Called when a view has been clicked and held. 18529 * 18530 * @param v The view that was clicked and held. 18531 * 18532 * @return true if the callback consumed the long click, false otherwise. 18533 */ 18534 boolean onLongClick(View v); 18535 } 18536 18537 /** 18538 * Interface definition for a callback to be invoked when a drag is being dispatched 18539 * to this view. The callback will be invoked before the hosting view's own 18540 * onDrag(event) method. If the listener wants to fall back to the hosting view's 18541 * onDrag(event) behavior, it should return 'false' from this callback. 18542 * 18543 * <div class="special reference"> 18544 * <h3>Developer Guides</h3> 18545 * <p>For a guide to implementing drag and drop features, read the 18546 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 18547 * </div> 18548 */ 18549 public interface OnDragListener { 18550 /** 18551 * Called when a drag event is dispatched to a view. This allows listeners 18552 * to get a chance to override base View behavior. 18553 * 18554 * @param v The View that received the drag event. 18555 * @param event The {@link android.view.DragEvent} object for the drag event. 18556 * @return {@code true} if the drag event was handled successfully, or {@code false} 18557 * if the drag event was not handled. Note that {@code false} will trigger the View 18558 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 18559 */ 18560 boolean onDrag(View v, DragEvent event); 18561 } 18562 18563 /** 18564 * Interface definition for a callback to be invoked when the focus state of 18565 * a view changed. 18566 */ 18567 public interface OnFocusChangeListener { 18568 /** 18569 * Called when the focus state of a view has changed. 18570 * 18571 * @param v The view whose state has changed. 18572 * @param hasFocus The new focus state of v. 18573 */ 18574 void onFocusChange(View v, boolean hasFocus); 18575 } 18576 18577 /** 18578 * Interface definition for a callback to be invoked when a view is clicked. 18579 */ 18580 public interface OnClickListener { 18581 /** 18582 * Called when a view has been clicked. 18583 * 18584 * @param v The view that was clicked. 18585 */ 18586 void onClick(View v); 18587 } 18588 18589 /** 18590 * Interface definition for a callback to be invoked when the context menu 18591 * for this view is being built. 18592 */ 18593 public interface OnCreateContextMenuListener { 18594 /** 18595 * Called when the context menu for this view is being built. It is not 18596 * safe to hold onto the menu after this method returns. 18597 * 18598 * @param menu The context menu that is being built 18599 * @param v The view for which the context menu is being built 18600 * @param menuInfo Extra information about the item for which the 18601 * context menu should be shown. This information will vary 18602 * depending on the class of v. 18603 */ 18604 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 18605 } 18606 18607 /** 18608 * Interface definition for a callback to be invoked when the status bar changes 18609 * visibility. This reports <strong>global</strong> changes to the system UI 18610 * state, not what the application is requesting. 18611 * 18612 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 18613 */ 18614 public interface OnSystemUiVisibilityChangeListener { 18615 /** 18616 * Called when the status bar changes visibility because of a call to 18617 * {@link View#setSystemUiVisibility(int)}. 18618 * 18619 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 18620 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 18621 * This tells you the <strong>global</strong> state of these UI visibility 18622 * flags, not what your app is currently applying. 18623 */ 18624 public void onSystemUiVisibilityChange(int visibility); 18625 } 18626 18627 /** 18628 * Interface definition for a callback to be invoked when this view is attached 18629 * or detached from its window. 18630 */ 18631 public interface OnAttachStateChangeListener { 18632 /** 18633 * Called when the view is attached to a window. 18634 * @param v The view that was attached 18635 */ 18636 public void onViewAttachedToWindow(View v); 18637 /** 18638 * Called when the view is detached from a window. 18639 * @param v The view that was detached 18640 */ 18641 public void onViewDetachedFromWindow(View v); 18642 } 18643 18644 private final class UnsetPressedState implements Runnable { 18645 public void run() { 18646 setPressed(false); 18647 } 18648 } 18649 18650 /** 18651 * Base class for derived classes that want to save and restore their own 18652 * state in {@link android.view.View#onSaveInstanceState()}. 18653 */ 18654 public static class BaseSavedState extends AbsSavedState { 18655 /** 18656 * Constructor used when reading from a parcel. Reads the state of the superclass. 18657 * 18658 * @param source 18659 */ 18660 public BaseSavedState(Parcel source) { 18661 super(source); 18662 } 18663 18664 /** 18665 * Constructor called by derived classes when creating their SavedState objects 18666 * 18667 * @param superState The state of the superclass of this view 18668 */ 18669 public BaseSavedState(Parcelable superState) { 18670 super(superState); 18671 } 18672 18673 public static final Parcelable.Creator<BaseSavedState> CREATOR = 18674 new Parcelable.Creator<BaseSavedState>() { 18675 public BaseSavedState createFromParcel(Parcel in) { 18676 return new BaseSavedState(in); 18677 } 18678 18679 public BaseSavedState[] newArray(int size) { 18680 return new BaseSavedState[size]; 18681 } 18682 }; 18683 } 18684 18685 /** 18686 * A set of information given to a view when it is attached to its parent 18687 * window. 18688 */ 18689 static class AttachInfo { 18690 interface Callbacks { 18691 void playSoundEffect(int effectId); 18692 boolean performHapticFeedback(int effectId, boolean always); 18693 } 18694 18695 /** 18696 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 18697 * to a Handler. This class contains the target (View) to invalidate and 18698 * the coordinates of the dirty rectangle. 18699 * 18700 * For performance purposes, this class also implements a pool of up to 18701 * POOL_LIMIT objects that get reused. This reduces memory allocations 18702 * whenever possible. 18703 */ 18704 static class InvalidateInfo { 18705 private static final int POOL_LIMIT = 10; 18706 18707 private static final SynchronizedPool<InvalidateInfo> sPool = 18708 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 18709 18710 View target; 18711 18712 int left; 18713 int top; 18714 int right; 18715 int bottom; 18716 18717 public static InvalidateInfo obtain() { 18718 InvalidateInfo instance = sPool.acquire(); 18719 return (instance != null) ? instance : new InvalidateInfo(); 18720 } 18721 18722 public void recycle() { 18723 target = null; 18724 sPool.release(this); 18725 } 18726 } 18727 18728 final IWindowSession mSession; 18729 18730 final IWindow mWindow; 18731 18732 final IBinder mWindowToken; 18733 18734 final Display mDisplay; 18735 18736 final Callbacks mRootCallbacks; 18737 18738 HardwareCanvas mHardwareCanvas; 18739 18740 IWindowId mIWindowId; 18741 WindowId mWindowId; 18742 18743 /** 18744 * The top view of the hierarchy. 18745 */ 18746 View mRootView; 18747 18748 IBinder mPanelParentWindowToken; 18749 Surface mSurface; 18750 18751 boolean mHardwareAccelerated; 18752 boolean mHardwareAccelerationRequested; 18753 HardwareRenderer mHardwareRenderer; 18754 18755 boolean mScreenOn; 18756 18757 /** 18758 * Scale factor used by the compatibility mode 18759 */ 18760 float mApplicationScale; 18761 18762 /** 18763 * Indicates whether the application is in compatibility mode 18764 */ 18765 boolean mScalingRequired; 18766 18767 /** 18768 * If set, ViewRootImpl doesn't use its lame animation for when the window resizes. 18769 */ 18770 boolean mTurnOffWindowResizeAnim; 18771 18772 /** 18773 * Left position of this view's window 18774 */ 18775 int mWindowLeft; 18776 18777 /** 18778 * Top position of this view's window 18779 */ 18780 int mWindowTop; 18781 18782 /** 18783 * Indicates whether views need to use 32-bit drawing caches 18784 */ 18785 boolean mUse32BitDrawingCache; 18786 18787 /** 18788 * For windows that are full-screen but using insets to layout inside 18789 * of the screen areas, these are the current insets to appear inside 18790 * the overscan area of the display. 18791 */ 18792 final Rect mOverscanInsets = new Rect(); 18793 18794 /** 18795 * For windows that are full-screen but using insets to layout inside 18796 * of the screen decorations, these are the current insets for the 18797 * content of the window. 18798 */ 18799 final Rect mContentInsets = new Rect(); 18800 18801 /** 18802 * For windows that are full-screen but using insets to layout inside 18803 * of the screen decorations, these are the current insets for the 18804 * actual visible parts of the window. 18805 */ 18806 final Rect mVisibleInsets = new Rect(); 18807 18808 /** 18809 * The internal insets given by this window. This value is 18810 * supplied by the client (through 18811 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 18812 * be given to the window manager when changed to be used in laying 18813 * out windows behind it. 18814 */ 18815 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 18816 = new ViewTreeObserver.InternalInsetsInfo(); 18817 18818 /** 18819 * Set to true when mGivenInternalInsets is non-empty. 18820 */ 18821 boolean mHasNonEmptyGivenInternalInsets; 18822 18823 /** 18824 * All views in the window's hierarchy that serve as scroll containers, 18825 * used to determine if the window can be resized or must be panned 18826 * to adjust for a soft input area. 18827 */ 18828 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 18829 18830 final KeyEvent.DispatcherState mKeyDispatchState 18831 = new KeyEvent.DispatcherState(); 18832 18833 /** 18834 * Indicates whether the view's window currently has the focus. 18835 */ 18836 boolean mHasWindowFocus; 18837 18838 /** 18839 * The current visibility of the window. 18840 */ 18841 int mWindowVisibility; 18842 18843 /** 18844 * Indicates the time at which drawing started to occur. 18845 */ 18846 long mDrawingTime; 18847 18848 /** 18849 * Indicates whether or not ignoring the DIRTY_MASK flags. 18850 */ 18851 boolean mIgnoreDirtyState; 18852 18853 /** 18854 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 18855 * to avoid clearing that flag prematurely. 18856 */ 18857 boolean mSetIgnoreDirtyState = false; 18858 18859 /** 18860 * Indicates whether the view's window is currently in touch mode. 18861 */ 18862 boolean mInTouchMode; 18863 18864 /** 18865 * Indicates that ViewAncestor should trigger a global layout change 18866 * the next time it performs a traversal 18867 */ 18868 boolean mRecomputeGlobalAttributes; 18869 18870 /** 18871 * Always report new attributes at next traversal. 18872 */ 18873 boolean mForceReportNewAttributes; 18874 18875 /** 18876 * Set during a traveral if any views want to keep the screen on. 18877 */ 18878 boolean mKeepScreenOn; 18879 18880 /** 18881 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 18882 */ 18883 int mSystemUiVisibility; 18884 18885 /** 18886 * Hack to force certain system UI visibility flags to be cleared. 18887 */ 18888 int mDisabledSystemUiVisibility; 18889 18890 /** 18891 * Last global system UI visibility reported by the window manager. 18892 */ 18893 int mGlobalSystemUiVisibility; 18894 18895 /** 18896 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 18897 * attached. 18898 */ 18899 boolean mHasSystemUiListeners; 18900 18901 /** 18902 * Set if the window has requested to extend into the overscan region 18903 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 18904 */ 18905 boolean mOverscanRequested; 18906 18907 /** 18908 * Set if the visibility of any views has changed. 18909 */ 18910 boolean mViewVisibilityChanged; 18911 18912 /** 18913 * Set to true if a view has been scrolled. 18914 */ 18915 boolean mViewScrollChanged; 18916 18917 /** 18918 * Global to the view hierarchy used as a temporary for dealing with 18919 * x/y points in the transparent region computations. 18920 */ 18921 final int[] mTransparentLocation = new int[2]; 18922 18923 /** 18924 * Global to the view hierarchy used as a temporary for dealing with 18925 * x/y points in the ViewGroup.invalidateChild implementation. 18926 */ 18927 final int[] mInvalidateChildLocation = new int[2]; 18928 18929 18930 /** 18931 * Global to the view hierarchy used as a temporary for dealing with 18932 * x/y location when view is transformed. 18933 */ 18934 final float[] mTmpTransformLocation = new float[2]; 18935 18936 /** 18937 * The view tree observer used to dispatch global events like 18938 * layout, pre-draw, touch mode change, etc. 18939 */ 18940 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 18941 18942 /** 18943 * A Canvas used by the view hierarchy to perform bitmap caching. 18944 */ 18945 Canvas mCanvas; 18946 18947 /** 18948 * The view root impl. 18949 */ 18950 final ViewRootImpl mViewRootImpl; 18951 18952 /** 18953 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 18954 * handler can be used to pump events in the UI events queue. 18955 */ 18956 final Handler mHandler; 18957 18958 /** 18959 * Temporary for use in computing invalidate rectangles while 18960 * calling up the hierarchy. 18961 */ 18962 final Rect mTmpInvalRect = new Rect(); 18963 18964 /** 18965 * Temporary for use in computing hit areas with transformed views 18966 */ 18967 final RectF mTmpTransformRect = new RectF(); 18968 18969 /** 18970 * Temporary for use in transforming invalidation rect 18971 */ 18972 final Matrix mTmpMatrix = new Matrix(); 18973 18974 /** 18975 * Temporary for use in transforming invalidation rect 18976 */ 18977 final Transformation mTmpTransformation = new Transformation(); 18978 18979 /** 18980 * Temporary list for use in collecting focusable descendents of a view. 18981 */ 18982 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 18983 18984 /** 18985 * The id of the window for accessibility purposes. 18986 */ 18987 int mAccessibilityWindowId = View.NO_ID; 18988 18989 /** 18990 * Flags related to accessibility processing. 18991 * 18992 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 18993 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 18994 */ 18995 int mAccessibilityFetchFlags; 18996 18997 /** 18998 * The drawable for highlighting accessibility focus. 18999 */ 19000 Drawable mAccessibilityFocusDrawable; 19001 19002 /** 19003 * Show where the margins, bounds and layout bounds are for each view. 19004 */ 19005 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 19006 19007 /** 19008 * Point used to compute visible regions. 19009 */ 19010 final Point mPoint = new Point(); 19011 19012 /** 19013 * Used to track which View originated a requestLayout() call, used when 19014 * requestLayout() is called during layout. 19015 */ 19016 View mViewRequestingLayout; 19017 19018 /** 19019 * Creates a new set of attachment information with the specified 19020 * events handler and thread. 19021 * 19022 * @param handler the events handler the view must use 19023 */ 19024 AttachInfo(IWindowSession session, IWindow window, Display display, 19025 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { 19026 mSession = session; 19027 mWindow = window; 19028 mWindowToken = window.asBinder(); 19029 mDisplay = display; 19030 mViewRootImpl = viewRootImpl; 19031 mHandler = handler; 19032 mRootCallbacks = effectPlayer; 19033 } 19034 } 19035 19036 /** 19037 * <p>ScrollabilityCache holds various fields used by a View when scrolling 19038 * is supported. This avoids keeping too many unused fields in most 19039 * instances of View.</p> 19040 */ 19041 private static class ScrollabilityCache implements Runnable { 19042 19043 /** 19044 * Scrollbars are not visible 19045 */ 19046 public static final int OFF = 0; 19047 19048 /** 19049 * Scrollbars are visible 19050 */ 19051 public static final int ON = 1; 19052 19053 /** 19054 * Scrollbars are fading away 19055 */ 19056 public static final int FADING = 2; 19057 19058 public boolean fadeScrollBars; 19059 19060 public int fadingEdgeLength; 19061 public int scrollBarDefaultDelayBeforeFade; 19062 public int scrollBarFadeDuration; 19063 19064 public int scrollBarSize; 19065 public ScrollBarDrawable scrollBar; 19066 public float[] interpolatorValues; 19067 public View host; 19068 19069 public final Paint paint; 19070 public final Matrix matrix; 19071 public Shader shader; 19072 19073 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 19074 19075 private static final float[] OPAQUE = { 255 }; 19076 private static final float[] TRANSPARENT = { 0.0f }; 19077 19078 /** 19079 * When fading should start. This time moves into the future every time 19080 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 19081 */ 19082 public long fadeStartTime; 19083 19084 19085 /** 19086 * The current state of the scrollbars: ON, OFF, or FADING 19087 */ 19088 public int state = OFF; 19089 19090 private int mLastColor; 19091 19092 public ScrollabilityCache(ViewConfiguration configuration, View host) { 19093 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 19094 scrollBarSize = configuration.getScaledScrollBarSize(); 19095 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 19096 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 19097 19098 paint = new Paint(); 19099 matrix = new Matrix(); 19100 // use use a height of 1, and then wack the matrix each time we 19101 // actually use it. 19102 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 19103 paint.setShader(shader); 19104 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 19105 19106 this.host = host; 19107 } 19108 19109 public void setFadeColor(int color) { 19110 if (color != mLastColor) { 19111 mLastColor = color; 19112 19113 if (color != 0) { 19114 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 19115 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 19116 paint.setShader(shader); 19117 // Restore the default transfer mode (src_over) 19118 paint.setXfermode(null); 19119 } else { 19120 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 19121 paint.setShader(shader); 19122 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 19123 } 19124 } 19125 } 19126 19127 public void run() { 19128 long now = AnimationUtils.currentAnimationTimeMillis(); 19129 if (now >= fadeStartTime) { 19130 19131 // the animation fades the scrollbars out by changing 19132 // the opacity (alpha) from fully opaque to fully 19133 // transparent 19134 int nextFrame = (int) now; 19135 int framesCount = 0; 19136 19137 Interpolator interpolator = scrollBarInterpolator; 19138 19139 // Start opaque 19140 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 19141 19142 // End transparent 19143 nextFrame += scrollBarFadeDuration; 19144 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 19145 19146 state = FADING; 19147 19148 // Kick off the fade animation 19149 host.invalidate(true); 19150 } 19151 } 19152 } 19153 19154 /** 19155 * Resuable callback for sending 19156 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 19157 */ 19158 private class SendViewScrolledAccessibilityEvent implements Runnable { 19159 public volatile boolean mIsPending; 19160 19161 public void run() { 19162 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 19163 mIsPending = false; 19164 } 19165 } 19166 19167 /** 19168 * <p> 19169 * This class represents a delegate that can be registered in a {@link View} 19170 * to enhance accessibility support via composition rather via inheritance. 19171 * It is specifically targeted to widget developers that extend basic View 19172 * classes i.e. classes in package android.view, that would like their 19173 * applications to be backwards compatible. 19174 * </p> 19175 * <div class="special reference"> 19176 * <h3>Developer Guides</h3> 19177 * <p>For more information about making applications accessible, read the 19178 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 19179 * developer guide.</p> 19180 * </div> 19181 * <p> 19182 * A scenario in which a developer would like to use an accessibility delegate 19183 * is overriding a method introduced in a later API version then the minimal API 19184 * version supported by the application. For example, the method 19185 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 19186 * in API version 4 when the accessibility APIs were first introduced. If a 19187 * developer would like his application to run on API version 4 devices (assuming 19188 * all other APIs used by the application are version 4 or lower) and take advantage 19189 * of this method, instead of overriding the method which would break the application's 19190 * backwards compatibility, he can override the corresponding method in this 19191 * delegate and register the delegate in the target View if the API version of 19192 * the system is high enough i.e. the API version is same or higher to the API 19193 * version that introduced 19194 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 19195 * </p> 19196 * <p> 19197 * Here is an example implementation: 19198 * </p> 19199 * <code><pre><p> 19200 * if (Build.VERSION.SDK_INT >= 14) { 19201 * // If the API version is equal of higher than the version in 19202 * // which onInitializeAccessibilityNodeInfo was introduced we 19203 * // register a delegate with a customized implementation. 19204 * View view = findViewById(R.id.view_id); 19205 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 19206 * public void onInitializeAccessibilityNodeInfo(View host, 19207 * AccessibilityNodeInfo info) { 19208 * // Let the default implementation populate the info. 19209 * super.onInitializeAccessibilityNodeInfo(host, info); 19210 * // Set some other information. 19211 * info.setEnabled(host.isEnabled()); 19212 * } 19213 * }); 19214 * } 19215 * </code></pre></p> 19216 * <p> 19217 * This delegate contains methods that correspond to the accessibility methods 19218 * in View. If a delegate has been specified the implementation in View hands 19219 * off handling to the corresponding method in this delegate. The default 19220 * implementation the delegate methods behaves exactly as the corresponding 19221 * method in View for the case of no accessibility delegate been set. Hence, 19222 * to customize the behavior of a View method, clients can override only the 19223 * corresponding delegate method without altering the behavior of the rest 19224 * accessibility related methods of the host view. 19225 * </p> 19226 */ 19227 public static class AccessibilityDelegate { 19228 19229 /** 19230 * Sends an accessibility event of the given type. If accessibility is not 19231 * enabled this method has no effect. 19232 * <p> 19233 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 19234 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 19235 * been set. 19236 * </p> 19237 * 19238 * @param host The View hosting the delegate. 19239 * @param eventType The type of the event to send. 19240 * 19241 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 19242 */ 19243 public void sendAccessibilityEvent(View host, int eventType) { 19244 host.sendAccessibilityEventInternal(eventType); 19245 } 19246 19247 /** 19248 * Performs the specified accessibility action on the view. For 19249 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 19250 * <p> 19251 * The default implementation behaves as 19252 * {@link View#performAccessibilityAction(int, Bundle) 19253 * View#performAccessibilityAction(int, Bundle)} for the case of 19254 * no accessibility delegate been set. 19255 * </p> 19256 * 19257 * @param action The action to perform. 19258 * @return Whether the action was performed. 19259 * 19260 * @see View#performAccessibilityAction(int, Bundle) 19261 * View#performAccessibilityAction(int, Bundle) 19262 */ 19263 public boolean performAccessibilityAction(View host, int action, Bundle args) { 19264 return host.performAccessibilityActionInternal(action, args); 19265 } 19266 19267 /** 19268 * Sends an accessibility event. This method behaves exactly as 19269 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 19270 * empty {@link AccessibilityEvent} and does not perform a check whether 19271 * accessibility is enabled. 19272 * <p> 19273 * The default implementation behaves as 19274 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19275 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 19276 * the case of no accessibility delegate been set. 19277 * </p> 19278 * 19279 * @param host The View hosting the delegate. 19280 * @param event The event to send. 19281 * 19282 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19283 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19284 */ 19285 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 19286 host.sendAccessibilityEventUncheckedInternal(event); 19287 } 19288 19289 /** 19290 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 19291 * to its children for adding their text content to the event. 19292 * <p> 19293 * The default implementation behaves as 19294 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 19295 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 19296 * the case of no accessibility delegate been set. 19297 * </p> 19298 * 19299 * @param host The View hosting the delegate. 19300 * @param event The event. 19301 * @return True if the event population was completed. 19302 * 19303 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 19304 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 19305 */ 19306 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 19307 return host.dispatchPopulateAccessibilityEventInternal(event); 19308 } 19309 19310 /** 19311 * Gives a chance to the host View to populate the accessibility event with its 19312 * text content. 19313 * <p> 19314 * The default implementation behaves as 19315 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 19316 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 19317 * the case of no accessibility delegate been set. 19318 * </p> 19319 * 19320 * @param host The View hosting the delegate. 19321 * @param event The accessibility event which to populate. 19322 * 19323 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 19324 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 19325 */ 19326 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 19327 host.onPopulateAccessibilityEventInternal(event); 19328 } 19329 19330 /** 19331 * Initializes an {@link AccessibilityEvent} with information about the 19332 * the host View which is the event source. 19333 * <p> 19334 * The default implementation behaves as 19335 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 19336 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 19337 * the case of no accessibility delegate been set. 19338 * </p> 19339 * 19340 * @param host The View hosting the delegate. 19341 * @param event The event to initialize. 19342 * 19343 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 19344 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 19345 */ 19346 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 19347 host.onInitializeAccessibilityEventInternal(event); 19348 } 19349 19350 /** 19351 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 19352 * <p> 19353 * The default implementation behaves as 19354 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 19355 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 19356 * the case of no accessibility delegate been set. 19357 * </p> 19358 * 19359 * @param host The View hosting the delegate. 19360 * @param info The instance to initialize. 19361 * 19362 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 19363 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 19364 */ 19365 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 19366 host.onInitializeAccessibilityNodeInfoInternal(info); 19367 } 19368 19369 /** 19370 * Called when a child of the host View has requested sending an 19371 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 19372 * to augment the event. 19373 * <p> 19374 * The default implementation behaves as 19375 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 19376 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 19377 * the case of no accessibility delegate been set. 19378 * </p> 19379 * 19380 * @param host The View hosting the delegate. 19381 * @param child The child which requests sending the event. 19382 * @param event The event to be sent. 19383 * @return True if the event should be sent 19384 * 19385 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 19386 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 19387 */ 19388 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 19389 AccessibilityEvent event) { 19390 return host.onRequestSendAccessibilityEventInternal(child, event); 19391 } 19392 19393 /** 19394 * Gets the provider for managing a virtual view hierarchy rooted at this View 19395 * and reported to {@link android.accessibilityservice.AccessibilityService}s 19396 * that explore the window content. 19397 * <p> 19398 * The default implementation behaves as 19399 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 19400 * the case of no accessibility delegate been set. 19401 * </p> 19402 * 19403 * @return The provider. 19404 * 19405 * @see AccessibilityNodeProvider 19406 */ 19407 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 19408 return null; 19409 } 19410 19411 /** 19412 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 19413 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 19414 * This method is responsible for obtaining an accessibility node info from a 19415 * pool of reusable instances and calling 19416 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 19417 * view to initialize the former. 19418 * <p> 19419 * <strong>Note:</strong> The client is responsible for recycling the obtained 19420 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 19421 * creation. 19422 * </p> 19423 * <p> 19424 * The default implementation behaves as 19425 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 19426 * the case of no accessibility delegate been set. 19427 * </p> 19428 * @return A populated {@link AccessibilityNodeInfo}. 19429 * 19430 * @see AccessibilityNodeInfo 19431 * 19432 * @hide 19433 */ 19434 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 19435 return host.createAccessibilityNodeInfoInternal(); 19436 } 19437 } 19438 19439 private class MatchIdPredicate implements Predicate<View> { 19440 public int mId; 19441 19442 @Override 19443 public boolean apply(View view) { 19444 return (view.mID == mId); 19445 } 19446 } 19447 19448 private class MatchLabelForPredicate implements Predicate<View> { 19449 private int mLabeledId; 19450 19451 @Override 19452 public boolean apply(View view) { 19453 return (view.mLabelForId == mLabeledId); 19454 } 19455 } 19456 19457 private class SendViewStateChangedAccessibilityEvent implements Runnable { 19458 private int mChangeTypes = 0; 19459 private boolean mPosted; 19460 private boolean mPostedWithDelay; 19461 private long mLastEventTimeMillis; 19462 19463 @Override 19464 public void run() { 19465 mPosted = false; 19466 mPostedWithDelay = false; 19467 mLastEventTimeMillis = SystemClock.uptimeMillis(); 19468 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 19469 final AccessibilityEvent event = AccessibilityEvent.obtain(); 19470 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 19471 event.setContentChangeTypes(mChangeTypes); 19472 sendAccessibilityEventUnchecked(event); 19473 } 19474 mChangeTypes = 0; 19475 } 19476 19477 public void runOrPost(int changeType) { 19478 mChangeTypes |= changeType; 19479 19480 // If this is a live region or the child of a live region, collect 19481 // all events from this frame and send them on the next frame. 19482 if (inLiveRegion()) { 19483 // If we're already posted with a delay, remove that. 19484 if (mPostedWithDelay) { 19485 removeCallbacks(this); 19486 mPostedWithDelay = false; 19487 } 19488 // Only post if we're not already posted. 19489 if (!mPosted) { 19490 post(this); 19491 mPosted = true; 19492 } 19493 return; 19494 } 19495 19496 if (mPosted) { 19497 return; 19498 } 19499 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; 19500 final long minEventIntevalMillis = 19501 ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); 19502 if (timeSinceLastMillis >= minEventIntevalMillis) { 19503 removeCallbacks(this); 19504 run(); 19505 } else { 19506 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); 19507 mPosted = true; 19508 mPostedWithDelay = true; 19509 } 19510 } 19511 } 19512 19513 private boolean inLiveRegion() { 19514 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) { 19515 return true; 19516 } 19517 19518 ViewParent parent = getParent(); 19519 while (parent instanceof View) { 19520 if (((View) parent).getAccessibilityLiveRegion() 19521 != View.ACCESSIBILITY_LIVE_REGION_NONE) { 19522 return true; 19523 } 19524 parent = parent.getParent(); 19525 } 19526 19527 return false; 19528 } 19529 19530 /** 19531 * Dump all private flags in readable format, useful for documentation and 19532 * sanity checking. 19533 */ 19534 private static void dumpFlags() { 19535 final HashMap<String, String> found = Maps.newHashMap(); 19536 try { 19537 for (Field field : View.class.getDeclaredFields()) { 19538 final int modifiers = field.getModifiers(); 19539 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 19540 if (field.getType().equals(int.class)) { 19541 final int value = field.getInt(null); 19542 dumpFlag(found, field.getName(), value); 19543 } else if (field.getType().equals(int[].class)) { 19544 final int[] values = (int[]) field.get(null); 19545 for (int i = 0; i < values.length; i++) { 19546 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 19547 } 19548 } 19549 } 19550 } 19551 } catch (IllegalAccessException e) { 19552 throw new RuntimeException(e); 19553 } 19554 19555 final ArrayList<String> keys = Lists.newArrayList(); 19556 keys.addAll(found.keySet()); 19557 Collections.sort(keys); 19558 for (String key : keys) { 19559 Log.d(VIEW_LOG_TAG, found.get(key)); 19560 } 19561 } 19562 19563 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 19564 // Sort flags by prefix, then by bits, always keeping unique keys 19565 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 19566 final int prefix = name.indexOf('_'); 19567 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 19568 final String output = bits + " " + name; 19569 found.put(key, output); 19570 } 19571 } 19572