View.java revision d1ca75bffef070f62ab70ed514f7f91824f73cbc
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 17package android.view; 18 19import android.animation.RevealAnimator; 20import android.animation.ValueAnimator; 21import android.annotation.IntDef; 22import android.annotation.NonNull; 23import android.annotation.Nullable; 24import android.content.ClipData; 25import android.content.Context; 26import android.content.res.Configuration; 27import android.content.res.Resources; 28import android.content.res.TypedArray; 29import android.graphics.Bitmap; 30import android.graphics.Canvas; 31import android.graphics.Insets; 32import android.graphics.Interpolator; 33import android.graphics.LinearGradient; 34import android.graphics.Matrix; 35import android.graphics.Outline; 36import android.graphics.Paint; 37import android.graphics.PixelFormat; 38import android.graphics.Point; 39import android.graphics.PorterDuff; 40import android.graphics.PorterDuffXfermode; 41import android.graphics.Rect; 42import android.graphics.RectF; 43import android.graphics.Region; 44import android.graphics.Shader; 45import android.graphics.drawable.ColorDrawable; 46import android.graphics.drawable.Drawable; 47import android.hardware.display.DisplayManagerGlobal; 48import android.os.Bundle; 49import android.os.Handler; 50import android.os.IBinder; 51import android.os.Parcel; 52import android.os.Parcelable; 53import android.os.RemoteException; 54import android.os.SystemClock; 55import android.os.SystemProperties; 56import android.text.TextUtils; 57import android.util.AttributeSet; 58import android.util.FloatProperty; 59import android.util.LayoutDirection; 60import android.util.Log; 61import android.util.LongSparseLongArray; 62import android.util.Pools.SynchronizedPool; 63import android.util.Property; 64import android.util.SparseArray; 65import android.util.SuperNotCalledException; 66import android.util.TypedValue; 67import android.view.ContextMenu.ContextMenuInfo; 68import android.view.AccessibilityIterators.TextSegmentIterator; 69import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 70import android.view.AccessibilityIterators.WordTextSegmentIterator; 71import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 72import android.view.accessibility.AccessibilityEvent; 73import android.view.accessibility.AccessibilityEventSource; 74import android.view.accessibility.AccessibilityManager; 75import android.view.accessibility.AccessibilityNodeInfo; 76import android.view.accessibility.AccessibilityNodeProvider; 77import android.view.animation.Animation; 78import android.view.animation.AnimationUtils; 79import android.view.animation.Transformation; 80import android.view.inputmethod.EditorInfo; 81import android.view.inputmethod.InputConnection; 82import android.view.inputmethod.InputMethodManager; 83import android.widget.ScrollBarDrawable; 84 85import static android.os.Build.VERSION_CODES.*; 86import static java.lang.Math.max; 87 88import com.android.internal.R; 89import com.android.internal.util.Predicate; 90import com.android.internal.view.menu.MenuBuilder; 91import com.google.android.collect.Lists; 92import com.google.android.collect.Maps; 93 94import java.lang.annotation.Retention; 95import java.lang.annotation.RetentionPolicy; 96import java.lang.ref.WeakReference; 97import java.lang.reflect.Field; 98import java.lang.reflect.InvocationTargetException; 99import java.lang.reflect.Method; 100import java.lang.reflect.Modifier; 101import java.util.ArrayList; 102import java.util.Arrays; 103import java.util.Collections; 104import java.util.HashMap; 105import java.util.List; 106import java.util.Locale; 107import java.util.Map; 108import java.util.concurrent.CopyOnWriteArrayList; 109import java.util.concurrent.atomic.AtomicInteger; 110 111/** 112 * <p> 113 * This class represents the basic building block for user interface components. A View 114 * occupies a rectangular area on the screen and is responsible for drawing and 115 * event handling. View is the base class for <em>widgets</em>, which are 116 * used to create interactive UI components (buttons, text fields, etc.). The 117 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 118 * are invisible containers that hold other Views (or other ViewGroups) and define 119 * their layout properties. 120 * </p> 121 * 122 * <div class="special reference"> 123 * <h3>Developer Guides</h3> 124 * <p>For information about using this class to develop your application's user interface, 125 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 126 * </div> 127 * 128 * <a name="Using"></a> 129 * <h3>Using Views</h3> 130 * <p> 131 * All of the views in a window are arranged in a single tree. You can add views 132 * either from code or by specifying a tree of views in one or more XML layout 133 * files. There are many specialized subclasses of views that act as controls or 134 * are capable of displaying text, images, or other content. 135 * </p> 136 * <p> 137 * Once you have created a tree of views, there are typically a few types of 138 * common operations you may wish to perform: 139 * <ul> 140 * <li><strong>Set properties:</strong> for example setting the text of a 141 * {@link android.widget.TextView}. The available properties and the methods 142 * that set them will vary among the different subclasses of views. Note that 143 * properties that are known at build time can be set in the XML layout 144 * files.</li> 145 * <li><strong>Set focus:</strong> The framework will handled moving focus in 146 * response to user input. To force focus to a specific view, call 147 * {@link #requestFocus}.</li> 148 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 149 * that will be notified when something interesting happens to the view. For 150 * example, all views will let you set a listener to be notified when the view 151 * gains or loses focus. You can register such a listener using 152 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 153 * Other view subclasses offer more specialized listeners. For example, a Button 154 * exposes a listener to notify clients when the button is clicked.</li> 155 * <li><strong>Set visibility:</strong> You can hide or show views using 156 * {@link #setVisibility(int)}.</li> 157 * </ul> 158 * </p> 159 * <p><em> 160 * Note: The Android framework is responsible for measuring, laying out and 161 * drawing views. You should not call methods that perform these actions on 162 * views yourself unless you are actually implementing a 163 * {@link android.view.ViewGroup}. 164 * </em></p> 165 * 166 * <a name="Lifecycle"></a> 167 * <h3>Implementing a Custom View</h3> 168 * 169 * <p> 170 * To implement a custom view, you will usually begin by providing overrides for 171 * some of the standard methods that the framework calls on all views. You do 172 * not need to override all of these methods. In fact, you can start by just 173 * overriding {@link #onDraw(android.graphics.Canvas)}. 174 * <table border="2" width="85%" align="center" cellpadding="5"> 175 * <thead> 176 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 177 * </thead> 178 * 179 * <tbody> 180 * <tr> 181 * <td rowspan="2">Creation</td> 182 * <td>Constructors</td> 183 * <td>There is a form of the constructor that are called when the view 184 * is created from code and a form that is called when the view is 185 * inflated from a layout file. The second form should parse and apply 186 * any attributes defined in the layout file. 187 * </td> 188 * </tr> 189 * <tr> 190 * <td><code>{@link #onFinishInflate()}</code></td> 191 * <td>Called after a view and all of its children has been inflated 192 * from XML.</td> 193 * </tr> 194 * 195 * <tr> 196 * <td rowspan="3">Layout</td> 197 * <td><code>{@link #onMeasure(int, int)}</code></td> 198 * <td>Called to determine the size requirements for this view and all 199 * of its children. 200 * </td> 201 * </tr> 202 * <tr> 203 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 204 * <td>Called when this view should assign a size and position to all 205 * of its children. 206 * </td> 207 * </tr> 208 * <tr> 209 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 210 * <td>Called when the size of this view has changed. 211 * </td> 212 * </tr> 213 * 214 * <tr> 215 * <td>Drawing</td> 216 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 217 * <td>Called when the view should render its content. 218 * </td> 219 * </tr> 220 * 221 * <tr> 222 * <td rowspan="4">Event processing</td> 223 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 224 * <td>Called when a new hardware key event occurs. 225 * </td> 226 * </tr> 227 * <tr> 228 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 229 * <td>Called when a hardware key up event occurs. 230 * </td> 231 * </tr> 232 * <tr> 233 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 234 * <td>Called when a trackball motion event occurs. 235 * </td> 236 * </tr> 237 * <tr> 238 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 239 * <td>Called when a touch screen motion event occurs. 240 * </td> 241 * </tr> 242 * 243 * <tr> 244 * <td rowspan="2">Focus</td> 245 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 246 * <td>Called when the view gains or loses focus. 247 * </td> 248 * </tr> 249 * 250 * <tr> 251 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 252 * <td>Called when the window containing the view gains or loses focus. 253 * </td> 254 * </tr> 255 * 256 * <tr> 257 * <td rowspan="3">Attaching</td> 258 * <td><code>{@link #onAttachedToWindow()}</code></td> 259 * <td>Called when the view is attached to a window. 260 * </td> 261 * </tr> 262 * 263 * <tr> 264 * <td><code>{@link #onDetachedFromWindow}</code></td> 265 * <td>Called when the view is detached from its window. 266 * </td> 267 * </tr> 268 * 269 * <tr> 270 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 271 * <td>Called when the visibility of the window containing the view 272 * has changed. 273 * </td> 274 * </tr> 275 * </tbody> 276 * 277 * </table> 278 * </p> 279 * 280 * <a name="IDs"></a> 281 * <h3>IDs</h3> 282 * Views may have an integer id associated with them. These ids are typically 283 * assigned in the layout XML files, and are used to find specific views within 284 * the view tree. A common pattern is to: 285 * <ul> 286 * <li>Define a Button in the layout file and assign it a unique ID. 287 * <pre> 288 * <Button 289 * android:id="@+id/my_button" 290 * android:layout_width="wrap_content" 291 * android:layout_height="wrap_content" 292 * android:text="@string/my_button_text"/> 293 * </pre></li> 294 * <li>From the onCreate method of an Activity, find the Button 295 * <pre class="prettyprint"> 296 * Button myButton = (Button) findViewById(R.id.my_button); 297 * </pre></li> 298 * </ul> 299 * <p> 300 * View IDs need not be unique throughout the tree, but it is good practice to 301 * ensure that they are at least unique within the part of the tree you are 302 * searching. 303 * </p> 304 * 305 * <a name="Position"></a> 306 * <h3>Position</h3> 307 * <p> 308 * The geometry of a view is that of a rectangle. A view has a location, 309 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 310 * two dimensions, expressed as a width and a height. The unit for location 311 * and dimensions is the pixel. 312 * </p> 313 * 314 * <p> 315 * It is possible to retrieve the location of a view by invoking the methods 316 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 317 * coordinate of the rectangle representing the view. The latter returns the 318 * top, or Y, coordinate of the rectangle representing the view. These methods 319 * both return the location of the view relative to its parent. For instance, 320 * when getLeft() returns 20, that means the view is located 20 pixels to the 321 * right of the left edge of its direct parent. 322 * </p> 323 * 324 * <p> 325 * In addition, several convenience methods are offered to avoid unnecessary 326 * computations, namely {@link #getRight()} and {@link #getBottom()}. 327 * These methods return the coordinates of the right and bottom edges of the 328 * rectangle representing the view. For instance, calling {@link #getRight()} 329 * is similar to the following computation: <code>getLeft() + getWidth()</code> 330 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 331 * </p> 332 * 333 * <a name="SizePaddingMargins"></a> 334 * <h3>Size, padding and margins</h3> 335 * <p> 336 * The size of a view is expressed with a width and a height. A view actually 337 * possess two pairs of width and height values. 338 * </p> 339 * 340 * <p> 341 * The first pair is known as <em>measured width</em> and 342 * <em>measured height</em>. These dimensions define how big a view wants to be 343 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 344 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 345 * and {@link #getMeasuredHeight()}. 346 * </p> 347 * 348 * <p> 349 * The second pair is simply known as <em>width</em> and <em>height</em>, or 350 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 351 * dimensions define the actual size of the view on screen, at drawing time and 352 * after layout. These values may, but do not have to, be different from the 353 * measured width and height. The width and height can be obtained by calling 354 * {@link #getWidth()} and {@link #getHeight()}. 355 * </p> 356 * 357 * <p> 358 * To measure its dimensions, a view takes into account its padding. The padding 359 * is expressed in pixels for the left, top, right and bottom parts of the view. 360 * Padding can be used to offset the content of the view by a specific amount of 361 * pixels. For instance, a left padding of 2 will push the view's content by 362 * 2 pixels to the right of the left edge. Padding can be set using the 363 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 364 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 365 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 366 * {@link #getPaddingEnd()}. 367 * </p> 368 * 369 * <p> 370 * Even though a view can define a padding, it does not provide any support for 371 * margins. However, view groups provide such a support. Refer to 372 * {@link android.view.ViewGroup} and 373 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 374 * </p> 375 * 376 * <a name="Layout"></a> 377 * <h3>Layout</h3> 378 * <p> 379 * Layout is a two pass process: a measure pass and a layout pass. The measuring 380 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 381 * of the view tree. Each view pushes dimension specifications down the tree 382 * during the recursion. At the end of the measure pass, every view has stored 383 * its measurements. The second pass happens in 384 * {@link #layout(int,int,int,int)} and is also top-down. During 385 * this pass each parent is responsible for positioning all of its children 386 * using the sizes computed in the measure pass. 387 * </p> 388 * 389 * <p> 390 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 391 * {@link #getMeasuredHeight()} values must be set, along with those for all of 392 * that view's descendants. A view's measured width and measured height values 393 * must respect the constraints imposed by the view's parents. This guarantees 394 * that at the end of the measure pass, all parents accept all of their 395 * children's measurements. A parent view may call measure() more than once on 396 * its children. For example, the parent may measure each child once with 397 * unspecified dimensions to find out how big they want to be, then call 398 * measure() on them again with actual numbers if the sum of all the children's 399 * unconstrained sizes is too big or too small. 400 * </p> 401 * 402 * <p> 403 * The measure pass uses two classes to communicate dimensions. The 404 * {@link MeasureSpec} class is used by views to tell their parents how they 405 * want to be measured and positioned. The base LayoutParams class just 406 * describes how big the view wants to be for both width and height. For each 407 * dimension, it can specify one of: 408 * <ul> 409 * <li> an exact number 410 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 411 * (minus padding) 412 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 413 * enclose its content (plus padding). 414 * </ul> 415 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 416 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 417 * an X and Y value. 418 * </p> 419 * 420 * <p> 421 * MeasureSpecs are used to push requirements down the tree from parent to 422 * child. A MeasureSpec can be in one of three modes: 423 * <ul> 424 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 425 * of a child view. For example, a LinearLayout may call measure() on its child 426 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 427 * tall the child view wants to be given a width of 240 pixels. 428 * <li>EXACTLY: This is used by the parent to impose an exact size on the 429 * child. The child must use this size, and guarantee that all of its 430 * descendants will fit within this size. 431 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 432 * child. The child must gurantee that it and all of its descendants will fit 433 * within this size. 434 * </ul> 435 * </p> 436 * 437 * <p> 438 * To intiate a layout, call {@link #requestLayout}. This method is typically 439 * called by a view on itself when it believes that is can no longer fit within 440 * its current bounds. 441 * </p> 442 * 443 * <a name="Drawing"></a> 444 * <h3>Drawing</h3> 445 * <p> 446 * Drawing is handled by walking the tree and rendering each view that 447 * intersects the invalid region. Because the tree is traversed in-order, 448 * this means that parents will draw before (i.e., behind) their children, with 449 * siblings drawn in the order they appear in the tree. 450 * If you set a background drawable for a View, then the View will draw it for you 451 * before calling back to its <code>onDraw()</code> method. 452 * </p> 453 * 454 * <p> 455 * Note that the framework will not draw views that are not in the invalid region. 456 * </p> 457 * 458 * <p> 459 * To force a view to draw, call {@link #invalidate()}. 460 * </p> 461 * 462 * <a name="EventHandlingThreading"></a> 463 * <h3>Event Handling and Threading</h3> 464 * <p> 465 * The basic cycle of a view is as follows: 466 * <ol> 467 * <li>An event comes in and is dispatched to the appropriate view. The view 468 * handles the event and notifies any listeners.</li> 469 * <li>If in the course of processing the event, the view's bounds may need 470 * to be changed, the view will call {@link #requestLayout()}.</li> 471 * <li>Similarly, if in the course of processing the event the view's appearance 472 * may need to be changed, the view will call {@link #invalidate()}.</li> 473 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 474 * the framework will take care of measuring, laying out, and drawing the tree 475 * as appropriate.</li> 476 * </ol> 477 * </p> 478 * 479 * <p><em>Note: The entire view tree is single threaded. You must always be on 480 * the UI thread when calling any method on any view.</em> 481 * If you are doing work on other threads and want to update the state of a view 482 * from that thread, you should use a {@link Handler}. 483 * </p> 484 * 485 * <a name="FocusHandling"></a> 486 * <h3>Focus Handling</h3> 487 * <p> 488 * The framework will handle routine focus movement in response to user input. 489 * This includes changing the focus as views are removed or hidden, or as new 490 * views become available. Views indicate their willingness to take focus 491 * through the {@link #isFocusable} method. To change whether a view can take 492 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 493 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 494 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 495 * </p> 496 * <p> 497 * Focus movement is based on an algorithm which finds the nearest neighbor in a 498 * given direction. In rare cases, the default algorithm may not match the 499 * intended behavior of the developer. In these situations, you can provide 500 * explicit overrides by using these XML attributes in the layout file: 501 * <pre> 502 * nextFocusDown 503 * nextFocusLeft 504 * nextFocusRight 505 * nextFocusUp 506 * </pre> 507 * </p> 508 * 509 * 510 * <p> 511 * To get a particular view to take focus, call {@link #requestFocus()}. 512 * </p> 513 * 514 * <a name="TouchMode"></a> 515 * <h3>Touch Mode</h3> 516 * <p> 517 * When a user is navigating a user interface via directional keys such as a D-pad, it is 518 * necessary to give focus to actionable items such as buttons so the user can see 519 * what will take input. If the device has touch capabilities, however, and the user 520 * begins interacting with the interface by touching it, it is no longer necessary to 521 * always highlight, or give focus to, a particular view. This motivates a mode 522 * for interaction named 'touch mode'. 523 * </p> 524 * <p> 525 * For a touch capable device, once the user touches the screen, the device 526 * will enter touch mode. From this point onward, only views for which 527 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 528 * Other views that are touchable, like buttons, will not take focus when touched; they will 529 * only fire the on click listeners. 530 * </p> 531 * <p> 532 * Any time a user hits a directional key, such as a D-pad direction, the view device will 533 * exit touch mode, and find a view to take focus, so that the user may resume interacting 534 * with the user interface without touching the screen again. 535 * </p> 536 * <p> 537 * The touch mode state is maintained across {@link android.app.Activity}s. Call 538 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 539 * </p> 540 * 541 * <a name="Scrolling"></a> 542 * <h3>Scrolling</h3> 543 * <p> 544 * The framework provides basic support for views that wish to internally 545 * scroll their content. This includes keeping track of the X and Y scroll 546 * offset as well as mechanisms for drawing scrollbars. See 547 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 548 * {@link #awakenScrollBars()} for more details. 549 * </p> 550 * 551 * <a name="Tags"></a> 552 * <h3>Tags</h3> 553 * <p> 554 * Unlike IDs, tags are not used to identify views. Tags are essentially an 555 * extra piece of information that can be associated with a view. They are most 556 * often used as a convenience to store data related to views in the views 557 * themselves rather than by putting them in a separate structure. 558 * </p> 559 * 560 * <a name="Properties"></a> 561 * <h3>Properties</h3> 562 * <p> 563 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 564 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 565 * available both in the {@link Property} form as well as in similarly-named setter/getter 566 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 567 * be used to set persistent state associated with these rendering-related properties on the view. 568 * The properties and methods can also be used in conjunction with 569 * {@link android.animation.Animator Animator}-based animations, described more in the 570 * <a href="#Animation">Animation</a> section. 571 * </p> 572 * 573 * <a name="Animation"></a> 574 * <h3>Animation</h3> 575 * <p> 576 * Starting with Android 3.0, the preferred way of animating views is to use the 577 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 578 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 579 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 580 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 581 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 582 * makes animating these View properties particularly easy and efficient. 583 * </p> 584 * <p> 585 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 586 * You can attach an {@link Animation} object to a view using 587 * {@link #setAnimation(Animation)} or 588 * {@link #startAnimation(Animation)}. The animation can alter the scale, 589 * rotation, translation and alpha of a view over time. If the animation is 590 * attached to a view that has children, the animation will affect the entire 591 * subtree rooted by that node. When an animation is started, the framework will 592 * take care of redrawing the appropriate views until the animation completes. 593 * </p> 594 * 595 * <a name="Security"></a> 596 * <h3>Security</h3> 597 * <p> 598 * Sometimes it is essential that an application be able to verify that an action 599 * is being performed with the full knowledge and consent of the user, such as 600 * granting a permission request, making a purchase or clicking on an advertisement. 601 * Unfortunately, a malicious application could try to spoof the user into 602 * performing these actions, unaware, by concealing the intended purpose of the view. 603 * As a remedy, the framework offers a touch filtering mechanism that can be used to 604 * improve the security of views that provide access to sensitive functionality. 605 * </p><p> 606 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 607 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 608 * will discard touches that are received whenever the view's window is obscured by 609 * another visible window. As a result, the view will not receive touches whenever a 610 * toast, dialog or other window appears above the view's window. 611 * </p><p> 612 * For more fine-grained control over security, consider overriding the 613 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 614 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 615 * </p> 616 * 617 * @attr ref android.R.styleable#View_alpha 618 * @attr ref android.R.styleable#View_background 619 * @attr ref android.R.styleable#View_clickable 620 * @attr ref android.R.styleable#View_contentDescription 621 * @attr ref android.R.styleable#View_drawingCacheQuality 622 * @attr ref android.R.styleable#View_duplicateParentState 623 * @attr ref android.R.styleable#View_id 624 * @attr ref android.R.styleable#View_requiresFadingEdge 625 * @attr ref android.R.styleable#View_fadeScrollbars 626 * @attr ref android.R.styleable#View_fadingEdgeLength 627 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 628 * @attr ref android.R.styleable#View_fitsSystemWindows 629 * @attr ref android.R.styleable#View_isScrollContainer 630 * @attr ref android.R.styleable#View_focusable 631 * @attr ref android.R.styleable#View_focusableInTouchMode 632 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 633 * @attr ref android.R.styleable#View_keepScreenOn 634 * @attr ref android.R.styleable#View_layerType 635 * @attr ref android.R.styleable#View_layoutDirection 636 * @attr ref android.R.styleable#View_longClickable 637 * @attr ref android.R.styleable#View_minHeight 638 * @attr ref android.R.styleable#View_minWidth 639 * @attr ref android.R.styleable#View_nextFocusDown 640 * @attr ref android.R.styleable#View_nextFocusLeft 641 * @attr ref android.R.styleable#View_nextFocusRight 642 * @attr ref android.R.styleable#View_nextFocusUp 643 * @attr ref android.R.styleable#View_onClick 644 * @attr ref android.R.styleable#View_padding 645 * @attr ref android.R.styleable#View_paddingBottom 646 * @attr ref android.R.styleable#View_paddingLeft 647 * @attr ref android.R.styleable#View_paddingRight 648 * @attr ref android.R.styleable#View_paddingTop 649 * @attr ref android.R.styleable#View_paddingStart 650 * @attr ref android.R.styleable#View_paddingEnd 651 * @attr ref android.R.styleable#View_saveEnabled 652 * @attr ref android.R.styleable#View_rotation 653 * @attr ref android.R.styleable#View_rotationX 654 * @attr ref android.R.styleable#View_rotationY 655 * @attr ref android.R.styleable#View_scaleX 656 * @attr ref android.R.styleable#View_scaleY 657 * @attr ref android.R.styleable#View_scrollX 658 * @attr ref android.R.styleable#View_scrollY 659 * @attr ref android.R.styleable#View_scrollbarSize 660 * @attr ref android.R.styleable#View_scrollbarStyle 661 * @attr ref android.R.styleable#View_scrollbars 662 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 663 * @attr ref android.R.styleable#View_scrollbarFadeDuration 664 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 665 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 666 * @attr ref android.R.styleable#View_scrollbarThumbVertical 667 * @attr ref android.R.styleable#View_scrollbarTrackVertical 668 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 669 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 670 * @attr ref android.R.styleable#View_sharedElementName 671 * @attr ref android.R.styleable#View_soundEffectsEnabled 672 * @attr ref android.R.styleable#View_tag 673 * @attr ref android.R.styleable#View_textAlignment 674 * @attr ref android.R.styleable#View_textDirection 675 * @attr ref android.R.styleable#View_transformPivotX 676 * @attr ref android.R.styleable#View_transformPivotY 677 * @attr ref android.R.styleable#View_translationX 678 * @attr ref android.R.styleable#View_translationY 679 * @attr ref android.R.styleable#View_translationZ 680 * @attr ref android.R.styleable#View_visibility 681 * 682 * @see android.view.ViewGroup 683 */ 684public class View implements Drawable.Callback, KeyEvent.Callback, 685 AccessibilityEventSource { 686 private static final boolean DBG = false; 687 688 /** 689 * The logging tag used by this class with android.util.Log. 690 */ 691 protected static final String VIEW_LOG_TAG = "View"; 692 693 /** 694 * When set to true, apps will draw debugging information about their layouts. 695 * 696 * @hide 697 */ 698 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 699 700 /** 701 * Used to mark a View that has no ID. 702 */ 703 public static final int NO_ID = -1; 704 705 /** 706 * Signals that compatibility booleans have been initialized according to 707 * target SDK versions. 708 */ 709 private static boolean sCompatibilityDone = false; 710 711 /** 712 * Use the old (broken) way of building MeasureSpecs. 713 */ 714 private static boolean sUseBrokenMakeMeasureSpec = false; 715 716 /** 717 * Ignore any optimizations using the measure cache. 718 */ 719 private static boolean sIgnoreMeasureCache = false; 720 721 /** 722 * Ignore the clipBounds of this view for the children. 723 */ 724 static boolean sIgnoreClipBoundsForChildren = false; 725 726 /** 727 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 728 * calling setFlags. 729 */ 730 private static final int NOT_FOCUSABLE = 0x00000000; 731 732 /** 733 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 734 * setFlags. 735 */ 736 private static final int FOCUSABLE = 0x00000001; 737 738 /** 739 * Mask for use with setFlags indicating bits used for focus. 740 */ 741 private static final int FOCUSABLE_MASK = 0x00000001; 742 743 /** 744 * This view will adjust its padding to fit sytem windows (e.g. status bar) 745 */ 746 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 747 748 /** @hide */ 749 @IntDef({VISIBLE, INVISIBLE, GONE}) 750 @Retention(RetentionPolicy.SOURCE) 751 public @interface Visibility {} 752 753 /** 754 * This view is visible. 755 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 756 * android:visibility}. 757 */ 758 public static final int VISIBLE = 0x00000000; 759 760 /** 761 * This view is invisible, but it still takes up space for layout purposes. 762 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 763 * android:visibility}. 764 */ 765 public static final int INVISIBLE = 0x00000004; 766 767 /** 768 * This view is invisible, and it doesn't take any space for layout 769 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 770 * android:visibility}. 771 */ 772 public static final int GONE = 0x00000008; 773 774 /** 775 * Mask for use with setFlags indicating bits used for visibility. 776 * {@hide} 777 */ 778 static final int VISIBILITY_MASK = 0x0000000C; 779 780 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 781 782 /** 783 * This view is enabled. Interpretation varies by subclass. 784 * Use with ENABLED_MASK when calling setFlags. 785 * {@hide} 786 */ 787 static final int ENABLED = 0x00000000; 788 789 /** 790 * This view is disabled. Interpretation varies by subclass. 791 * Use with ENABLED_MASK when calling setFlags. 792 * {@hide} 793 */ 794 static final int DISABLED = 0x00000020; 795 796 /** 797 * Mask for use with setFlags indicating bits used for indicating whether 798 * this view is enabled 799 * {@hide} 800 */ 801 static final int ENABLED_MASK = 0x00000020; 802 803 /** 804 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 805 * called and further optimizations will be performed. It is okay to have 806 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 807 * {@hide} 808 */ 809 static final int WILL_NOT_DRAW = 0x00000080; 810 811 /** 812 * Mask for use with setFlags indicating bits used for indicating whether 813 * this view is will draw 814 * {@hide} 815 */ 816 static final int DRAW_MASK = 0x00000080; 817 818 /** 819 * <p>This view doesn't show scrollbars.</p> 820 * {@hide} 821 */ 822 static final int SCROLLBARS_NONE = 0x00000000; 823 824 /** 825 * <p>This view shows horizontal scrollbars.</p> 826 * {@hide} 827 */ 828 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 829 830 /** 831 * <p>This view shows vertical scrollbars.</p> 832 * {@hide} 833 */ 834 static final int SCROLLBARS_VERTICAL = 0x00000200; 835 836 /** 837 * <p>Mask for use with setFlags indicating bits used for indicating which 838 * scrollbars are enabled.</p> 839 * {@hide} 840 */ 841 static final int SCROLLBARS_MASK = 0x00000300; 842 843 /** 844 * Indicates that the view should filter touches when its window is obscured. 845 * Refer to the class comments for more information about this security feature. 846 * {@hide} 847 */ 848 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 849 850 /** 851 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 852 * that they are optional and should be skipped if the window has 853 * requested system UI flags that ignore those insets for layout. 854 */ 855 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 856 857 /** 858 * <p>This view doesn't show fading edges.</p> 859 * {@hide} 860 */ 861 static final int FADING_EDGE_NONE = 0x00000000; 862 863 /** 864 * <p>This view shows horizontal fading edges.</p> 865 * {@hide} 866 */ 867 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 868 869 /** 870 * <p>This view shows vertical fading edges.</p> 871 * {@hide} 872 */ 873 static final int FADING_EDGE_VERTICAL = 0x00002000; 874 875 /** 876 * <p>Mask for use with setFlags indicating bits used for indicating which 877 * fading edges are enabled.</p> 878 * {@hide} 879 */ 880 static final int FADING_EDGE_MASK = 0x00003000; 881 882 /** 883 * <p>Indicates this view can be clicked. When clickable, a View reacts 884 * to clicks by notifying the OnClickListener.<p> 885 * {@hide} 886 */ 887 static final int CLICKABLE = 0x00004000; 888 889 /** 890 * <p>Indicates this view is caching its drawing into a bitmap.</p> 891 * {@hide} 892 */ 893 static final int DRAWING_CACHE_ENABLED = 0x00008000; 894 895 /** 896 * <p>Indicates that no icicle should be saved for this view.<p> 897 * {@hide} 898 */ 899 static final int SAVE_DISABLED = 0x000010000; 900 901 /** 902 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 903 * property.</p> 904 * {@hide} 905 */ 906 static final int SAVE_DISABLED_MASK = 0x000010000; 907 908 /** 909 * <p>Indicates that no drawing cache should ever be created for this view.<p> 910 * {@hide} 911 */ 912 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 913 914 /** 915 * <p>Indicates this view can take / keep focus when int touch mode.</p> 916 * {@hide} 917 */ 918 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 919 920 /** @hide */ 921 @Retention(RetentionPolicy.SOURCE) 922 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO}) 923 public @interface DrawingCacheQuality {} 924 925 /** 926 * <p>Enables low quality mode for the drawing cache.</p> 927 */ 928 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 929 930 /** 931 * <p>Enables high quality mode for the drawing cache.</p> 932 */ 933 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 934 935 /** 936 * <p>Enables automatic quality mode for the drawing cache.</p> 937 */ 938 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 939 940 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 941 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 942 }; 943 944 /** 945 * <p>Mask for use with setFlags indicating bits used for the cache 946 * quality property.</p> 947 * {@hide} 948 */ 949 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 950 951 /** 952 * <p> 953 * Indicates this view can be long clicked. When long clickable, a View 954 * reacts to long clicks by notifying the OnLongClickListener or showing a 955 * context menu. 956 * </p> 957 * {@hide} 958 */ 959 static final int LONG_CLICKABLE = 0x00200000; 960 961 /** 962 * <p>Indicates that this view gets its drawable states from its direct parent 963 * and ignores its original internal states.</p> 964 * 965 * @hide 966 */ 967 static final int DUPLICATE_PARENT_STATE = 0x00400000; 968 969 /** @hide */ 970 @IntDef({ 971 SCROLLBARS_INSIDE_OVERLAY, 972 SCROLLBARS_INSIDE_INSET, 973 SCROLLBARS_OUTSIDE_OVERLAY, 974 SCROLLBARS_OUTSIDE_INSET 975 }) 976 @Retention(RetentionPolicy.SOURCE) 977 public @interface ScrollBarStyle {} 978 979 /** 980 * The scrollbar style to display the scrollbars inside the content area, 981 * without increasing the padding. The scrollbars will be overlaid with 982 * translucency on the view's content. 983 */ 984 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 985 986 /** 987 * The scrollbar style to display the scrollbars inside the padded area, 988 * increasing the padding of the view. The scrollbars will not overlap the 989 * content area of the view. 990 */ 991 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 992 993 /** 994 * The scrollbar style to display the scrollbars at the edge of the view, 995 * without increasing the padding. The scrollbars will be overlaid with 996 * translucency. 997 */ 998 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 999 1000 /** 1001 * The scrollbar style to display the scrollbars at the edge of the view, 1002 * increasing the padding of the view. The scrollbars will only overlap the 1003 * background, if any. 1004 */ 1005 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 1006 1007 /** 1008 * Mask to check if the scrollbar style is overlay or inset. 1009 * {@hide} 1010 */ 1011 static final int SCROLLBARS_INSET_MASK = 0x01000000; 1012 1013 /** 1014 * Mask to check if the scrollbar style is inside or outside. 1015 * {@hide} 1016 */ 1017 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 1018 1019 /** 1020 * Mask for scrollbar style. 1021 * {@hide} 1022 */ 1023 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 1024 1025 /** 1026 * View flag indicating that the screen should remain on while the 1027 * window containing this view is visible to the user. This effectively 1028 * takes care of automatically setting the WindowManager's 1029 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 1030 */ 1031 public static final int KEEP_SCREEN_ON = 0x04000000; 1032 1033 /** 1034 * View flag indicating whether this view should have sound effects enabled 1035 * for events such as clicking and touching. 1036 */ 1037 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1038 1039 /** 1040 * View flag indicating whether this view should have haptic feedback 1041 * enabled for events such as long presses. 1042 */ 1043 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1044 1045 /** 1046 * <p>Indicates that the view hierarchy should stop saving state when 1047 * it reaches this view. If state saving is initiated immediately at 1048 * the view, it will be allowed. 1049 * {@hide} 1050 */ 1051 static final int PARENT_SAVE_DISABLED = 0x20000000; 1052 1053 /** 1054 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1055 * {@hide} 1056 */ 1057 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1058 1059 /** @hide */ 1060 @IntDef(flag = true, 1061 value = { 1062 FOCUSABLES_ALL, 1063 FOCUSABLES_TOUCH_MODE 1064 }) 1065 @Retention(RetentionPolicy.SOURCE) 1066 public @interface FocusableMode {} 1067 1068 /** 1069 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1070 * should add all focusable Views regardless if they are focusable in touch mode. 1071 */ 1072 public static final int FOCUSABLES_ALL = 0x00000000; 1073 1074 /** 1075 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1076 * should add only Views focusable in touch mode. 1077 */ 1078 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1079 1080 /** @hide */ 1081 @IntDef({ 1082 FOCUS_BACKWARD, 1083 FOCUS_FORWARD, 1084 FOCUS_LEFT, 1085 FOCUS_UP, 1086 FOCUS_RIGHT, 1087 FOCUS_DOWN 1088 }) 1089 @Retention(RetentionPolicy.SOURCE) 1090 public @interface FocusDirection {} 1091 1092 /** @hide */ 1093 @IntDef({ 1094 FOCUS_LEFT, 1095 FOCUS_UP, 1096 FOCUS_RIGHT, 1097 FOCUS_DOWN 1098 }) 1099 @Retention(RetentionPolicy.SOURCE) 1100 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward 1101 1102 /** 1103 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1104 * item. 1105 */ 1106 public static final int FOCUS_BACKWARD = 0x00000001; 1107 1108 /** 1109 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1110 * item. 1111 */ 1112 public static final int FOCUS_FORWARD = 0x00000002; 1113 1114 /** 1115 * Use with {@link #focusSearch(int)}. Move focus to the left. 1116 */ 1117 public static final int FOCUS_LEFT = 0x00000011; 1118 1119 /** 1120 * Use with {@link #focusSearch(int)}. Move focus up. 1121 */ 1122 public static final int FOCUS_UP = 0x00000021; 1123 1124 /** 1125 * Use with {@link #focusSearch(int)}. Move focus to the right. 1126 */ 1127 public static final int FOCUS_RIGHT = 0x00000042; 1128 1129 /** 1130 * Use with {@link #focusSearch(int)}. Move focus down. 1131 */ 1132 public static final int FOCUS_DOWN = 0x00000082; 1133 1134 /** 1135 * Bits of {@link #getMeasuredWidthAndState()} and 1136 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1137 */ 1138 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1139 1140 /** 1141 * Bits of {@link #getMeasuredWidthAndState()} and 1142 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1143 */ 1144 public static final int MEASURED_STATE_MASK = 0xff000000; 1145 1146 /** 1147 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1148 * for functions that combine both width and height into a single int, 1149 * such as {@link #getMeasuredState()} and the childState argument of 1150 * {@link #resolveSizeAndState(int, int, int)}. 1151 */ 1152 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1153 1154 /** 1155 * Bit of {@link #getMeasuredWidthAndState()} and 1156 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1157 * is smaller that the space the view would like to have. 1158 */ 1159 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1160 1161 /** 1162 * Base View state sets 1163 */ 1164 // Singles 1165 /** 1166 * Indicates the view has no states set. States are used with 1167 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1168 * view depending on its state. 1169 * 1170 * @see android.graphics.drawable.Drawable 1171 * @see #getDrawableState() 1172 */ 1173 protected static final int[] EMPTY_STATE_SET; 1174 /** 1175 * Indicates the view is enabled. States are used with 1176 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1177 * view depending on its state. 1178 * 1179 * @see android.graphics.drawable.Drawable 1180 * @see #getDrawableState() 1181 */ 1182 protected static final int[] ENABLED_STATE_SET; 1183 /** 1184 * Indicates the view is focused. States are used with 1185 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1186 * view depending on its state. 1187 * 1188 * @see android.graphics.drawable.Drawable 1189 * @see #getDrawableState() 1190 */ 1191 protected static final int[] FOCUSED_STATE_SET; 1192 /** 1193 * Indicates the view is selected. States are used with 1194 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1195 * view depending on its state. 1196 * 1197 * @see android.graphics.drawable.Drawable 1198 * @see #getDrawableState() 1199 */ 1200 protected static final int[] SELECTED_STATE_SET; 1201 /** 1202 * Indicates the view is pressed. States are used with 1203 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1204 * view depending on its state. 1205 * 1206 * @see android.graphics.drawable.Drawable 1207 * @see #getDrawableState() 1208 */ 1209 protected static final int[] PRESSED_STATE_SET; 1210 /** 1211 * Indicates the view's window has focus. States are used with 1212 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1213 * view depending on its state. 1214 * 1215 * @see android.graphics.drawable.Drawable 1216 * @see #getDrawableState() 1217 */ 1218 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1219 // Doubles 1220 /** 1221 * Indicates the view is enabled and has the focus. 1222 * 1223 * @see #ENABLED_STATE_SET 1224 * @see #FOCUSED_STATE_SET 1225 */ 1226 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1227 /** 1228 * Indicates the view is enabled and selected. 1229 * 1230 * @see #ENABLED_STATE_SET 1231 * @see #SELECTED_STATE_SET 1232 */ 1233 protected static final int[] ENABLED_SELECTED_STATE_SET; 1234 /** 1235 * Indicates the view is enabled and that its window has focus. 1236 * 1237 * @see #ENABLED_STATE_SET 1238 * @see #WINDOW_FOCUSED_STATE_SET 1239 */ 1240 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1241 /** 1242 * Indicates the view is focused and selected. 1243 * 1244 * @see #FOCUSED_STATE_SET 1245 * @see #SELECTED_STATE_SET 1246 */ 1247 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1248 /** 1249 * Indicates the view has the focus and that its window has the focus. 1250 * 1251 * @see #FOCUSED_STATE_SET 1252 * @see #WINDOW_FOCUSED_STATE_SET 1253 */ 1254 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1255 /** 1256 * Indicates the view is selected and that its window has the focus. 1257 * 1258 * @see #SELECTED_STATE_SET 1259 * @see #WINDOW_FOCUSED_STATE_SET 1260 */ 1261 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1262 // Triples 1263 /** 1264 * Indicates the view is enabled, focused and selected. 1265 * 1266 * @see #ENABLED_STATE_SET 1267 * @see #FOCUSED_STATE_SET 1268 * @see #SELECTED_STATE_SET 1269 */ 1270 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1271 /** 1272 * Indicates the view is enabled, focused and its window has the focus. 1273 * 1274 * @see #ENABLED_STATE_SET 1275 * @see #FOCUSED_STATE_SET 1276 * @see #WINDOW_FOCUSED_STATE_SET 1277 */ 1278 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1279 /** 1280 * Indicates the view is enabled, selected and its window has the focus. 1281 * 1282 * @see #ENABLED_STATE_SET 1283 * @see #SELECTED_STATE_SET 1284 * @see #WINDOW_FOCUSED_STATE_SET 1285 */ 1286 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1287 /** 1288 * Indicates the view is focused, selected and its window has the focus. 1289 * 1290 * @see #FOCUSED_STATE_SET 1291 * @see #SELECTED_STATE_SET 1292 * @see #WINDOW_FOCUSED_STATE_SET 1293 */ 1294 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1295 /** 1296 * Indicates the view is enabled, focused, selected and its window 1297 * has the focus. 1298 * 1299 * @see #ENABLED_STATE_SET 1300 * @see #FOCUSED_STATE_SET 1301 * @see #SELECTED_STATE_SET 1302 * @see #WINDOW_FOCUSED_STATE_SET 1303 */ 1304 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1305 /** 1306 * Indicates the view is pressed and its window has the focus. 1307 * 1308 * @see #PRESSED_STATE_SET 1309 * @see #WINDOW_FOCUSED_STATE_SET 1310 */ 1311 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1312 /** 1313 * Indicates the view is pressed and selected. 1314 * 1315 * @see #PRESSED_STATE_SET 1316 * @see #SELECTED_STATE_SET 1317 */ 1318 protected static final int[] PRESSED_SELECTED_STATE_SET; 1319 /** 1320 * Indicates the view is pressed, selected and its window has the focus. 1321 * 1322 * @see #PRESSED_STATE_SET 1323 * @see #SELECTED_STATE_SET 1324 * @see #WINDOW_FOCUSED_STATE_SET 1325 */ 1326 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1327 /** 1328 * Indicates the view is pressed and focused. 1329 * 1330 * @see #PRESSED_STATE_SET 1331 * @see #FOCUSED_STATE_SET 1332 */ 1333 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1334 /** 1335 * Indicates the view is pressed, focused and its window has the focus. 1336 * 1337 * @see #PRESSED_STATE_SET 1338 * @see #FOCUSED_STATE_SET 1339 * @see #WINDOW_FOCUSED_STATE_SET 1340 */ 1341 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1342 /** 1343 * Indicates the view is pressed, focused and selected. 1344 * 1345 * @see #PRESSED_STATE_SET 1346 * @see #SELECTED_STATE_SET 1347 * @see #FOCUSED_STATE_SET 1348 */ 1349 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1350 /** 1351 * Indicates the view is pressed, focused, selected and its window has the focus. 1352 * 1353 * @see #PRESSED_STATE_SET 1354 * @see #FOCUSED_STATE_SET 1355 * @see #SELECTED_STATE_SET 1356 * @see #WINDOW_FOCUSED_STATE_SET 1357 */ 1358 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1359 /** 1360 * Indicates the view is pressed and enabled. 1361 * 1362 * @see #PRESSED_STATE_SET 1363 * @see #ENABLED_STATE_SET 1364 */ 1365 protected static final int[] PRESSED_ENABLED_STATE_SET; 1366 /** 1367 * Indicates the view is pressed, enabled and its window has the focus. 1368 * 1369 * @see #PRESSED_STATE_SET 1370 * @see #ENABLED_STATE_SET 1371 * @see #WINDOW_FOCUSED_STATE_SET 1372 */ 1373 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1374 /** 1375 * Indicates the view is pressed, enabled and selected. 1376 * 1377 * @see #PRESSED_STATE_SET 1378 * @see #ENABLED_STATE_SET 1379 * @see #SELECTED_STATE_SET 1380 */ 1381 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1382 /** 1383 * Indicates the view is pressed, enabled, selected and its window has the 1384 * focus. 1385 * 1386 * @see #PRESSED_STATE_SET 1387 * @see #ENABLED_STATE_SET 1388 * @see #SELECTED_STATE_SET 1389 * @see #WINDOW_FOCUSED_STATE_SET 1390 */ 1391 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1392 /** 1393 * Indicates the view is pressed, enabled and focused. 1394 * 1395 * @see #PRESSED_STATE_SET 1396 * @see #ENABLED_STATE_SET 1397 * @see #FOCUSED_STATE_SET 1398 */ 1399 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1400 /** 1401 * Indicates the view is pressed, enabled, focused and its window has the 1402 * focus. 1403 * 1404 * @see #PRESSED_STATE_SET 1405 * @see #ENABLED_STATE_SET 1406 * @see #FOCUSED_STATE_SET 1407 * @see #WINDOW_FOCUSED_STATE_SET 1408 */ 1409 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1410 /** 1411 * Indicates the view is pressed, enabled, focused and selected. 1412 * 1413 * @see #PRESSED_STATE_SET 1414 * @see #ENABLED_STATE_SET 1415 * @see #SELECTED_STATE_SET 1416 * @see #FOCUSED_STATE_SET 1417 */ 1418 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1419 /** 1420 * Indicates the view is pressed, enabled, focused, selected and its window 1421 * has the focus. 1422 * 1423 * @see #PRESSED_STATE_SET 1424 * @see #ENABLED_STATE_SET 1425 * @see #SELECTED_STATE_SET 1426 * @see #FOCUSED_STATE_SET 1427 * @see #WINDOW_FOCUSED_STATE_SET 1428 */ 1429 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1430 1431 /** 1432 * The order here is very important to {@link #getDrawableState()} 1433 */ 1434 private static final int[][] VIEW_STATE_SETS; 1435 1436 static final int VIEW_STATE_WINDOW_FOCUSED = 1; 1437 static final int VIEW_STATE_SELECTED = 1 << 1; 1438 static final int VIEW_STATE_FOCUSED = 1 << 2; 1439 static final int VIEW_STATE_ENABLED = 1 << 3; 1440 static final int VIEW_STATE_PRESSED = 1 << 4; 1441 static final int VIEW_STATE_ACTIVATED = 1 << 5; 1442 static final int VIEW_STATE_ACCELERATED = 1 << 6; 1443 static final int VIEW_STATE_HOVERED = 1 << 7; 1444 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8; 1445 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9; 1446 1447 static final int[] VIEW_STATE_IDS = new int[] { 1448 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED, 1449 R.attr.state_selected, VIEW_STATE_SELECTED, 1450 R.attr.state_focused, VIEW_STATE_FOCUSED, 1451 R.attr.state_enabled, VIEW_STATE_ENABLED, 1452 R.attr.state_pressed, VIEW_STATE_PRESSED, 1453 R.attr.state_activated, VIEW_STATE_ACTIVATED, 1454 R.attr.state_accelerated, VIEW_STATE_ACCELERATED, 1455 R.attr.state_hovered, VIEW_STATE_HOVERED, 1456 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT, 1457 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED 1458 }; 1459 1460 static { 1461 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) { 1462 throw new IllegalStateException( 1463 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array"); 1464 } 1465 int[] orderedIds = new int[VIEW_STATE_IDS.length]; 1466 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) { 1467 int viewState = R.styleable.ViewDrawableStates[i]; 1468 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) { 1469 if (VIEW_STATE_IDS[j] == viewState) { 1470 orderedIds[i * 2] = viewState; 1471 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1]; 1472 } 1473 } 1474 } 1475 final int NUM_BITS = VIEW_STATE_IDS.length / 2; 1476 VIEW_STATE_SETS = new int[1 << NUM_BITS][]; 1477 for (int i = 0; i < VIEW_STATE_SETS.length; i++) { 1478 int numBits = Integer.bitCount(i); 1479 int[] set = new int[numBits]; 1480 int pos = 0; 1481 for (int j = 0; j < orderedIds.length; j += 2) { 1482 if ((i & orderedIds[j+1]) != 0) { 1483 set[pos++] = orderedIds[j]; 1484 } 1485 } 1486 VIEW_STATE_SETS[i] = set; 1487 } 1488 1489 EMPTY_STATE_SET = VIEW_STATE_SETS[0]; 1490 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED]; 1491 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED]; 1492 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1493 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED]; 1494 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED]; 1495 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1496 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED]; 1497 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1498 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED]; 1499 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1500 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1501 | VIEW_STATE_FOCUSED]; 1502 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED]; 1503 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1504 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED]; 1505 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1506 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED]; 1507 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1508 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1509 | VIEW_STATE_ENABLED]; 1510 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1511 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED]; 1512 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1513 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1514 | VIEW_STATE_ENABLED]; 1515 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1516 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1517 | VIEW_STATE_ENABLED]; 1518 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1519 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1520 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED]; 1521 1522 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED]; 1523 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1524 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED]; 1525 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1526 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED]; 1527 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1528 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1529 | VIEW_STATE_PRESSED]; 1530 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1531 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1532 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1533 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1534 | VIEW_STATE_PRESSED]; 1535 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1536 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1537 | VIEW_STATE_PRESSED]; 1538 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1539 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1540 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1541 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[ 1542 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1543 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1544 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED 1545 | VIEW_STATE_PRESSED]; 1546 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1547 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED 1548 | VIEW_STATE_PRESSED]; 1549 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1550 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1551 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1552 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1553 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED 1554 | VIEW_STATE_PRESSED]; 1555 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1556 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1557 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1558 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1559 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1560 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1561 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1562 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1563 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED 1564 | VIEW_STATE_PRESSED]; 1565 } 1566 1567 /** 1568 * Accessibility event types that are dispatched for text population. 1569 */ 1570 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1571 AccessibilityEvent.TYPE_VIEW_CLICKED 1572 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1573 | AccessibilityEvent.TYPE_VIEW_SELECTED 1574 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1575 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1576 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1577 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 1578 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 1579 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 1580 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 1581 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 1582 1583 /** 1584 * Temporary Rect currently for use in setBackground(). This will probably 1585 * be extended in the future to hold our own class with more than just 1586 * a Rect. :) 1587 */ 1588 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1589 1590 /** 1591 * Map used to store views' tags. 1592 */ 1593 private SparseArray<Object> mKeyedTags; 1594 1595 /** 1596 * The next available accessibility id. 1597 */ 1598 private static int sNextAccessibilityViewId; 1599 1600 /** 1601 * The animation currently associated with this view. 1602 * @hide 1603 */ 1604 protected Animation mCurrentAnimation = null; 1605 1606 /** 1607 * Width as measured during measure pass. 1608 * {@hide} 1609 */ 1610 @ViewDebug.ExportedProperty(category = "measurement") 1611 int mMeasuredWidth; 1612 1613 /** 1614 * Height as measured during measure pass. 1615 * {@hide} 1616 */ 1617 @ViewDebug.ExportedProperty(category = "measurement") 1618 int mMeasuredHeight; 1619 1620 /** 1621 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1622 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1623 * its display list. This flag, used only when hw accelerated, allows us to clear the 1624 * flag while retaining this information until it's needed (at getDisplayList() time and 1625 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1626 * 1627 * {@hide} 1628 */ 1629 boolean mRecreateDisplayList = false; 1630 1631 /** 1632 * The view's identifier. 1633 * {@hide} 1634 * 1635 * @see #setId(int) 1636 * @see #getId() 1637 */ 1638 @ViewDebug.ExportedProperty(resolveId = true) 1639 int mID = NO_ID; 1640 1641 /** 1642 * The stable ID of this view for accessibility purposes. 1643 */ 1644 int mAccessibilityViewId = NO_ID; 1645 1646 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 1647 1648 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent; 1649 1650 /** 1651 * The view's tag. 1652 * {@hide} 1653 * 1654 * @see #setTag(Object) 1655 * @see #getTag() 1656 */ 1657 protected Object mTag = null; 1658 1659 // for mPrivateFlags: 1660 /** {@hide} */ 1661 static final int PFLAG_WANTS_FOCUS = 0x00000001; 1662 /** {@hide} */ 1663 static final int PFLAG_FOCUSED = 0x00000002; 1664 /** {@hide} */ 1665 static final int PFLAG_SELECTED = 0x00000004; 1666 /** {@hide} */ 1667 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 1668 /** {@hide} */ 1669 static final int PFLAG_HAS_BOUNDS = 0x00000010; 1670 /** {@hide} */ 1671 static final int PFLAG_DRAWN = 0x00000020; 1672 /** 1673 * When this flag is set, this view is running an animation on behalf of its 1674 * children and should therefore not cancel invalidate requests, even if they 1675 * lie outside of this view's bounds. 1676 * 1677 * {@hide} 1678 */ 1679 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 1680 /** {@hide} */ 1681 static final int PFLAG_SKIP_DRAW = 0x00000080; 1682 /** {@hide} */ 1683 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100; 1684 /** {@hide} */ 1685 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1686 /** {@hide} */ 1687 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 1688 /** {@hide} */ 1689 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 1690 /** {@hide} */ 1691 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 1692 /** {@hide} */ 1693 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 1694 1695 private static final int PFLAG_PRESSED = 0x00004000; 1696 1697 /** {@hide} */ 1698 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 1699 /** 1700 * Flag used to indicate that this view should be drawn once more (and only once 1701 * more) after its animation has completed. 1702 * {@hide} 1703 */ 1704 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 1705 1706 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 1707 1708 /** 1709 * Indicates that the View returned true when onSetAlpha() was called and that 1710 * the alpha must be restored. 1711 * {@hide} 1712 */ 1713 static final int PFLAG_ALPHA_SET = 0x00040000; 1714 1715 /** 1716 * Set by {@link #setScrollContainer(boolean)}. 1717 */ 1718 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 1719 1720 /** 1721 * Set by {@link #setScrollContainer(boolean)}. 1722 */ 1723 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 1724 1725 /** 1726 * View flag indicating whether this view was invalidated (fully or partially.) 1727 * 1728 * @hide 1729 */ 1730 static final int PFLAG_DIRTY = 0x00200000; 1731 1732 /** 1733 * View flag indicating whether this view was invalidated by an opaque 1734 * invalidate request. 1735 * 1736 * @hide 1737 */ 1738 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 1739 1740 /** 1741 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 1742 * 1743 * @hide 1744 */ 1745 static final int PFLAG_DIRTY_MASK = 0x00600000; 1746 1747 /** 1748 * Indicates whether the background is opaque. 1749 * 1750 * @hide 1751 */ 1752 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 1753 1754 /** 1755 * Indicates whether the scrollbars are opaque. 1756 * 1757 * @hide 1758 */ 1759 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 1760 1761 /** 1762 * Indicates whether the view is opaque. 1763 * 1764 * @hide 1765 */ 1766 static final int PFLAG_OPAQUE_MASK = 0x01800000; 1767 1768 /** 1769 * Indicates a prepressed state; 1770 * the short time between ACTION_DOWN and recognizing 1771 * a 'real' press. Prepressed is used to recognize quick taps 1772 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1773 * 1774 * @hide 1775 */ 1776 private static final int PFLAG_PREPRESSED = 0x02000000; 1777 1778 /** 1779 * Indicates whether the view is temporarily detached. 1780 * 1781 * @hide 1782 */ 1783 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 1784 1785 /** 1786 * Indicates that we should awaken scroll bars once attached 1787 * 1788 * @hide 1789 */ 1790 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1791 1792 /** 1793 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1794 * @hide 1795 */ 1796 private static final int PFLAG_HOVERED = 0x10000000; 1797 1798 /** 1799 * no longer needed, should be reused 1800 */ 1801 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000; 1802 1803 /** {@hide} */ 1804 static final int PFLAG_ACTIVATED = 0x40000000; 1805 1806 /** 1807 * Indicates that this view was specifically invalidated, not just dirtied because some 1808 * child view was invalidated. The flag is used to determine when we need to recreate 1809 * a view's display list (as opposed to just returning a reference to its existing 1810 * display list). 1811 * 1812 * @hide 1813 */ 1814 static final int PFLAG_INVALIDATED = 0x80000000; 1815 1816 /** 1817 * Masks for mPrivateFlags2, as generated by dumpFlags(): 1818 * 1819 * |-------|-------|-------|-------| 1820 * 1 PFLAG2_DRAG_CAN_ACCEPT 1821 * 1 PFLAG2_DRAG_HOVERED 1822 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 1823 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 1824 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 1825 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 1826 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 1827 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 1828 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 1829 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 1830 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 1831 * 111 PFLAG2_TEXT_DIRECTION_MASK 1832 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 1833 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 1834 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 1835 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 1836 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 1837 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 1838 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 1839 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 1840 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 1841 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 1842 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 1843 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 1844 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 1845 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 1846 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 1847 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 1848 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 1849 * 1 PFLAG2_VIEW_QUICK_REJECTED 1850 * 1 PFLAG2_PADDING_RESOLVED 1851 * 1 PFLAG2_DRAWABLE_RESOLVED 1852 * 1 PFLAG2_HAS_TRANSIENT_STATE 1853 * |-------|-------|-------|-------| 1854 */ 1855 1856 /** 1857 * Indicates that this view has reported that it can accept the current drag's content. 1858 * Cleared when the drag operation concludes. 1859 * @hide 1860 */ 1861 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 1862 1863 /** 1864 * Indicates that this view is currently directly under the drag location in a 1865 * drag-and-drop operation involving content that it can accept. Cleared when 1866 * the drag exits the view, or when the drag operation concludes. 1867 * @hide 1868 */ 1869 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 1870 1871 /** @hide */ 1872 @IntDef({ 1873 LAYOUT_DIRECTION_LTR, 1874 LAYOUT_DIRECTION_RTL, 1875 LAYOUT_DIRECTION_INHERIT, 1876 LAYOUT_DIRECTION_LOCALE 1877 }) 1878 @Retention(RetentionPolicy.SOURCE) 1879 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection 1880 public @interface LayoutDir {} 1881 1882 /** @hide */ 1883 @IntDef({ 1884 LAYOUT_DIRECTION_LTR, 1885 LAYOUT_DIRECTION_RTL 1886 }) 1887 @Retention(RetentionPolicy.SOURCE) 1888 public @interface ResolvedLayoutDir {} 1889 1890 /** 1891 * Horizontal layout direction of this view is from Left to Right. 1892 * Use with {@link #setLayoutDirection}. 1893 */ 1894 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 1895 1896 /** 1897 * Horizontal layout direction of this view is from Right to Left. 1898 * Use with {@link #setLayoutDirection}. 1899 */ 1900 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 1901 1902 /** 1903 * Horizontal layout direction of this view is inherited from its parent. 1904 * Use with {@link #setLayoutDirection}. 1905 */ 1906 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 1907 1908 /** 1909 * Horizontal layout direction of this view is from deduced from the default language 1910 * script for the locale. Use with {@link #setLayoutDirection}. 1911 */ 1912 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 1913 1914 /** 1915 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1916 * @hide 1917 */ 1918 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 1919 1920 /** 1921 * Mask for use with private flags indicating bits used for horizontal layout direction. 1922 * @hide 1923 */ 1924 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1925 1926 /** 1927 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 1928 * right-to-left direction. 1929 * @hide 1930 */ 1931 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1932 1933 /** 1934 * Indicates whether the view horizontal layout direction has been resolved. 1935 * @hide 1936 */ 1937 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1938 1939 /** 1940 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 1941 * @hide 1942 */ 1943 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 1944 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1945 1946 /* 1947 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 1948 * flag value. 1949 * @hide 1950 */ 1951 private static final int[] LAYOUT_DIRECTION_FLAGS = { 1952 LAYOUT_DIRECTION_LTR, 1953 LAYOUT_DIRECTION_RTL, 1954 LAYOUT_DIRECTION_INHERIT, 1955 LAYOUT_DIRECTION_LOCALE 1956 }; 1957 1958 /** 1959 * Default horizontal layout direction. 1960 */ 1961 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 1962 1963 /** 1964 * Default horizontal layout direction. 1965 * @hide 1966 */ 1967 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 1968 1969 /** 1970 * Text direction is inherited thru {@link ViewGroup} 1971 */ 1972 public static final int TEXT_DIRECTION_INHERIT = 0; 1973 1974 /** 1975 * Text direction is using "first strong algorithm". The first strong directional character 1976 * determines the paragraph direction. If there is no strong directional character, the 1977 * paragraph direction is the view's resolved layout direction. 1978 */ 1979 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 1980 1981 /** 1982 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 1983 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 1984 * If there are neither, the paragraph direction is the view's resolved layout direction. 1985 */ 1986 public static final int TEXT_DIRECTION_ANY_RTL = 2; 1987 1988 /** 1989 * Text direction is forced to LTR. 1990 */ 1991 public static final int TEXT_DIRECTION_LTR = 3; 1992 1993 /** 1994 * Text direction is forced to RTL. 1995 */ 1996 public static final int TEXT_DIRECTION_RTL = 4; 1997 1998 /** 1999 * Text direction is coming from the system Locale. 2000 */ 2001 public static final int TEXT_DIRECTION_LOCALE = 5; 2002 2003 /** 2004 * Default text direction is inherited 2005 */ 2006 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 2007 2008 /** 2009 * Default resolved text direction 2010 * @hide 2011 */ 2012 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 2013 2014 /** 2015 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 2016 * @hide 2017 */ 2018 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 2019 2020 /** 2021 * Mask for use with private flags indicating bits used for text direction. 2022 * @hide 2023 */ 2024 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 2025 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2026 2027 /** 2028 * Array of text direction flags for mapping attribute "textDirection" to correct 2029 * flag value. 2030 * @hide 2031 */ 2032 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 2033 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2034 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2035 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2036 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2037 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2038 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 2039 }; 2040 2041 /** 2042 * Indicates whether the view text direction has been resolved. 2043 * @hide 2044 */ 2045 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 2046 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2047 2048 /** 2049 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2050 * @hide 2051 */ 2052 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 2053 2054 /** 2055 * Mask for use with private flags indicating bits used for resolved text direction. 2056 * @hide 2057 */ 2058 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 2059 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2060 2061 /** 2062 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 2063 * @hide 2064 */ 2065 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 2066 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2067 2068 /** @hide */ 2069 @IntDef({ 2070 TEXT_ALIGNMENT_INHERIT, 2071 TEXT_ALIGNMENT_GRAVITY, 2072 TEXT_ALIGNMENT_CENTER, 2073 TEXT_ALIGNMENT_TEXT_START, 2074 TEXT_ALIGNMENT_TEXT_END, 2075 TEXT_ALIGNMENT_VIEW_START, 2076 TEXT_ALIGNMENT_VIEW_END 2077 }) 2078 @Retention(RetentionPolicy.SOURCE) 2079 public @interface TextAlignment {} 2080 2081 /** 2082 * Default text alignment. The text alignment of this View is inherited from its parent. 2083 * Use with {@link #setTextAlignment(int)} 2084 */ 2085 public static final int TEXT_ALIGNMENT_INHERIT = 0; 2086 2087 /** 2088 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 2089 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 2090 * 2091 * Use with {@link #setTextAlignment(int)} 2092 */ 2093 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 2094 2095 /** 2096 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2097 * 2098 * Use with {@link #setTextAlignment(int)} 2099 */ 2100 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2101 2102 /** 2103 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2104 * 2105 * Use with {@link #setTextAlignment(int)} 2106 */ 2107 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2108 2109 /** 2110 * Center the paragraph, e.g. ALIGN_CENTER. 2111 * 2112 * Use with {@link #setTextAlignment(int)} 2113 */ 2114 public static final int TEXT_ALIGNMENT_CENTER = 4; 2115 2116 /** 2117 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved 2118 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2119 * 2120 * Use with {@link #setTextAlignment(int)} 2121 */ 2122 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2123 2124 /** 2125 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved 2126 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2127 * 2128 * Use with {@link #setTextAlignment(int)} 2129 */ 2130 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2131 2132 /** 2133 * Default text alignment is inherited 2134 */ 2135 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2136 2137 /** 2138 * Default resolved text alignment 2139 * @hide 2140 */ 2141 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2142 2143 /** 2144 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2145 * @hide 2146 */ 2147 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2148 2149 /** 2150 * Mask for use with private flags indicating bits used for text alignment. 2151 * @hide 2152 */ 2153 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2154 2155 /** 2156 * Array of text direction flags for mapping attribute "textAlignment" to correct 2157 * flag value. 2158 * @hide 2159 */ 2160 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2161 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2162 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2163 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2164 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2165 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2166 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2167 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2168 }; 2169 2170 /** 2171 * Indicates whether the view text alignment has been resolved. 2172 * @hide 2173 */ 2174 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2175 2176 /** 2177 * Bit shift to get the resolved text alignment. 2178 * @hide 2179 */ 2180 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2181 2182 /** 2183 * Mask for use with private flags indicating bits used for text alignment. 2184 * @hide 2185 */ 2186 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2187 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2188 2189 /** 2190 * Indicates whether if the view text alignment has been resolved to gravity 2191 */ 2192 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2193 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2194 2195 // Accessiblity constants for mPrivateFlags2 2196 2197 /** 2198 * Shift for the bits in {@link #mPrivateFlags2} related to the 2199 * "importantForAccessibility" attribute. 2200 */ 2201 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2202 2203 /** 2204 * Automatically determine whether a view is important for accessibility. 2205 */ 2206 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2207 2208 /** 2209 * The view is important for accessibility. 2210 */ 2211 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2212 2213 /** 2214 * The view is not important for accessibility. 2215 */ 2216 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2217 2218 /** 2219 * The view is not important for accessibility, nor are any of its 2220 * descendant views. 2221 */ 2222 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2223 2224 /** 2225 * The default whether the view is important for accessibility. 2226 */ 2227 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2228 2229 /** 2230 * Mask for obtainig the bits which specify how to determine 2231 * whether a view is important for accessibility. 2232 */ 2233 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2234 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2235 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2236 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2237 2238 /** 2239 * Shift for the bits in {@link #mPrivateFlags2} related to the 2240 * "accessibilityLiveRegion" attribute. 2241 */ 2242 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2243 2244 /** 2245 * Live region mode specifying that accessibility services should not 2246 * automatically announce changes to this view. This is the default live 2247 * region mode for most views. 2248 * <p> 2249 * Use with {@link #setAccessibilityLiveRegion(int)}. 2250 */ 2251 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2252 2253 /** 2254 * Live region mode specifying that accessibility services should announce 2255 * changes to this view. 2256 * <p> 2257 * Use with {@link #setAccessibilityLiveRegion(int)}. 2258 */ 2259 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2260 2261 /** 2262 * Live region mode specifying that accessibility services should interrupt 2263 * ongoing speech to immediately announce changes to this view. 2264 * <p> 2265 * Use with {@link #setAccessibilityLiveRegion(int)}. 2266 */ 2267 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2268 2269 /** 2270 * The default whether the view is important for accessibility. 2271 */ 2272 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2273 2274 /** 2275 * Mask for obtaining the bits which specify a view's accessibility live 2276 * region mode. 2277 */ 2278 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2279 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2280 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2281 2282 /** 2283 * Flag indicating whether a view has accessibility focus. 2284 */ 2285 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2286 2287 /** 2288 * Flag whether the accessibility state of the subtree rooted at this view changed. 2289 */ 2290 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2291 2292 /** 2293 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2294 * is used to check whether later changes to the view's transform should invalidate the 2295 * view to force the quickReject test to run again. 2296 */ 2297 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2298 2299 /** 2300 * Flag indicating that start/end padding has been resolved into left/right padding 2301 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2302 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2303 * during measurement. In some special cases this is required such as when an adapter-based 2304 * view measures prospective children without attaching them to a window. 2305 */ 2306 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2307 2308 /** 2309 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2310 */ 2311 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2312 2313 /** 2314 * Indicates that the view is tracking some sort of transient state 2315 * that the app should not need to be aware of, but that the framework 2316 * should take special care to preserve. 2317 */ 2318 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2319 2320 /** 2321 * Group of bits indicating that RTL properties resolution is done. 2322 */ 2323 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2324 PFLAG2_TEXT_DIRECTION_RESOLVED | 2325 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2326 PFLAG2_PADDING_RESOLVED | 2327 PFLAG2_DRAWABLE_RESOLVED; 2328 2329 // There are a couple of flags left in mPrivateFlags2 2330 2331 /* End of masks for mPrivateFlags2 */ 2332 2333 /** 2334 * Masks for mPrivateFlags3, as generated by dumpFlags(): 2335 * 2336 * |-------|-------|-------|-------| 2337 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM 2338 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA 2339 * 1 PFLAG3_IS_LAID_OUT 2340 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT 2341 * 1 PFLAG3_CALLED_SUPER 2342 * |-------|-------|-------|-------| 2343 */ 2344 2345 /** 2346 * Flag indicating that view has a transform animation set on it. This is used to track whether 2347 * an animation is cleared between successive frames, in order to tell the associated 2348 * DisplayList to clear its animation matrix. 2349 */ 2350 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2351 2352 /** 2353 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2354 * animation is cleared between successive frames, in order to tell the associated 2355 * DisplayList to restore its alpha value. 2356 */ 2357 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2358 2359 /** 2360 * Flag indicating that the view has been through at least one layout since it 2361 * was last attached to a window. 2362 */ 2363 static final int PFLAG3_IS_LAID_OUT = 0x4; 2364 2365 /** 2366 * Flag indicating that a call to measure() was skipped and should be done 2367 * instead when layout() is invoked. 2368 */ 2369 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2370 2371 /** 2372 * Flag indicating that an overridden method correctly called down to 2373 * the superclass implementation as required by the API spec. 2374 */ 2375 static final int PFLAG3_CALLED_SUPER = 0x10; 2376 2377 /** 2378 * Flag indicating that a view's outline has been specifically defined. 2379 */ 2380 static final int PFLAG3_OUTLINE_DEFINED = 0x20; 2381 2382 /** 2383 * Flag indicating that we're in the process of applying window insets. 2384 */ 2385 static final int PFLAG3_APPLYING_INSETS = 0x40; 2386 2387 /** 2388 * Flag indicating that we're in the process of fitting system windows using the old method. 2389 */ 2390 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80; 2391 2392 /** 2393 * Flag indicating that nested scrolling is enabled for this view. 2394 * The view will optionally cooperate with views up its parent chain to allow for 2395 * integrated nested scrolling along the same axis. 2396 */ 2397 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x200; 2398 2399 /* End of masks for mPrivateFlags3 */ 2400 2401 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 2402 2403 /** 2404 * Always allow a user to over-scroll this view, provided it is a 2405 * view that can scroll. 2406 * 2407 * @see #getOverScrollMode() 2408 * @see #setOverScrollMode(int) 2409 */ 2410 public static final int OVER_SCROLL_ALWAYS = 0; 2411 2412 /** 2413 * Allow a user to over-scroll this view only if the content is large 2414 * enough to meaningfully scroll, provided it is a view that can scroll. 2415 * 2416 * @see #getOverScrollMode() 2417 * @see #setOverScrollMode(int) 2418 */ 2419 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 2420 2421 /** 2422 * Never allow a user to over-scroll this view. 2423 * 2424 * @see #getOverScrollMode() 2425 * @see #setOverScrollMode(int) 2426 */ 2427 public static final int OVER_SCROLL_NEVER = 2; 2428 2429 /** 2430 * Special constant for {@link #setSystemUiVisibility(int)}: View has 2431 * requested the system UI (status bar) to be visible (the default). 2432 * 2433 * @see #setSystemUiVisibility(int) 2434 */ 2435 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 2436 2437 /** 2438 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 2439 * system UI to enter an unobtrusive "low profile" mode. 2440 * 2441 * <p>This is for use in games, book readers, video players, or any other 2442 * "immersive" application where the usual system chrome is deemed too distracting. 2443 * 2444 * <p>In low profile mode, the status bar and/or navigation icons may dim. 2445 * 2446 * @see #setSystemUiVisibility(int) 2447 */ 2448 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 2449 2450 /** 2451 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 2452 * system navigation be temporarily hidden. 2453 * 2454 * <p>This is an even less obtrusive state than that called for by 2455 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 2456 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 2457 * those to disappear. This is useful (in conjunction with the 2458 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 2459 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 2460 * window flags) for displaying content using every last pixel on the display. 2461 * 2462 * <p>There is a limitation: because navigation controls are so important, the least user 2463 * interaction will cause them to reappear immediately. When this happens, both 2464 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 2465 * so that both elements reappear at the same time. 2466 * 2467 * @see #setSystemUiVisibility(int) 2468 */ 2469 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 2470 2471 /** 2472 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 2473 * into the normal fullscreen mode so that its content can take over the screen 2474 * while still allowing the user to interact with the application. 2475 * 2476 * <p>This has the same visual effect as 2477 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 2478 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 2479 * meaning that non-critical screen decorations (such as the status bar) will be 2480 * hidden while the user is in the View's window, focusing the experience on 2481 * that content. Unlike the window flag, if you are using ActionBar in 2482 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2483 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 2484 * hide the action bar. 2485 * 2486 * <p>This approach to going fullscreen is best used over the window flag when 2487 * it is a transient state -- that is, the application does this at certain 2488 * points in its user interaction where it wants to allow the user to focus 2489 * on content, but not as a continuous state. For situations where the application 2490 * would like to simply stay full screen the entire time (such as a game that 2491 * wants to take over the screen), the 2492 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 2493 * is usually a better approach. The state set here will be removed by the system 2494 * in various situations (such as the user moving to another application) like 2495 * the other system UI states. 2496 * 2497 * <p>When using this flag, the application should provide some easy facility 2498 * for the user to go out of it. A common example would be in an e-book 2499 * reader, where tapping on the screen brings back whatever screen and UI 2500 * decorations that had been hidden while the user was immersed in reading 2501 * the book. 2502 * 2503 * @see #setSystemUiVisibility(int) 2504 */ 2505 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 2506 2507 /** 2508 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 2509 * flags, we would like a stable view of the content insets given to 2510 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 2511 * will always represent the worst case that the application can expect 2512 * as a continuous state. In the stock Android UI this is the space for 2513 * the system bar, nav bar, and status bar, but not more transient elements 2514 * such as an input method. 2515 * 2516 * The stable layout your UI sees is based on the system UI modes you can 2517 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 2518 * then you will get a stable layout for changes of the 2519 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 2520 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 2521 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 2522 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 2523 * with a stable layout. (Note that you should avoid using 2524 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 2525 * 2526 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 2527 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 2528 * then a hidden status bar will be considered a "stable" state for purposes 2529 * here. This allows your UI to continually hide the status bar, while still 2530 * using the system UI flags to hide the action bar while still retaining 2531 * a stable layout. Note that changing the window fullscreen flag will never 2532 * provide a stable layout for a clean transition. 2533 * 2534 * <p>If you are using ActionBar in 2535 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2536 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 2537 * insets it adds to those given to the application. 2538 */ 2539 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 2540 2541 /** 2542 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2543 * to be layed out as if it has requested 2544 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 2545 * allows it to avoid artifacts when switching in and out of that mode, at 2546 * the expense that some of its user interface may be covered by screen 2547 * decorations when they are shown. You can perform layout of your inner 2548 * UI elements to account for the navigation system UI through the 2549 * {@link #fitSystemWindows(Rect)} method. 2550 */ 2551 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 2552 2553 /** 2554 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2555 * to be layed out as if it has requested 2556 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 2557 * allows it to avoid artifacts when switching in and out of that mode, at 2558 * the expense that some of its user interface may be covered by screen 2559 * decorations when they are shown. You can perform layout of your inner 2560 * UI elements to account for non-fullscreen system UI through the 2561 * {@link #fitSystemWindows(Rect)} method. 2562 */ 2563 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 2564 2565 /** 2566 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2567 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 2568 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 2569 * user interaction. 2570 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 2571 * has an effect when used in combination with that flag.</p> 2572 */ 2573 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 2574 2575 /** 2576 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2577 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 2578 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 2579 * experience while also hiding the system bars. If this flag is not set, 2580 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 2581 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 2582 * if the user swipes from the top of the screen. 2583 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 2584 * system gestures, such as swiping from the top of the screen. These transient system bars 2585 * will overlay app’s content, may have some degree of transparency, and will automatically 2586 * hide after a short timeout. 2587 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 2588 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 2589 * with one or both of those flags.</p> 2590 */ 2591 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 2592 2593 /** 2594 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 2595 */ 2596 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 2597 2598 /** 2599 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 2600 */ 2601 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 2602 2603 /** 2604 * @hide 2605 * 2606 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2607 * out of the public fields to keep the undefined bits out of the developer's way. 2608 * 2609 * Flag to make the status bar not expandable. Unless you also 2610 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 2611 */ 2612 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 2613 2614 /** 2615 * @hide 2616 * 2617 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2618 * out of the public fields to keep the undefined bits out of the developer's way. 2619 * 2620 * Flag to hide notification icons and scrolling ticker text. 2621 */ 2622 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 2623 2624 /** 2625 * @hide 2626 * 2627 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2628 * out of the public fields to keep the undefined bits out of the developer's way. 2629 * 2630 * Flag to disable incoming notification alerts. This will not block 2631 * icons, but it will block sound, vibrating and other visual or aural notifications. 2632 */ 2633 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 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 hide only the scrolling ticker. Note that 2642 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 2643 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 2644 */ 2645 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 2646 2647 /** 2648 * @hide 2649 * 2650 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2651 * out of the public fields to keep the undefined bits out of the developer's way. 2652 * 2653 * Flag to hide the center system info area. 2654 */ 2655 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 2656 2657 /** 2658 * @hide 2659 * 2660 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2661 * out of the public fields to keep the undefined bits out of the developer's way. 2662 * 2663 * Flag to hide only the home button. Don't use this 2664 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2665 */ 2666 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 2667 2668 /** 2669 * @hide 2670 * 2671 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2672 * out of the public fields to keep the undefined bits out of the developer's way. 2673 * 2674 * Flag to hide only the back button. Don't use this 2675 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2676 */ 2677 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 2678 2679 /** 2680 * @hide 2681 * 2682 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2683 * out of the public fields to keep the undefined bits out of the developer's way. 2684 * 2685 * Flag to hide only the clock. You might use this if your activity has 2686 * its own clock making the status bar's clock redundant. 2687 */ 2688 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 2689 2690 /** 2691 * @hide 2692 * 2693 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2694 * out of the public fields to keep the undefined bits out of the developer's way. 2695 * 2696 * Flag to hide only the recent apps button. Don't use this 2697 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2698 */ 2699 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 2700 2701 /** 2702 * @hide 2703 * 2704 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2705 * out of the public fields to keep the undefined bits out of the developer's way. 2706 * 2707 * Flag to disable the global search gesture. Don't use this 2708 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2709 */ 2710 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 2711 2712 /** 2713 * @hide 2714 * 2715 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2716 * out of the public fields to keep the undefined bits out of the developer's way. 2717 * 2718 * Flag to specify that the status bar is displayed in transient mode. 2719 */ 2720 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 2721 2722 /** 2723 * @hide 2724 * 2725 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2726 * out of the public fields to keep the undefined bits out of the developer's way. 2727 * 2728 * Flag to specify that the navigation bar is displayed in transient mode. 2729 */ 2730 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 2731 2732 /** 2733 * @hide 2734 * 2735 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2736 * out of the public fields to keep the undefined bits out of the developer's way. 2737 * 2738 * Flag to specify that the hidden status bar would like to be shown. 2739 */ 2740 public static final int STATUS_BAR_UNHIDE = 0x10000000; 2741 2742 /** 2743 * @hide 2744 * 2745 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2746 * out of the public fields to keep the undefined bits out of the developer's way. 2747 * 2748 * Flag to specify that the hidden navigation bar would like to be shown. 2749 */ 2750 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 2751 2752 /** 2753 * @hide 2754 * 2755 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2756 * out of the public fields to keep the undefined bits out of the developer's way. 2757 * 2758 * Flag to specify that the status bar is displayed in translucent mode. 2759 */ 2760 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 2761 2762 /** 2763 * @hide 2764 * 2765 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2766 * out of the public fields to keep the undefined bits out of the developer's way. 2767 * 2768 * Flag to specify that the navigation bar is displayed in translucent mode. 2769 */ 2770 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 2771 2772 /** 2773 * @hide 2774 */ 2775 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF; 2776 2777 /** 2778 * These are the system UI flags that can be cleared by events outside 2779 * of an application. Currently this is just the ability to tap on the 2780 * screen while hiding the navigation bar to have it return. 2781 * @hide 2782 */ 2783 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 2784 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 2785 | SYSTEM_UI_FLAG_FULLSCREEN; 2786 2787 /** 2788 * Flags that can impact the layout in relation to system UI. 2789 */ 2790 public static final int SYSTEM_UI_LAYOUT_FLAGS = 2791 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 2792 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 2793 2794 /** @hide */ 2795 @IntDef(flag = true, 2796 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION }) 2797 @Retention(RetentionPolicy.SOURCE) 2798 public @interface FindViewFlags {} 2799 2800 /** 2801 * Find views that render the specified text. 2802 * 2803 * @see #findViewsWithText(ArrayList, CharSequence, int) 2804 */ 2805 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 2806 2807 /** 2808 * Find find views that contain the specified content description. 2809 * 2810 * @see #findViewsWithText(ArrayList, CharSequence, int) 2811 */ 2812 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 2813 2814 /** 2815 * Find views that contain {@link AccessibilityNodeProvider}. Such 2816 * a View is a root of virtual view hierarchy and may contain the searched 2817 * text. If this flag is set Views with providers are automatically 2818 * added and it is a responsibility of the client to call the APIs of 2819 * the provider to determine whether the virtual tree rooted at this View 2820 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 2821 * representing the virtual views with this text. 2822 * 2823 * @see #findViewsWithText(ArrayList, CharSequence, int) 2824 * 2825 * @hide 2826 */ 2827 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 2828 2829 /** 2830 * The undefined cursor position. 2831 * 2832 * @hide 2833 */ 2834 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 2835 2836 /** 2837 * Indicates that the screen has changed state and is now off. 2838 * 2839 * @see #onScreenStateChanged(int) 2840 */ 2841 public static final int SCREEN_STATE_OFF = 0x0; 2842 2843 /** 2844 * Indicates that the screen has changed state and is now on. 2845 * 2846 * @see #onScreenStateChanged(int) 2847 */ 2848 public static final int SCREEN_STATE_ON = 0x1; 2849 2850 /** 2851 * Indicates no axis of view scrolling. 2852 */ 2853 public static final int SCROLL_AXIS_NONE = 0; 2854 2855 /** 2856 * Indicates scrolling along the horizontal axis. 2857 */ 2858 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0; 2859 2860 /** 2861 * Indicates scrolling along the vertical axis. 2862 */ 2863 public static final int SCROLL_AXIS_VERTICAL = 1 << 1; 2864 2865 /** 2866 * Controls the over-scroll mode for this view. 2867 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 2868 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 2869 * and {@link #OVER_SCROLL_NEVER}. 2870 */ 2871 private int mOverScrollMode; 2872 2873 /** 2874 * The parent this view is attached to. 2875 * {@hide} 2876 * 2877 * @see #getParent() 2878 */ 2879 protected ViewParent mParent; 2880 2881 /** 2882 * {@hide} 2883 */ 2884 AttachInfo mAttachInfo; 2885 2886 /** 2887 * {@hide} 2888 */ 2889 @ViewDebug.ExportedProperty(flagMapping = { 2890 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 2891 name = "FORCE_LAYOUT"), 2892 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 2893 name = "LAYOUT_REQUIRED"), 2894 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 2895 name = "DRAWING_CACHE_INVALID", outputIf = false), 2896 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 2897 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 2898 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 2899 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 2900 }) 2901 int mPrivateFlags; 2902 int mPrivateFlags2; 2903 int mPrivateFlags3; 2904 2905 /** 2906 * This view's request for the visibility of the status bar. 2907 * @hide 2908 */ 2909 @ViewDebug.ExportedProperty(flagMapping = { 2910 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 2911 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 2912 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 2913 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 2914 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 2915 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 2916 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 2917 equals = SYSTEM_UI_FLAG_VISIBLE, 2918 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 2919 }) 2920 int mSystemUiVisibility; 2921 2922 /** 2923 * Reference count for transient state. 2924 * @see #setHasTransientState(boolean) 2925 */ 2926 int mTransientStateCount = 0; 2927 2928 /** 2929 * Count of how many windows this view has been attached to. 2930 */ 2931 int mWindowAttachCount; 2932 2933 /** 2934 * The layout parameters associated with this view and used by the parent 2935 * {@link android.view.ViewGroup} to determine how this view should be 2936 * laid out. 2937 * {@hide} 2938 */ 2939 protected ViewGroup.LayoutParams mLayoutParams; 2940 2941 /** 2942 * The view flags hold various views states. 2943 * {@hide} 2944 */ 2945 @ViewDebug.ExportedProperty 2946 int mViewFlags; 2947 2948 static class TransformationInfo { 2949 /** 2950 * The transform matrix for the View. This transform is calculated internally 2951 * based on the translation, rotation, and scale properties. 2952 * 2953 * Do *not* use this variable directly; instead call getMatrix(), which will 2954 * load the value from the View's RenderNode. 2955 */ 2956 private final Matrix mMatrix = new Matrix(); 2957 2958 /** 2959 * The inverse transform matrix for the View. This transform is calculated 2960 * internally based on the translation, rotation, and scale properties. 2961 * 2962 * Do *not* use this variable directly; instead call getInverseMatrix(), 2963 * which will load the value from the View's RenderNode. 2964 */ 2965 private Matrix mInverseMatrix; 2966 2967 /** 2968 * The opacity of the View. This is a value from 0 to 1, where 0 means 2969 * completely transparent and 1 means completely opaque. 2970 */ 2971 @ViewDebug.ExportedProperty 2972 float mAlpha = 1f; 2973 2974 /** 2975 * The opacity of the view as manipulated by the Fade transition. This is a hidden 2976 * property only used by transitions, which is composited with the other alpha 2977 * values to calculate the final visual alpha value. 2978 */ 2979 float mTransitionAlpha = 1f; 2980 } 2981 2982 TransformationInfo mTransformationInfo; 2983 2984 /** 2985 * Current clip bounds. to which all drawing of this view are constrained. 2986 */ 2987 Rect mClipBounds = null; 2988 2989 private boolean mLastIsOpaque; 2990 2991 /** 2992 * The distance in pixels from the left edge of this view's parent 2993 * to the left edge of this view. 2994 * {@hide} 2995 */ 2996 @ViewDebug.ExportedProperty(category = "layout") 2997 protected int mLeft; 2998 /** 2999 * The distance in pixels from the left edge of this view's parent 3000 * to the right edge of this view. 3001 * {@hide} 3002 */ 3003 @ViewDebug.ExportedProperty(category = "layout") 3004 protected int mRight; 3005 /** 3006 * The distance in pixels from the top edge of this view's parent 3007 * to the top edge of this view. 3008 * {@hide} 3009 */ 3010 @ViewDebug.ExportedProperty(category = "layout") 3011 protected int mTop; 3012 /** 3013 * The distance in pixels from the top edge of this view's parent 3014 * to the bottom edge of this view. 3015 * {@hide} 3016 */ 3017 @ViewDebug.ExportedProperty(category = "layout") 3018 protected int mBottom; 3019 3020 /** 3021 * The offset, in pixels, by which the content of this view is scrolled 3022 * horizontally. 3023 * {@hide} 3024 */ 3025 @ViewDebug.ExportedProperty(category = "scrolling") 3026 protected int mScrollX; 3027 /** 3028 * The offset, in pixels, by which the content of this view is scrolled 3029 * vertically. 3030 * {@hide} 3031 */ 3032 @ViewDebug.ExportedProperty(category = "scrolling") 3033 protected int mScrollY; 3034 3035 /** 3036 * The left padding in pixels, that is the distance in pixels between the 3037 * left edge of this view and the left edge of its content. 3038 * {@hide} 3039 */ 3040 @ViewDebug.ExportedProperty(category = "padding") 3041 protected int mPaddingLeft = 0; 3042 /** 3043 * The right padding in pixels, that is the distance in pixels between the 3044 * right edge of this view and the right edge of its content. 3045 * {@hide} 3046 */ 3047 @ViewDebug.ExportedProperty(category = "padding") 3048 protected int mPaddingRight = 0; 3049 /** 3050 * The top padding in pixels, that is the distance in pixels between the 3051 * top edge of this view and the top edge of its content. 3052 * {@hide} 3053 */ 3054 @ViewDebug.ExportedProperty(category = "padding") 3055 protected int mPaddingTop; 3056 /** 3057 * The bottom padding in pixels, that is the distance in pixels between the 3058 * bottom edge of this view and the bottom edge of its content. 3059 * {@hide} 3060 */ 3061 @ViewDebug.ExportedProperty(category = "padding") 3062 protected int mPaddingBottom; 3063 3064 /** 3065 * The layout insets in pixels, that is the distance in pixels between the 3066 * visible edges of this view its bounds. 3067 */ 3068 private Insets mLayoutInsets; 3069 3070 /** 3071 * Briefly describes the view and is primarily used for accessibility support. 3072 */ 3073 private CharSequence mContentDescription; 3074 3075 /** 3076 * Specifies the id of a view for which this view serves as a label for 3077 * accessibility purposes. 3078 */ 3079 private int mLabelForId = View.NO_ID; 3080 3081 /** 3082 * Predicate for matching labeled view id with its label for 3083 * accessibility purposes. 3084 */ 3085 private MatchLabelForPredicate mMatchLabelForPredicate; 3086 3087 /** 3088 * Predicate for matching a view by its id. 3089 */ 3090 private MatchIdPredicate mMatchIdPredicate; 3091 3092 /** 3093 * Cache the paddingRight set by the user to append to the scrollbar's size. 3094 * 3095 * @hide 3096 */ 3097 @ViewDebug.ExportedProperty(category = "padding") 3098 protected int mUserPaddingRight; 3099 3100 /** 3101 * Cache the paddingBottom set by the user to append to the scrollbar's size. 3102 * 3103 * @hide 3104 */ 3105 @ViewDebug.ExportedProperty(category = "padding") 3106 protected int mUserPaddingBottom; 3107 3108 /** 3109 * Cache the paddingLeft set by the user to append to the scrollbar's size. 3110 * 3111 * @hide 3112 */ 3113 @ViewDebug.ExportedProperty(category = "padding") 3114 protected int mUserPaddingLeft; 3115 3116 /** 3117 * Cache the paddingStart set by the user to append to the scrollbar's size. 3118 * 3119 */ 3120 @ViewDebug.ExportedProperty(category = "padding") 3121 int mUserPaddingStart; 3122 3123 /** 3124 * Cache the paddingEnd set by the user to append to the scrollbar's size. 3125 * 3126 */ 3127 @ViewDebug.ExportedProperty(category = "padding") 3128 int mUserPaddingEnd; 3129 3130 /** 3131 * Cache initial left padding. 3132 * 3133 * @hide 3134 */ 3135 int mUserPaddingLeftInitial; 3136 3137 /** 3138 * Cache initial right padding. 3139 * 3140 * @hide 3141 */ 3142 int mUserPaddingRightInitial; 3143 3144 /** 3145 * Default undefined padding 3146 */ 3147 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 3148 3149 /** 3150 * Cache if a left padding has been defined 3151 */ 3152 private boolean mLeftPaddingDefined = false; 3153 3154 /** 3155 * Cache if a right padding has been defined 3156 */ 3157 private boolean mRightPaddingDefined = false; 3158 3159 /** 3160 * @hide 3161 */ 3162 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 3163 /** 3164 * @hide 3165 */ 3166 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 3167 3168 private LongSparseLongArray mMeasureCache; 3169 3170 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 3171 private Drawable mBackground; 3172 3173 /** 3174 * Display list used for backgrounds. 3175 * <p> 3176 * When non-null and valid, this is expected to contain an up-to-date copy 3177 * of the background drawable. It is cleared on temporary detach and reset 3178 * on cleanup. 3179 */ 3180 private RenderNode mBackgroundDisplayList; 3181 3182 private int mBackgroundResource; 3183 private boolean mBackgroundSizeChanged; 3184 3185 static class ListenerInfo { 3186 /** 3187 * Listener used to dispatch focus change events. 3188 * This field should be made private, so it is hidden from the SDK. 3189 * {@hide} 3190 */ 3191 protected OnFocusChangeListener mOnFocusChangeListener; 3192 3193 /** 3194 * Listeners for layout change events. 3195 */ 3196 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 3197 3198 /** 3199 * Listeners for attach events. 3200 */ 3201 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 3202 3203 /** 3204 * Listener used to dispatch click events. 3205 * This field should be made private, so it is hidden from the SDK. 3206 * {@hide} 3207 */ 3208 public OnClickListener mOnClickListener; 3209 3210 /** 3211 * Listener used to dispatch long click events. 3212 * This field should be made private, so it is hidden from the SDK. 3213 * {@hide} 3214 */ 3215 protected OnLongClickListener mOnLongClickListener; 3216 3217 /** 3218 * Listener used to build the context menu. 3219 * This field should be made private, so it is hidden from the SDK. 3220 * {@hide} 3221 */ 3222 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 3223 3224 private OnKeyListener mOnKeyListener; 3225 3226 private OnTouchListener mOnTouchListener; 3227 3228 private OnHoverListener mOnHoverListener; 3229 3230 private OnGenericMotionListener mOnGenericMotionListener; 3231 3232 private OnDragListener mOnDragListener; 3233 3234 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 3235 3236 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener; 3237 } 3238 3239 ListenerInfo mListenerInfo; 3240 3241 /** 3242 * The application environment this view lives in. 3243 * This field should be made private, so it is hidden from the SDK. 3244 * {@hide} 3245 */ 3246 protected Context mContext; 3247 3248 private final Resources mResources; 3249 3250 private ScrollabilityCache mScrollCache; 3251 3252 private int[] mDrawableState = null; 3253 3254 /** 3255 * Stores the outline of the view, passed down to the DisplayList level for 3256 * defining shadow shape. 3257 */ 3258 private Outline mOutline; 3259 3260 /** 3261 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 3262 * the user may specify which view to go to next. 3263 */ 3264 private int mNextFocusLeftId = View.NO_ID; 3265 3266 /** 3267 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 3268 * the user may specify which view to go to next. 3269 */ 3270 private int mNextFocusRightId = View.NO_ID; 3271 3272 /** 3273 * When this view has focus and the next focus is {@link #FOCUS_UP}, 3274 * the user may specify which view to go to next. 3275 */ 3276 private int mNextFocusUpId = View.NO_ID; 3277 3278 /** 3279 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 3280 * the user may specify which view to go to next. 3281 */ 3282 private int mNextFocusDownId = View.NO_ID; 3283 3284 /** 3285 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 3286 * the user may specify which view to go to next. 3287 */ 3288 int mNextFocusForwardId = View.NO_ID; 3289 3290 private CheckForLongPress mPendingCheckForLongPress; 3291 private CheckForTap mPendingCheckForTap = null; 3292 private PerformClick mPerformClick; 3293 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 3294 3295 private UnsetPressedState mUnsetPressedState; 3296 3297 /** 3298 * Whether the long press's action has been invoked. The tap's action is invoked on the 3299 * up event while a long press is invoked as soon as the long press duration is reached, so 3300 * a long press could be performed before the tap is checked, in which case the tap's action 3301 * should not be invoked. 3302 */ 3303 private boolean mHasPerformedLongPress; 3304 3305 /** 3306 * The minimum height of the view. We'll try our best to have the height 3307 * of this view to at least this amount. 3308 */ 3309 @ViewDebug.ExportedProperty(category = "measurement") 3310 private int mMinHeight; 3311 3312 /** 3313 * The minimum width of the view. We'll try our best to have the width 3314 * of this view to at least this amount. 3315 */ 3316 @ViewDebug.ExportedProperty(category = "measurement") 3317 private int mMinWidth; 3318 3319 /** 3320 * The delegate to handle touch events that are physically in this view 3321 * but should be handled by another view. 3322 */ 3323 private TouchDelegate mTouchDelegate = null; 3324 3325 /** 3326 * Solid color to use as a background when creating the drawing cache. Enables 3327 * the cache to use 16 bit bitmaps instead of 32 bit. 3328 */ 3329 private int mDrawingCacheBackgroundColor = 0; 3330 3331 /** 3332 * Special tree observer used when mAttachInfo is null. 3333 */ 3334 private ViewTreeObserver mFloatingTreeObserver; 3335 3336 /** 3337 * Cache the touch slop from the context that created the view. 3338 */ 3339 private int mTouchSlop; 3340 3341 /** 3342 * Object that handles automatic animation of view properties. 3343 */ 3344 private ViewPropertyAnimator mAnimator = null; 3345 3346 /** 3347 * Flag indicating that a drag can cross window boundaries. When 3348 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called 3349 * with this flag set, all visible applications will be able to participate 3350 * in the drag operation and receive the dragged content. 3351 * 3352 * @hide 3353 */ 3354 public static final int DRAG_FLAG_GLOBAL = 1; 3355 3356 /** 3357 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 3358 */ 3359 private float mVerticalScrollFactor; 3360 3361 /** 3362 * Position of the vertical scroll bar. 3363 */ 3364 private int mVerticalScrollbarPosition; 3365 3366 /** 3367 * Position the scroll bar at the default position as determined by the system. 3368 */ 3369 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 3370 3371 /** 3372 * Position the scroll bar along the left edge. 3373 */ 3374 public static final int SCROLLBAR_POSITION_LEFT = 1; 3375 3376 /** 3377 * Position the scroll bar along the right edge. 3378 */ 3379 public static final int SCROLLBAR_POSITION_RIGHT = 2; 3380 3381 /** 3382 * Indicates that the view does not have a layer. 3383 * 3384 * @see #getLayerType() 3385 * @see #setLayerType(int, android.graphics.Paint) 3386 * @see #LAYER_TYPE_SOFTWARE 3387 * @see #LAYER_TYPE_HARDWARE 3388 */ 3389 public static final int LAYER_TYPE_NONE = 0; 3390 3391 /** 3392 * <p>Indicates that the view has a software layer. A software layer is backed 3393 * by a bitmap and causes the view to be rendered using Android's software 3394 * rendering pipeline, even if hardware acceleration is enabled.</p> 3395 * 3396 * <p>Software layers have various usages:</p> 3397 * <p>When the application is not using hardware acceleration, a software layer 3398 * is useful to apply a specific color filter and/or blending mode and/or 3399 * translucency to a view and all its children.</p> 3400 * <p>When the application is using hardware acceleration, a software layer 3401 * is useful to render drawing primitives not supported by the hardware 3402 * accelerated pipeline. It can also be used to cache a complex view tree 3403 * into a texture and reduce the complexity of drawing operations. For instance, 3404 * when animating a complex view tree with a translation, a software layer can 3405 * be used to render the view tree only once.</p> 3406 * <p>Software layers should be avoided when the affected view tree updates 3407 * often. Every update will require to re-render the software layer, which can 3408 * potentially be slow (particularly when hardware acceleration is turned on 3409 * since the layer will have to be uploaded into a hardware texture after every 3410 * update.)</p> 3411 * 3412 * @see #getLayerType() 3413 * @see #setLayerType(int, android.graphics.Paint) 3414 * @see #LAYER_TYPE_NONE 3415 * @see #LAYER_TYPE_HARDWARE 3416 */ 3417 public static final int LAYER_TYPE_SOFTWARE = 1; 3418 3419 /** 3420 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 3421 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 3422 * OpenGL hardware) and causes the view to be rendered using Android's hardware 3423 * rendering pipeline, but only if hardware acceleration is turned on for the 3424 * view hierarchy. When hardware acceleration is turned off, hardware layers 3425 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 3426 * 3427 * <p>A hardware layer is useful to apply a specific color filter and/or 3428 * blending mode and/or translucency to a view and all its children.</p> 3429 * <p>A hardware layer can be used to cache a complex view tree into a 3430 * texture and reduce the complexity of drawing operations. For instance, 3431 * when animating a complex view tree with a translation, a hardware layer can 3432 * be used to render the view tree only once.</p> 3433 * <p>A hardware layer can also be used to increase the rendering quality when 3434 * rotation transformations are applied on a view. It can also be used to 3435 * prevent potential clipping issues when applying 3D transforms on a view.</p> 3436 * 3437 * @see #getLayerType() 3438 * @see #setLayerType(int, android.graphics.Paint) 3439 * @see #LAYER_TYPE_NONE 3440 * @see #LAYER_TYPE_SOFTWARE 3441 */ 3442 public static final int LAYER_TYPE_HARDWARE = 2; 3443 3444 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 3445 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 3446 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 3447 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 3448 }) 3449 int mLayerType = LAYER_TYPE_NONE; 3450 Paint mLayerPaint; 3451 Rect mLocalDirtyRect; 3452 private HardwareLayer mHardwareLayer; 3453 3454 /** 3455 * Set to true when drawing cache is enabled and cannot be created. 3456 * 3457 * @hide 3458 */ 3459 public boolean mCachingFailed; 3460 private Bitmap mDrawingCache; 3461 private Bitmap mUnscaledDrawingCache; 3462 3463 /** 3464 * RenderNode holding View properties, potentially holding a DisplayList of View content. 3465 * <p> 3466 * When non-null and valid, this is expected to contain an up-to-date copy 3467 * of the View content. Its DisplayList content is cleared on temporary detach and reset on 3468 * cleanup. 3469 */ 3470 final RenderNode mRenderNode; 3471 3472 /** 3473 * Set to true when the view is sending hover accessibility events because it 3474 * is the innermost hovered view. 3475 */ 3476 private boolean mSendingHoverAccessibilityEvents; 3477 3478 /** 3479 * Delegate for injecting accessibility functionality. 3480 */ 3481 AccessibilityDelegate mAccessibilityDelegate; 3482 3483 /** 3484 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 3485 * and add/remove objects to/from the overlay directly through the Overlay methods. 3486 */ 3487 ViewOverlay mOverlay; 3488 3489 /** 3490 * The currently active parent view for receiving delegated nested scrolling events. 3491 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared 3492 * by {@link #stopNestedScroll()} at the same point where we clear 3493 * requestDisallowInterceptTouchEvent. 3494 */ 3495 private ViewParent mNestedScrollingParent; 3496 3497 /** 3498 * Consistency verifier for debugging purposes. 3499 * @hide 3500 */ 3501 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 3502 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 3503 new InputEventConsistencyVerifier(this, 0) : null; 3504 3505 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 3506 3507 private int[] mTempNestedScrollConsumed; 3508 3509 /** 3510 * Simple constructor to use when creating a view from code. 3511 * 3512 * @param context The Context the view is running in, through which it can 3513 * access the current theme, resources, etc. 3514 */ 3515 public View(Context context) { 3516 mContext = context; 3517 mResources = context != null ? context.getResources() : null; 3518 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; 3519 // Set some flags defaults 3520 mPrivateFlags2 = 3521 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 3522 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 3523 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 3524 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 3525 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 3526 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 3527 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 3528 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 3529 mUserPaddingStart = UNDEFINED_PADDING; 3530 mUserPaddingEnd = UNDEFINED_PADDING; 3531 mRenderNode = RenderNode.create(getClass().getName()); 3532 3533 if (!sCompatibilityDone && context != null) { 3534 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 3535 3536 // Older apps may need this compatibility hack for measurement. 3537 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1; 3538 3539 // Older apps expect onMeasure() to always be called on a layout pass, regardless 3540 // of whether a layout was requested on that View. 3541 sIgnoreMeasureCache = targetSdkVersion < KITKAT; 3542 3543 // Older apps may need this to ignore the clip bounds 3544 sIgnoreClipBoundsForChildren = targetSdkVersion < L; 3545 3546 sCompatibilityDone = true; 3547 } 3548 } 3549 3550 /** 3551 * Constructor that is called when inflating a view from XML. This is called 3552 * when a view is being constructed from an XML file, supplying attributes 3553 * that were specified in the XML file. This version uses a default style of 3554 * 0, so the only attribute values applied are those in the Context's Theme 3555 * and the given AttributeSet. 3556 * 3557 * <p> 3558 * The method onFinishInflate() will be called after all children have been 3559 * added. 3560 * 3561 * @param context The Context the view is running in, through which it can 3562 * access the current theme, resources, etc. 3563 * @param attrs The attributes of the XML tag that is inflating the view. 3564 * @see #View(Context, AttributeSet, int) 3565 */ 3566 public View(Context context, AttributeSet attrs) { 3567 this(context, attrs, 0); 3568 } 3569 3570 /** 3571 * Perform inflation from XML and apply a class-specific base style from a 3572 * theme attribute. This constructor of View allows subclasses to use their 3573 * own base style when they are inflating. For example, a Button class's 3574 * constructor would call this version of the super class constructor and 3575 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this 3576 * allows the theme's button style to modify all of the base view attributes 3577 * (in particular its background) as well as the Button class's attributes. 3578 * 3579 * @param context The Context the view is running in, through which it can 3580 * access the current theme, resources, etc. 3581 * @param attrs The attributes of the XML tag that is inflating the view. 3582 * @param defStyleAttr An attribute in the current theme that contains a 3583 * reference to a style resource that supplies default values for 3584 * the view. Can be 0 to not look for defaults. 3585 * @see #View(Context, AttributeSet) 3586 */ 3587 public View(Context context, AttributeSet attrs, int defStyleAttr) { 3588 this(context, attrs, defStyleAttr, 0); 3589 } 3590 3591 /** 3592 * Perform inflation from XML and apply a class-specific base style from a 3593 * theme attribute or style resource. This constructor of View allows 3594 * subclasses to use their own base style when they are inflating. 3595 * <p> 3596 * When determining the final value of a particular attribute, there are 3597 * four inputs that come into play: 3598 * <ol> 3599 * <li>Any attribute values in the given AttributeSet. 3600 * <li>The style resource specified in the AttributeSet (named "style"). 3601 * <li>The default style specified by <var>defStyleAttr</var>. 3602 * <li>The default style specified by <var>defStyleRes</var>. 3603 * <li>The base values in this theme. 3604 * </ol> 3605 * <p> 3606 * Each of these inputs is considered in-order, with the first listed taking 3607 * precedence over the following ones. In other words, if in the 3608 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code> 3609 * , then the button's text will <em>always</em> be black, regardless of 3610 * what is specified in any of the styles. 3611 * 3612 * @param context The Context the view is running in, through which it can 3613 * access the current theme, resources, etc. 3614 * @param attrs The attributes of the XML tag that is inflating the view. 3615 * @param defStyleAttr An attribute in the current theme that contains a 3616 * reference to a style resource that supplies default values for 3617 * the view. Can be 0 to not look for defaults. 3618 * @param defStyleRes A resource identifier of a style resource that 3619 * supplies default values for the view, used only if 3620 * defStyleAttr is 0 or can not be found in the theme. Can be 0 3621 * to not look for defaults. 3622 * @see #View(Context, AttributeSet, int) 3623 */ 3624 public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 3625 this(context); 3626 3627 final TypedArray a = context.obtainStyledAttributes( 3628 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); 3629 3630 Drawable background = null; 3631 3632 int leftPadding = -1; 3633 int topPadding = -1; 3634 int rightPadding = -1; 3635 int bottomPadding = -1; 3636 int startPadding = UNDEFINED_PADDING; 3637 int endPadding = UNDEFINED_PADDING; 3638 3639 int padding = -1; 3640 3641 int viewFlagValues = 0; 3642 int viewFlagMasks = 0; 3643 3644 boolean setScrollContainer = false; 3645 3646 int x = 0; 3647 int y = 0; 3648 3649 float tx = 0; 3650 float ty = 0; 3651 float tz = 0; 3652 float rotation = 0; 3653 float rotationX = 0; 3654 float rotationY = 0; 3655 float sx = 1f; 3656 float sy = 1f; 3657 boolean transformSet = false; 3658 3659 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 3660 int overScrollMode = mOverScrollMode; 3661 boolean initializeScrollbars = false; 3662 3663 boolean startPaddingDefined = false; 3664 boolean endPaddingDefined = false; 3665 boolean leftPaddingDefined = false; 3666 boolean rightPaddingDefined = false; 3667 3668 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 3669 3670 final int N = a.getIndexCount(); 3671 for (int i = 0; i < N; i++) { 3672 int attr = a.getIndex(i); 3673 switch (attr) { 3674 case com.android.internal.R.styleable.View_background: 3675 background = a.getDrawable(attr); 3676 break; 3677 case com.android.internal.R.styleable.View_padding: 3678 padding = a.getDimensionPixelSize(attr, -1); 3679 mUserPaddingLeftInitial = padding; 3680 mUserPaddingRightInitial = padding; 3681 leftPaddingDefined = true; 3682 rightPaddingDefined = true; 3683 break; 3684 case com.android.internal.R.styleable.View_paddingLeft: 3685 leftPadding = a.getDimensionPixelSize(attr, -1); 3686 mUserPaddingLeftInitial = leftPadding; 3687 leftPaddingDefined = true; 3688 break; 3689 case com.android.internal.R.styleable.View_paddingTop: 3690 topPadding = a.getDimensionPixelSize(attr, -1); 3691 break; 3692 case com.android.internal.R.styleable.View_paddingRight: 3693 rightPadding = a.getDimensionPixelSize(attr, -1); 3694 mUserPaddingRightInitial = rightPadding; 3695 rightPaddingDefined = true; 3696 break; 3697 case com.android.internal.R.styleable.View_paddingBottom: 3698 bottomPadding = a.getDimensionPixelSize(attr, -1); 3699 break; 3700 case com.android.internal.R.styleable.View_paddingStart: 3701 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 3702 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 3703 break; 3704 case com.android.internal.R.styleable.View_paddingEnd: 3705 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 3706 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 3707 break; 3708 case com.android.internal.R.styleable.View_scrollX: 3709 x = a.getDimensionPixelOffset(attr, 0); 3710 break; 3711 case com.android.internal.R.styleable.View_scrollY: 3712 y = a.getDimensionPixelOffset(attr, 0); 3713 break; 3714 case com.android.internal.R.styleable.View_alpha: 3715 setAlpha(a.getFloat(attr, 1f)); 3716 break; 3717 case com.android.internal.R.styleable.View_transformPivotX: 3718 setPivotX(a.getDimensionPixelOffset(attr, 0)); 3719 break; 3720 case com.android.internal.R.styleable.View_transformPivotY: 3721 setPivotY(a.getDimensionPixelOffset(attr, 0)); 3722 break; 3723 case com.android.internal.R.styleable.View_translationX: 3724 tx = a.getDimensionPixelOffset(attr, 0); 3725 transformSet = true; 3726 break; 3727 case com.android.internal.R.styleable.View_translationY: 3728 ty = a.getDimensionPixelOffset(attr, 0); 3729 transformSet = true; 3730 break; 3731 case com.android.internal.R.styleable.View_translationZ: 3732 tz = a.getDimensionPixelOffset(attr, 0); 3733 transformSet = true; 3734 break; 3735 case com.android.internal.R.styleable.View_rotation: 3736 rotation = a.getFloat(attr, 0); 3737 transformSet = true; 3738 break; 3739 case com.android.internal.R.styleable.View_rotationX: 3740 rotationX = a.getFloat(attr, 0); 3741 transformSet = true; 3742 break; 3743 case com.android.internal.R.styleable.View_rotationY: 3744 rotationY = a.getFloat(attr, 0); 3745 transformSet = true; 3746 break; 3747 case com.android.internal.R.styleable.View_scaleX: 3748 sx = a.getFloat(attr, 1f); 3749 transformSet = true; 3750 break; 3751 case com.android.internal.R.styleable.View_scaleY: 3752 sy = a.getFloat(attr, 1f); 3753 transformSet = true; 3754 break; 3755 case com.android.internal.R.styleable.View_id: 3756 mID = a.getResourceId(attr, NO_ID); 3757 break; 3758 case com.android.internal.R.styleable.View_tag: 3759 mTag = a.getText(attr); 3760 break; 3761 case com.android.internal.R.styleable.View_fitsSystemWindows: 3762 if (a.getBoolean(attr, false)) { 3763 viewFlagValues |= FITS_SYSTEM_WINDOWS; 3764 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 3765 } 3766 break; 3767 case com.android.internal.R.styleable.View_focusable: 3768 if (a.getBoolean(attr, false)) { 3769 viewFlagValues |= FOCUSABLE; 3770 viewFlagMasks |= FOCUSABLE_MASK; 3771 } 3772 break; 3773 case com.android.internal.R.styleable.View_focusableInTouchMode: 3774 if (a.getBoolean(attr, false)) { 3775 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 3776 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 3777 } 3778 break; 3779 case com.android.internal.R.styleable.View_clickable: 3780 if (a.getBoolean(attr, false)) { 3781 viewFlagValues |= CLICKABLE; 3782 viewFlagMasks |= CLICKABLE; 3783 } 3784 break; 3785 case com.android.internal.R.styleable.View_longClickable: 3786 if (a.getBoolean(attr, false)) { 3787 viewFlagValues |= LONG_CLICKABLE; 3788 viewFlagMasks |= LONG_CLICKABLE; 3789 } 3790 break; 3791 case com.android.internal.R.styleable.View_saveEnabled: 3792 if (!a.getBoolean(attr, true)) { 3793 viewFlagValues |= SAVE_DISABLED; 3794 viewFlagMasks |= SAVE_DISABLED_MASK; 3795 } 3796 break; 3797 case com.android.internal.R.styleable.View_duplicateParentState: 3798 if (a.getBoolean(attr, false)) { 3799 viewFlagValues |= DUPLICATE_PARENT_STATE; 3800 viewFlagMasks |= DUPLICATE_PARENT_STATE; 3801 } 3802 break; 3803 case com.android.internal.R.styleable.View_visibility: 3804 final int visibility = a.getInt(attr, 0); 3805 if (visibility != 0) { 3806 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 3807 viewFlagMasks |= VISIBILITY_MASK; 3808 } 3809 break; 3810 case com.android.internal.R.styleable.View_layoutDirection: 3811 // Clear any layout direction flags (included resolved bits) already set 3812 mPrivateFlags2 &= 3813 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 3814 // Set the layout direction flags depending on the value of the attribute 3815 final int layoutDirection = a.getInt(attr, -1); 3816 final int value = (layoutDirection != -1) ? 3817 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 3818 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 3819 break; 3820 case com.android.internal.R.styleable.View_drawingCacheQuality: 3821 final int cacheQuality = a.getInt(attr, 0); 3822 if (cacheQuality != 0) { 3823 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 3824 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 3825 } 3826 break; 3827 case com.android.internal.R.styleable.View_contentDescription: 3828 setContentDescription(a.getString(attr)); 3829 break; 3830 case com.android.internal.R.styleable.View_labelFor: 3831 setLabelFor(a.getResourceId(attr, NO_ID)); 3832 break; 3833 case com.android.internal.R.styleable.View_soundEffectsEnabled: 3834 if (!a.getBoolean(attr, true)) { 3835 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 3836 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 3837 } 3838 break; 3839 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 3840 if (!a.getBoolean(attr, true)) { 3841 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 3842 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 3843 } 3844 break; 3845 case R.styleable.View_scrollbars: 3846 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 3847 if (scrollbars != SCROLLBARS_NONE) { 3848 viewFlagValues |= scrollbars; 3849 viewFlagMasks |= SCROLLBARS_MASK; 3850 initializeScrollbars = true; 3851 } 3852 break; 3853 //noinspection deprecation 3854 case R.styleable.View_fadingEdge: 3855 if (targetSdkVersion >= ICE_CREAM_SANDWICH) { 3856 // Ignore the attribute starting with ICS 3857 break; 3858 } 3859 // With builds < ICS, fall through and apply fading edges 3860 case R.styleable.View_requiresFadingEdge: 3861 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 3862 if (fadingEdge != FADING_EDGE_NONE) { 3863 viewFlagValues |= fadingEdge; 3864 viewFlagMasks |= FADING_EDGE_MASK; 3865 initializeFadingEdge(a); 3866 } 3867 break; 3868 case R.styleable.View_scrollbarStyle: 3869 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 3870 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 3871 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 3872 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 3873 } 3874 break; 3875 case R.styleable.View_isScrollContainer: 3876 setScrollContainer = true; 3877 if (a.getBoolean(attr, false)) { 3878 setScrollContainer(true); 3879 } 3880 break; 3881 case com.android.internal.R.styleable.View_keepScreenOn: 3882 if (a.getBoolean(attr, false)) { 3883 viewFlagValues |= KEEP_SCREEN_ON; 3884 viewFlagMasks |= KEEP_SCREEN_ON; 3885 } 3886 break; 3887 case R.styleable.View_filterTouchesWhenObscured: 3888 if (a.getBoolean(attr, false)) { 3889 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 3890 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 3891 } 3892 break; 3893 case R.styleable.View_nextFocusLeft: 3894 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 3895 break; 3896 case R.styleable.View_nextFocusRight: 3897 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 3898 break; 3899 case R.styleable.View_nextFocusUp: 3900 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 3901 break; 3902 case R.styleable.View_nextFocusDown: 3903 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 3904 break; 3905 case R.styleable.View_nextFocusForward: 3906 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 3907 break; 3908 case R.styleable.View_minWidth: 3909 mMinWidth = a.getDimensionPixelSize(attr, 0); 3910 break; 3911 case R.styleable.View_minHeight: 3912 mMinHeight = a.getDimensionPixelSize(attr, 0); 3913 break; 3914 case R.styleable.View_onClick: 3915 if (context.isRestricted()) { 3916 throw new IllegalStateException("The android:onClick attribute cannot " 3917 + "be used within a restricted context"); 3918 } 3919 3920 final String handlerName = a.getString(attr); 3921 if (handlerName != null) { 3922 setOnClickListener(new OnClickListener() { 3923 private Method mHandler; 3924 3925 public void onClick(View v) { 3926 if (mHandler == null) { 3927 try { 3928 mHandler = getContext().getClass().getMethod(handlerName, 3929 View.class); 3930 } catch (NoSuchMethodException e) { 3931 int id = getId(); 3932 String idText = id == NO_ID ? "" : " with id '" 3933 + getContext().getResources().getResourceEntryName( 3934 id) + "'"; 3935 throw new IllegalStateException("Could not find a method " + 3936 handlerName + "(View) in the activity " 3937 + getContext().getClass() + " for onClick handler" 3938 + " on view " + View.this.getClass() + idText, e); 3939 } 3940 } 3941 3942 try { 3943 mHandler.invoke(getContext(), View.this); 3944 } catch (IllegalAccessException e) { 3945 throw new IllegalStateException("Could not execute non " 3946 + "public method of the activity", e); 3947 } catch (InvocationTargetException e) { 3948 throw new IllegalStateException("Could not execute " 3949 + "method of the activity", e); 3950 } 3951 } 3952 }); 3953 } 3954 break; 3955 case R.styleable.View_overScrollMode: 3956 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 3957 break; 3958 case R.styleable.View_verticalScrollbarPosition: 3959 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 3960 break; 3961 case R.styleable.View_layerType: 3962 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 3963 break; 3964 case R.styleable.View_textDirection: 3965 // Clear any text direction flag already set 3966 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 3967 // Set the text direction flags depending on the value of the attribute 3968 final int textDirection = a.getInt(attr, -1); 3969 if (textDirection != -1) { 3970 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 3971 } 3972 break; 3973 case R.styleable.View_textAlignment: 3974 // Clear any text alignment flag already set 3975 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 3976 // Set the text alignment flag depending on the value of the attribute 3977 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 3978 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 3979 break; 3980 case R.styleable.View_importantForAccessibility: 3981 setImportantForAccessibility(a.getInt(attr, 3982 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 3983 break; 3984 case R.styleable.View_accessibilityLiveRegion: 3985 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 3986 break; 3987 case R.styleable.View_sharedElementName: 3988 setSharedElementName(a.getString(attr)); 3989 break; 3990 case R.styleable.View_nestedScrollingEnabled: 3991 setNestedScrollingEnabled(a.getBoolean(attr, false)); 3992 break; 3993 } 3994 } 3995 3996 setOverScrollMode(overScrollMode); 3997 3998 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 3999 // the resolved layout direction). Those cached values will be used later during padding 4000 // resolution. 4001 mUserPaddingStart = startPadding; 4002 mUserPaddingEnd = endPadding; 4003 4004 if (background != null) { 4005 setBackground(background); 4006 } 4007 4008 // setBackground above will record that padding is currently provided by the background. 4009 // If we have padding specified via xml, record that here instead and use it. 4010 mLeftPaddingDefined = leftPaddingDefined; 4011 mRightPaddingDefined = rightPaddingDefined; 4012 4013 if (padding >= 0) { 4014 leftPadding = padding; 4015 topPadding = padding; 4016 rightPadding = padding; 4017 bottomPadding = padding; 4018 mUserPaddingLeftInitial = padding; 4019 mUserPaddingRightInitial = padding; 4020 } 4021 4022 if (isRtlCompatibilityMode()) { 4023 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 4024 // left / right padding are used if defined (meaning here nothing to do). If they are not 4025 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 4026 // start / end and resolve them as left / right (layout direction is not taken into account). 4027 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4028 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4029 // defined. 4030 if (!mLeftPaddingDefined && startPaddingDefined) { 4031 leftPadding = startPadding; 4032 } 4033 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 4034 if (!mRightPaddingDefined && endPaddingDefined) { 4035 rightPadding = endPadding; 4036 } 4037 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 4038 } else { 4039 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 4040 // values defined. Otherwise, left /right values are used. 4041 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4042 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4043 // defined. 4044 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 4045 4046 if (mLeftPaddingDefined && !hasRelativePadding) { 4047 mUserPaddingLeftInitial = leftPadding; 4048 } 4049 if (mRightPaddingDefined && !hasRelativePadding) { 4050 mUserPaddingRightInitial = rightPadding; 4051 } 4052 } 4053 4054 internalSetPadding( 4055 mUserPaddingLeftInitial, 4056 topPadding >= 0 ? topPadding : mPaddingTop, 4057 mUserPaddingRightInitial, 4058 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 4059 4060 if (viewFlagMasks != 0) { 4061 setFlags(viewFlagValues, viewFlagMasks); 4062 } 4063 4064 if (initializeScrollbars) { 4065 initializeScrollbars(a); 4066 } 4067 4068 a.recycle(); 4069 4070 // Needs to be called after mViewFlags is set 4071 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4072 recomputePadding(); 4073 } 4074 4075 if (x != 0 || y != 0) { 4076 scrollTo(x, y); 4077 } 4078 4079 if (transformSet) { 4080 setTranslationX(tx); 4081 setTranslationY(ty); 4082 setTranslationZ(tz); 4083 setRotation(rotation); 4084 setRotationX(rotationX); 4085 setRotationY(rotationY); 4086 setScaleX(sx); 4087 setScaleY(sy); 4088 } 4089 4090 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 4091 setScrollContainer(true); 4092 } 4093 4094 computeOpaqueFlags(); 4095 } 4096 4097 /** 4098 * Non-public constructor for use in testing 4099 */ 4100 View() { 4101 mResources = null; 4102 mRenderNode = RenderNode.create(getClass().getName()); 4103 } 4104 4105 public String toString() { 4106 StringBuilder out = new StringBuilder(128); 4107 out.append(getClass().getName()); 4108 out.append('{'); 4109 out.append(Integer.toHexString(System.identityHashCode(this))); 4110 out.append(' '); 4111 switch (mViewFlags&VISIBILITY_MASK) { 4112 case VISIBLE: out.append('V'); break; 4113 case INVISIBLE: out.append('I'); break; 4114 case GONE: out.append('G'); break; 4115 default: out.append('.'); break; 4116 } 4117 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.'); 4118 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 4119 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 4120 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 4121 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 4122 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 4123 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 4124 out.append(' '); 4125 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 4126 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 4127 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 4128 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 4129 out.append('p'); 4130 } else { 4131 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 4132 } 4133 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 4134 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 4135 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 4136 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 4137 out.append(' '); 4138 out.append(mLeft); 4139 out.append(','); 4140 out.append(mTop); 4141 out.append('-'); 4142 out.append(mRight); 4143 out.append(','); 4144 out.append(mBottom); 4145 final int id = getId(); 4146 if (id != NO_ID) { 4147 out.append(" #"); 4148 out.append(Integer.toHexString(id)); 4149 final Resources r = mResources; 4150 if (Resources.resourceHasPackage(id) && r != null) { 4151 try { 4152 String pkgname; 4153 switch (id&0xff000000) { 4154 case 0x7f000000: 4155 pkgname="app"; 4156 break; 4157 case 0x01000000: 4158 pkgname="android"; 4159 break; 4160 default: 4161 pkgname = r.getResourcePackageName(id); 4162 break; 4163 } 4164 String typename = r.getResourceTypeName(id); 4165 String entryname = r.getResourceEntryName(id); 4166 out.append(" "); 4167 out.append(pkgname); 4168 out.append(":"); 4169 out.append(typename); 4170 out.append("/"); 4171 out.append(entryname); 4172 } catch (Resources.NotFoundException e) { 4173 } 4174 } 4175 } 4176 out.append("}"); 4177 return out.toString(); 4178 } 4179 4180 /** 4181 * <p> 4182 * Initializes the fading edges from a given set of styled attributes. This 4183 * method should be called by subclasses that need fading edges and when an 4184 * instance of these subclasses is created programmatically rather than 4185 * being inflated from XML. This method is automatically called when the XML 4186 * is inflated. 4187 * </p> 4188 * 4189 * @param a the styled attributes set to initialize the fading edges from 4190 */ 4191 protected void initializeFadingEdge(TypedArray a) { 4192 initScrollCache(); 4193 4194 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 4195 R.styleable.View_fadingEdgeLength, 4196 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 4197 } 4198 4199 /** 4200 * Returns the size of the vertical faded edges used to indicate that more 4201 * content in this view is visible. 4202 * 4203 * @return The size in pixels of the vertical faded edge or 0 if vertical 4204 * faded edges are not enabled for this view. 4205 * @attr ref android.R.styleable#View_fadingEdgeLength 4206 */ 4207 public int getVerticalFadingEdgeLength() { 4208 if (isVerticalFadingEdgeEnabled()) { 4209 ScrollabilityCache cache = mScrollCache; 4210 if (cache != null) { 4211 return cache.fadingEdgeLength; 4212 } 4213 } 4214 return 0; 4215 } 4216 4217 /** 4218 * Set the size of the faded edge used to indicate that more content in this 4219 * view is available. Will not change whether the fading edge is enabled; use 4220 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 4221 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 4222 * for the vertical or horizontal fading edges. 4223 * 4224 * @param length The size in pixels of the faded edge used to indicate that more 4225 * content in this view is visible. 4226 */ 4227 public void setFadingEdgeLength(int length) { 4228 initScrollCache(); 4229 mScrollCache.fadingEdgeLength = length; 4230 } 4231 4232 /** 4233 * Returns the size of the horizontal faded edges used to indicate that more 4234 * content in this view is visible. 4235 * 4236 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 4237 * faded edges are not enabled for this view. 4238 * @attr ref android.R.styleable#View_fadingEdgeLength 4239 */ 4240 public int getHorizontalFadingEdgeLength() { 4241 if (isHorizontalFadingEdgeEnabled()) { 4242 ScrollabilityCache cache = mScrollCache; 4243 if (cache != null) { 4244 return cache.fadingEdgeLength; 4245 } 4246 } 4247 return 0; 4248 } 4249 4250 /** 4251 * Returns the width of the vertical scrollbar. 4252 * 4253 * @return The width in pixels of the vertical scrollbar or 0 if there 4254 * is no vertical scrollbar. 4255 */ 4256 public int getVerticalScrollbarWidth() { 4257 ScrollabilityCache cache = mScrollCache; 4258 if (cache != null) { 4259 ScrollBarDrawable scrollBar = cache.scrollBar; 4260 if (scrollBar != null) { 4261 int size = scrollBar.getSize(true); 4262 if (size <= 0) { 4263 size = cache.scrollBarSize; 4264 } 4265 return size; 4266 } 4267 return 0; 4268 } 4269 return 0; 4270 } 4271 4272 /** 4273 * Returns the height of the horizontal scrollbar. 4274 * 4275 * @return The height in pixels of the horizontal scrollbar or 0 if 4276 * there is no horizontal scrollbar. 4277 */ 4278 protected int getHorizontalScrollbarHeight() { 4279 ScrollabilityCache cache = mScrollCache; 4280 if (cache != null) { 4281 ScrollBarDrawable scrollBar = cache.scrollBar; 4282 if (scrollBar != null) { 4283 int size = scrollBar.getSize(false); 4284 if (size <= 0) { 4285 size = cache.scrollBarSize; 4286 } 4287 return size; 4288 } 4289 return 0; 4290 } 4291 return 0; 4292 } 4293 4294 /** 4295 * <p> 4296 * Initializes the scrollbars from a given set of styled attributes. This 4297 * method should be called by subclasses that need scrollbars and when an 4298 * instance of these subclasses is created programmatically rather than 4299 * being inflated from XML. This method is automatically called when the XML 4300 * is inflated. 4301 * </p> 4302 * 4303 * @param a the styled attributes set to initialize the scrollbars from 4304 */ 4305 protected void initializeScrollbars(TypedArray a) { 4306 initScrollCache(); 4307 4308 final ScrollabilityCache scrollabilityCache = mScrollCache; 4309 4310 if (scrollabilityCache.scrollBar == null) { 4311 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 4312 } 4313 4314 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 4315 4316 if (!fadeScrollbars) { 4317 scrollabilityCache.state = ScrollabilityCache.ON; 4318 } 4319 scrollabilityCache.fadeScrollBars = fadeScrollbars; 4320 4321 4322 scrollabilityCache.scrollBarFadeDuration = a.getInt( 4323 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 4324 .getScrollBarFadeDuration()); 4325 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 4326 R.styleable.View_scrollbarDefaultDelayBeforeFade, 4327 ViewConfiguration.getScrollDefaultDelay()); 4328 4329 4330 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 4331 com.android.internal.R.styleable.View_scrollbarSize, 4332 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 4333 4334 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 4335 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 4336 4337 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 4338 if (thumb != null) { 4339 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 4340 } 4341 4342 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 4343 false); 4344 if (alwaysDraw) { 4345 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 4346 } 4347 4348 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 4349 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 4350 4351 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 4352 if (thumb != null) { 4353 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 4354 } 4355 4356 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 4357 false); 4358 if (alwaysDraw) { 4359 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 4360 } 4361 4362 // Apply layout direction to the new Drawables if needed 4363 final int layoutDirection = getLayoutDirection(); 4364 if (track != null) { 4365 track.setLayoutDirection(layoutDirection); 4366 } 4367 if (thumb != null) { 4368 thumb.setLayoutDirection(layoutDirection); 4369 } 4370 4371 // Re-apply user/background padding so that scrollbar(s) get added 4372 resolvePadding(); 4373 } 4374 4375 /** 4376 * <p> 4377 * Initalizes the scrollability cache if necessary. 4378 * </p> 4379 */ 4380 private void initScrollCache() { 4381 if (mScrollCache == null) { 4382 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 4383 } 4384 } 4385 4386 private ScrollabilityCache getScrollCache() { 4387 initScrollCache(); 4388 return mScrollCache; 4389 } 4390 4391 /** 4392 * Set the position of the vertical scroll bar. Should be one of 4393 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 4394 * {@link #SCROLLBAR_POSITION_RIGHT}. 4395 * 4396 * @param position Where the vertical scroll bar should be positioned. 4397 */ 4398 public void setVerticalScrollbarPosition(int position) { 4399 if (mVerticalScrollbarPosition != position) { 4400 mVerticalScrollbarPosition = position; 4401 computeOpaqueFlags(); 4402 resolvePadding(); 4403 } 4404 } 4405 4406 /** 4407 * @return The position where the vertical scroll bar will show, if applicable. 4408 * @see #setVerticalScrollbarPosition(int) 4409 */ 4410 public int getVerticalScrollbarPosition() { 4411 return mVerticalScrollbarPosition; 4412 } 4413 4414 ListenerInfo getListenerInfo() { 4415 if (mListenerInfo != null) { 4416 return mListenerInfo; 4417 } 4418 mListenerInfo = new ListenerInfo(); 4419 return mListenerInfo; 4420 } 4421 4422 /** 4423 * Register a callback to be invoked when focus of this view changed. 4424 * 4425 * @param l The callback that will run. 4426 */ 4427 public void setOnFocusChangeListener(OnFocusChangeListener l) { 4428 getListenerInfo().mOnFocusChangeListener = l; 4429 } 4430 4431 /** 4432 * Add a listener that will be called when the bounds of the view change due to 4433 * layout processing. 4434 * 4435 * @param listener The listener that will be called when layout bounds change. 4436 */ 4437 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 4438 ListenerInfo li = getListenerInfo(); 4439 if (li.mOnLayoutChangeListeners == null) { 4440 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 4441 } 4442 if (!li.mOnLayoutChangeListeners.contains(listener)) { 4443 li.mOnLayoutChangeListeners.add(listener); 4444 } 4445 } 4446 4447 /** 4448 * Remove a listener for layout changes. 4449 * 4450 * @param listener The listener for layout bounds change. 4451 */ 4452 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 4453 ListenerInfo li = mListenerInfo; 4454 if (li == null || li.mOnLayoutChangeListeners == null) { 4455 return; 4456 } 4457 li.mOnLayoutChangeListeners.remove(listener); 4458 } 4459 4460 /** 4461 * Add a listener for attach state changes. 4462 * 4463 * This listener will be called whenever this view is attached or detached 4464 * from a window. Remove the listener using 4465 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 4466 * 4467 * @param listener Listener to attach 4468 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 4469 */ 4470 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 4471 ListenerInfo li = getListenerInfo(); 4472 if (li.mOnAttachStateChangeListeners == null) { 4473 li.mOnAttachStateChangeListeners 4474 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 4475 } 4476 li.mOnAttachStateChangeListeners.add(listener); 4477 } 4478 4479 /** 4480 * Remove a listener for attach state changes. The listener will receive no further 4481 * notification of window attach/detach events. 4482 * 4483 * @param listener Listener to remove 4484 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 4485 */ 4486 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 4487 ListenerInfo li = mListenerInfo; 4488 if (li == null || li.mOnAttachStateChangeListeners == null) { 4489 return; 4490 } 4491 li.mOnAttachStateChangeListeners.remove(listener); 4492 } 4493 4494 /** 4495 * Returns the focus-change callback registered for this view. 4496 * 4497 * @return The callback, or null if one is not registered. 4498 */ 4499 public OnFocusChangeListener getOnFocusChangeListener() { 4500 ListenerInfo li = mListenerInfo; 4501 return li != null ? li.mOnFocusChangeListener : null; 4502 } 4503 4504 /** 4505 * Register a callback to be invoked when this view is clicked. If this view is not 4506 * clickable, it becomes clickable. 4507 * 4508 * @param l The callback that will run 4509 * 4510 * @see #setClickable(boolean) 4511 */ 4512 public void setOnClickListener(OnClickListener l) { 4513 if (!isClickable()) { 4514 setClickable(true); 4515 } 4516 getListenerInfo().mOnClickListener = l; 4517 } 4518 4519 /** 4520 * Return whether this view has an attached OnClickListener. Returns 4521 * true if there is a listener, false if there is none. 4522 */ 4523 public boolean hasOnClickListeners() { 4524 ListenerInfo li = mListenerInfo; 4525 return (li != null && li.mOnClickListener != null); 4526 } 4527 4528 /** 4529 * Register a callback to be invoked when this view is clicked and held. If this view is not 4530 * long clickable, it becomes long clickable. 4531 * 4532 * @param l The callback that will run 4533 * 4534 * @see #setLongClickable(boolean) 4535 */ 4536 public void setOnLongClickListener(OnLongClickListener l) { 4537 if (!isLongClickable()) { 4538 setLongClickable(true); 4539 } 4540 getListenerInfo().mOnLongClickListener = l; 4541 } 4542 4543 /** 4544 * Register a callback to be invoked when the context menu for this view is 4545 * being built. If this view is not long clickable, it becomes long clickable. 4546 * 4547 * @param l The callback that will run 4548 * 4549 */ 4550 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 4551 if (!isLongClickable()) { 4552 setLongClickable(true); 4553 } 4554 getListenerInfo().mOnCreateContextMenuListener = l; 4555 } 4556 4557 /** 4558 * Call this view's OnClickListener, if it is defined. Performs all normal 4559 * actions associated with clicking: reporting accessibility event, playing 4560 * a sound, etc. 4561 * 4562 * @return True there was an assigned OnClickListener that was called, false 4563 * otherwise is returned. 4564 */ 4565 public boolean performClick() { 4566 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 4567 4568 ListenerInfo li = mListenerInfo; 4569 if (li != null && li.mOnClickListener != null) { 4570 playSoundEffect(SoundEffectConstants.CLICK); 4571 li.mOnClickListener.onClick(this); 4572 return true; 4573 } 4574 4575 return false; 4576 } 4577 4578 /** 4579 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 4580 * this only calls the listener, and does not do any associated clicking 4581 * actions like reporting an accessibility event. 4582 * 4583 * @return True there was an assigned OnClickListener that was called, false 4584 * otherwise is returned. 4585 */ 4586 public boolean callOnClick() { 4587 ListenerInfo li = mListenerInfo; 4588 if (li != null && li.mOnClickListener != null) { 4589 li.mOnClickListener.onClick(this); 4590 return true; 4591 } 4592 return false; 4593 } 4594 4595 /** 4596 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the 4597 * OnLongClickListener did not consume the event. 4598 * 4599 * @return True if one of the above receivers consumed the event, false otherwise. 4600 */ 4601 public boolean performLongClick() { 4602 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 4603 4604 boolean handled = false; 4605 ListenerInfo li = mListenerInfo; 4606 if (li != null && li.mOnLongClickListener != null) { 4607 handled = li.mOnLongClickListener.onLongClick(View.this); 4608 } 4609 if (!handled) { 4610 handled = showContextMenu(); 4611 } 4612 if (handled) { 4613 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 4614 } 4615 return handled; 4616 } 4617 4618 /** 4619 * Performs button-related actions during a touch down event. 4620 * 4621 * @param event The event. 4622 * @return True if the down was consumed. 4623 * 4624 * @hide 4625 */ 4626 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 4627 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 4628 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) { 4629 return true; 4630 } 4631 } 4632 return false; 4633 } 4634 4635 /** 4636 * Bring up the context menu for this view. 4637 * 4638 * @return Whether a context menu was displayed. 4639 */ 4640 public boolean showContextMenu() { 4641 return getParent().showContextMenuForChild(this); 4642 } 4643 4644 /** 4645 * Bring up the context menu for this view, referring to the item under the specified point. 4646 * 4647 * @param x The referenced x coordinate. 4648 * @param y The referenced y coordinate. 4649 * @param metaState The keyboard modifiers that were pressed. 4650 * @return Whether a context menu was displayed. 4651 * 4652 * @hide 4653 */ 4654 public boolean showContextMenu(float x, float y, int metaState) { 4655 return showContextMenu(); 4656 } 4657 4658 /** 4659 * Start an action mode. 4660 * 4661 * @param callback Callback that will control the lifecycle of the action mode 4662 * @return The new action mode if it is started, null otherwise 4663 * 4664 * @see ActionMode 4665 */ 4666 public ActionMode startActionMode(ActionMode.Callback callback) { 4667 ViewParent parent = getParent(); 4668 if (parent == null) return null; 4669 return parent.startActionModeForChild(this, callback); 4670 } 4671 4672 /** 4673 * Register a callback to be invoked when a hardware key is pressed in this view. 4674 * Key presses in software input methods will generally not trigger the methods of 4675 * this listener. 4676 * @param l the key listener to attach to this view 4677 */ 4678 public void setOnKeyListener(OnKeyListener l) { 4679 getListenerInfo().mOnKeyListener = l; 4680 } 4681 4682 /** 4683 * Register a callback to be invoked when a touch event is sent to this view. 4684 * @param l the touch listener to attach to this view 4685 */ 4686 public void setOnTouchListener(OnTouchListener l) { 4687 getListenerInfo().mOnTouchListener = l; 4688 } 4689 4690 /** 4691 * Register a callback to be invoked when a generic motion event is sent to this view. 4692 * @param l the generic motion listener to attach to this view 4693 */ 4694 public void setOnGenericMotionListener(OnGenericMotionListener l) { 4695 getListenerInfo().mOnGenericMotionListener = l; 4696 } 4697 4698 /** 4699 * Register a callback to be invoked when a hover event is sent to this view. 4700 * @param l the hover listener to attach to this view 4701 */ 4702 public void setOnHoverListener(OnHoverListener l) { 4703 getListenerInfo().mOnHoverListener = l; 4704 } 4705 4706 /** 4707 * Register a drag event listener callback object for this View. The parameter is 4708 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 4709 * View, the system calls the 4710 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 4711 * @param l An implementation of {@link android.view.View.OnDragListener}. 4712 */ 4713 public void setOnDragListener(OnDragListener l) { 4714 getListenerInfo().mOnDragListener = l; 4715 } 4716 4717 /** 4718 * Give this view focus. This will cause 4719 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 4720 * 4721 * Note: this does not check whether this {@link View} should get focus, it just 4722 * gives it focus no matter what. It should only be called internally by framework 4723 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 4724 * 4725 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 4726 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 4727 * focus moved when requestFocus() is called. It may not always 4728 * apply, in which case use the default View.FOCUS_DOWN. 4729 * @param previouslyFocusedRect The rectangle of the view that had focus 4730 * prior in this View's coordinate system. 4731 */ 4732 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) { 4733 if (DBG) { 4734 System.out.println(this + " requestFocus()"); 4735 } 4736 4737 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 4738 mPrivateFlags |= PFLAG_FOCUSED; 4739 4740 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 4741 4742 if (mParent != null) { 4743 mParent.requestChildFocus(this, this); 4744 } 4745 4746 if (mAttachInfo != null) { 4747 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 4748 } 4749 4750 manageFocusHotspot(true, oldFocus); 4751 onFocusChanged(true, direction, previouslyFocusedRect); 4752 refreshDrawableState(); 4753 } 4754 } 4755 4756 /** 4757 * Forwards focus information to the background drawable, if necessary. When 4758 * the view is gaining focus, <code>v</code> is the previous focus holder. 4759 * When the view is losing focus, <code>v</code> is the next focus holder. 4760 * 4761 * @param focused whether this view is focused 4762 * @param v previous or the next focus holder, or null if none 4763 */ 4764 private void manageFocusHotspot(boolean focused, View v) { 4765 if (mBackground != null && mBackground.supportsHotspots()) { 4766 final Rect r = new Rect(); 4767 if (!focused && v != null) { 4768 v.getBoundsOnScreen(r); 4769 final int[] location = new int[2]; 4770 getLocationOnScreen(location); 4771 r.offset(-location[0], -location[1]); 4772 } else { 4773 r.set(0, 0, mRight - mLeft, mBottom - mTop); 4774 } 4775 4776 final float x = r.exactCenterX(); 4777 final float y = r.exactCenterY(); 4778 mBackground.setHotspot(R.attr.state_focused, x, y); 4779 4780 if (!focused) { 4781 mBackground.removeHotspot(R.attr.state_focused); 4782 } 4783 } 4784 } 4785 4786 /** 4787 * Request that a rectangle of this view be visible on the screen, 4788 * scrolling if necessary just enough. 4789 * 4790 * <p>A View should call this if it maintains some notion of which part 4791 * of its content is interesting. For example, a text editing view 4792 * should call this when its cursor moves. 4793 * 4794 * @param rectangle The rectangle. 4795 * @return Whether any parent scrolled. 4796 */ 4797 public boolean requestRectangleOnScreen(Rect rectangle) { 4798 return requestRectangleOnScreen(rectangle, false); 4799 } 4800 4801 /** 4802 * Request that a rectangle of this view be visible on the screen, 4803 * scrolling if necessary just enough. 4804 * 4805 * <p>A View should call this if it maintains some notion of which part 4806 * of its content is interesting. For example, a text editing view 4807 * should call this when its cursor moves. 4808 * 4809 * <p>When <code>immediate</code> is set to true, scrolling will not be 4810 * animated. 4811 * 4812 * @param rectangle The rectangle. 4813 * @param immediate True to forbid animated scrolling, false otherwise 4814 * @return Whether any parent scrolled. 4815 */ 4816 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 4817 if (mParent == null) { 4818 return false; 4819 } 4820 4821 View child = this; 4822 4823 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 4824 position.set(rectangle); 4825 4826 ViewParent parent = mParent; 4827 boolean scrolled = false; 4828 while (parent != null) { 4829 rectangle.set((int) position.left, (int) position.top, 4830 (int) position.right, (int) position.bottom); 4831 4832 scrolled |= parent.requestChildRectangleOnScreen(child, 4833 rectangle, immediate); 4834 4835 if (!child.hasIdentityMatrix()) { 4836 child.getMatrix().mapRect(position); 4837 } 4838 4839 position.offset(child.mLeft, child.mTop); 4840 4841 if (!(parent instanceof View)) { 4842 break; 4843 } 4844 4845 View parentView = (View) parent; 4846 4847 position.offset(-parentView.getScrollX(), -parentView.getScrollY()); 4848 4849 child = parentView; 4850 parent = child.getParent(); 4851 } 4852 4853 return scrolled; 4854 } 4855 4856 /** 4857 * Called when this view wants to give up focus. If focus is cleared 4858 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 4859 * <p> 4860 * <strong>Note:</strong> When a View clears focus the framework is trying 4861 * to give focus to the first focusable View from the top. Hence, if this 4862 * View is the first from the top that can take focus, then all callbacks 4863 * related to clearing focus will be invoked after wich the framework will 4864 * give focus to this view. 4865 * </p> 4866 */ 4867 public void clearFocus() { 4868 if (DBG) { 4869 System.out.println(this + " clearFocus()"); 4870 } 4871 4872 clearFocusInternal(null, true, true); 4873 } 4874 4875 /** 4876 * Clears focus from the view, optionally propagating the change up through 4877 * the parent hierarchy and requesting that the root view place new focus. 4878 * 4879 * @param propagate whether to propagate the change up through the parent 4880 * hierarchy 4881 * @param refocus when propagate is true, specifies whether to request the 4882 * root view place new focus 4883 */ 4884 void clearFocusInternal(View focused, boolean propagate, boolean refocus) { 4885 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 4886 mPrivateFlags &= ~PFLAG_FOCUSED; 4887 4888 if (propagate && mParent != null) { 4889 mParent.clearChildFocus(this); 4890 } 4891 4892 onFocusChanged(false, 0, null); 4893 4894 manageFocusHotspot(false, focused); 4895 refreshDrawableState(); 4896 4897 if (propagate && (!refocus || !rootViewRequestFocus())) { 4898 notifyGlobalFocusCleared(this); 4899 } 4900 } 4901 } 4902 4903 void notifyGlobalFocusCleared(View oldFocus) { 4904 if (oldFocus != null && mAttachInfo != null) { 4905 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 4906 } 4907 } 4908 4909 boolean rootViewRequestFocus() { 4910 final View root = getRootView(); 4911 return root != null && root.requestFocus(); 4912 } 4913 4914 /** 4915 * Called internally by the view system when a new view is getting focus. 4916 * This is what clears the old focus. 4917 * <p> 4918 * <b>NOTE:</b> The parent view's focused child must be updated manually 4919 * after calling this method. Otherwise, the view hierarchy may be left in 4920 * an inconstent state. 4921 */ 4922 void unFocus(View focused) { 4923 if (DBG) { 4924 System.out.println(this + " unFocus()"); 4925 } 4926 4927 clearFocusInternal(focused, false, false); 4928 } 4929 4930 /** 4931 * Returns true if this view has focus iteself, or is the ancestor of the 4932 * view that has focus. 4933 * 4934 * @return True if this view has or contains focus, false otherwise. 4935 */ 4936 @ViewDebug.ExportedProperty(category = "focus") 4937 public boolean hasFocus() { 4938 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 4939 } 4940 4941 /** 4942 * Returns true if this view is focusable or if it contains a reachable View 4943 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 4944 * is a View whose parents do not block descendants focus. 4945 * 4946 * Only {@link #VISIBLE} views are considered focusable. 4947 * 4948 * @return True if the view is focusable or if the view contains a focusable 4949 * View, false otherwise. 4950 * 4951 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 4952 */ 4953 public boolean hasFocusable() { 4954 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 4955 } 4956 4957 /** 4958 * Called by the view system when the focus state of this view changes. 4959 * When the focus change event is caused by directional navigation, direction 4960 * and previouslyFocusedRect provide insight into where the focus is coming from. 4961 * When overriding, be sure to call up through to the super class so that 4962 * the standard focus handling will occur. 4963 * 4964 * @param gainFocus True if the View has focus; false otherwise. 4965 * @param direction The direction focus has moved when requestFocus() 4966 * is called to give this view focus. Values are 4967 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 4968 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 4969 * It may not always apply, in which case use the default. 4970 * @param previouslyFocusedRect The rectangle, in this view's coordinate 4971 * system, of the previously focused view. If applicable, this will be 4972 * passed in as finer grained information about where the focus is coming 4973 * from (in addition to direction). Will be <code>null</code> otherwise. 4974 */ 4975 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, 4976 @Nullable Rect previouslyFocusedRect) { 4977 if (gainFocus) { 4978 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 4979 } else { 4980 notifyViewAccessibilityStateChangedIfNeeded( 4981 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 4982 } 4983 4984 InputMethodManager imm = InputMethodManager.peekInstance(); 4985 if (!gainFocus) { 4986 if (isPressed()) { 4987 setPressed(false); 4988 } 4989 if (imm != null && mAttachInfo != null 4990 && mAttachInfo.mHasWindowFocus) { 4991 imm.focusOut(this); 4992 } 4993 onFocusLost(); 4994 } else if (imm != null && mAttachInfo != null 4995 && mAttachInfo.mHasWindowFocus) { 4996 imm.focusIn(this); 4997 } 4998 4999 invalidate(true); 5000 ListenerInfo li = mListenerInfo; 5001 if (li != null && li.mOnFocusChangeListener != null) { 5002 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 5003 } 5004 5005 if (mAttachInfo != null) { 5006 mAttachInfo.mKeyDispatchState.reset(this); 5007 } 5008 } 5009 5010 /** 5011 * Sends an accessibility event of the given type. If accessibility is 5012 * not enabled this method has no effect. The default implementation calls 5013 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 5014 * to populate information about the event source (this View), then calls 5015 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 5016 * populate the text content of the event source including its descendants, 5017 * and last calls 5018 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 5019 * on its parent to resuest sending of the event to interested parties. 5020 * <p> 5021 * If an {@link AccessibilityDelegate} has been specified via calling 5022 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5023 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 5024 * responsible for handling this call. 5025 * </p> 5026 * 5027 * @param eventType The type of the event to send, as defined by several types from 5028 * {@link android.view.accessibility.AccessibilityEvent}, such as 5029 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 5030 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 5031 * 5032 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 5033 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5034 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 5035 * @see AccessibilityDelegate 5036 */ 5037 public void sendAccessibilityEvent(int eventType) { 5038 if (mAccessibilityDelegate != null) { 5039 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 5040 } else { 5041 sendAccessibilityEventInternal(eventType); 5042 } 5043 } 5044 5045 /** 5046 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 5047 * {@link AccessibilityEvent} to make an announcement which is related to some 5048 * sort of a context change for which none of the events representing UI transitions 5049 * is a good fit. For example, announcing a new page in a book. If accessibility 5050 * is not enabled this method does nothing. 5051 * 5052 * @param text The announcement text. 5053 */ 5054 public void announceForAccessibility(CharSequence text) { 5055 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 5056 AccessibilityEvent event = AccessibilityEvent.obtain( 5057 AccessibilityEvent.TYPE_ANNOUNCEMENT); 5058 onInitializeAccessibilityEvent(event); 5059 event.getText().add(text); 5060 event.setContentDescription(null); 5061 mParent.requestSendAccessibilityEvent(this, event); 5062 } 5063 } 5064 5065 /** 5066 * @see #sendAccessibilityEvent(int) 5067 * 5068 * Note: Called from the default {@link AccessibilityDelegate}. 5069 */ 5070 void sendAccessibilityEventInternal(int eventType) { 5071 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 5072 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 5073 } 5074 } 5075 5076 /** 5077 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 5078 * takes as an argument an empty {@link AccessibilityEvent} and does not 5079 * perform a check whether accessibility is enabled. 5080 * <p> 5081 * If an {@link AccessibilityDelegate} has been specified via calling 5082 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5083 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 5084 * is responsible for handling this call. 5085 * </p> 5086 * 5087 * @param event The event to send. 5088 * 5089 * @see #sendAccessibilityEvent(int) 5090 */ 5091 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 5092 if (mAccessibilityDelegate != null) { 5093 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 5094 } else { 5095 sendAccessibilityEventUncheckedInternal(event); 5096 } 5097 } 5098 5099 /** 5100 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 5101 * 5102 * Note: Called from the default {@link AccessibilityDelegate}. 5103 */ 5104 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 5105 if (!isShown()) { 5106 return; 5107 } 5108 onInitializeAccessibilityEvent(event); 5109 // Only a subset of accessibility events populates text content. 5110 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 5111 dispatchPopulateAccessibilityEvent(event); 5112 } 5113 // In the beginning we called #isShown(), so we know that getParent() is not null. 5114 getParent().requestSendAccessibilityEvent(this, event); 5115 } 5116 5117 /** 5118 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 5119 * to its children for adding their text content to the event. Note that the 5120 * event text is populated in a separate dispatch path since we add to the 5121 * event not only the text of the source but also the text of all its descendants. 5122 * A typical implementation will call 5123 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 5124 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 5125 * on each child. Override this method if custom population of the event text 5126 * content is required. 5127 * <p> 5128 * If an {@link AccessibilityDelegate} has been specified via calling 5129 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5130 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 5131 * is responsible for handling this call. 5132 * </p> 5133 * <p> 5134 * <em>Note:</em> Accessibility events of certain types are not dispatched for 5135 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 5136 * </p> 5137 * 5138 * @param event The event. 5139 * 5140 * @return True if the event population was completed. 5141 */ 5142 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 5143 if (mAccessibilityDelegate != null) { 5144 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 5145 } else { 5146 return dispatchPopulateAccessibilityEventInternal(event); 5147 } 5148 } 5149 5150 /** 5151 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5152 * 5153 * Note: Called from the default {@link AccessibilityDelegate}. 5154 */ 5155 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 5156 onPopulateAccessibilityEvent(event); 5157 return false; 5158 } 5159 5160 /** 5161 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 5162 * giving a chance to this View to populate the accessibility event with its 5163 * text content. While this method is free to modify event 5164 * attributes other than text content, doing so should normally be performed in 5165 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 5166 * <p> 5167 * Example: Adding formatted date string to an accessibility event in addition 5168 * to the text added by the super implementation: 5169 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 5170 * super.onPopulateAccessibilityEvent(event); 5171 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 5172 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 5173 * mCurrentDate.getTimeInMillis(), flags); 5174 * event.getText().add(selectedDateUtterance); 5175 * }</pre> 5176 * <p> 5177 * If an {@link AccessibilityDelegate} has been specified via calling 5178 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5179 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 5180 * is responsible for handling this call. 5181 * </p> 5182 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 5183 * information to the event, in case the default implementation has basic information to add. 5184 * </p> 5185 * 5186 * @param event The accessibility event which to populate. 5187 * 5188 * @see #sendAccessibilityEvent(int) 5189 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5190 */ 5191 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 5192 if (mAccessibilityDelegate != null) { 5193 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 5194 } else { 5195 onPopulateAccessibilityEventInternal(event); 5196 } 5197 } 5198 5199 /** 5200 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 5201 * 5202 * Note: Called from the default {@link AccessibilityDelegate}. 5203 */ 5204 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 5205 } 5206 5207 /** 5208 * Initializes an {@link AccessibilityEvent} with information about 5209 * this View which is the event source. In other words, the source of 5210 * an accessibility event is the view whose state change triggered firing 5211 * the event. 5212 * <p> 5213 * Example: Setting the password property of an event in addition 5214 * to properties set by the super implementation: 5215 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 5216 * super.onInitializeAccessibilityEvent(event); 5217 * event.setPassword(true); 5218 * }</pre> 5219 * <p> 5220 * If an {@link AccessibilityDelegate} has been specified via calling 5221 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5222 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 5223 * is responsible for handling this call. 5224 * </p> 5225 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 5226 * information to the event, in case the default implementation has basic information to add. 5227 * </p> 5228 * @param event The event to initialize. 5229 * 5230 * @see #sendAccessibilityEvent(int) 5231 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5232 */ 5233 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 5234 if (mAccessibilityDelegate != null) { 5235 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 5236 } else { 5237 onInitializeAccessibilityEventInternal(event); 5238 } 5239 } 5240 5241 /** 5242 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 5243 * 5244 * Note: Called from the default {@link AccessibilityDelegate}. 5245 */ 5246 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 5247 event.setSource(this); 5248 event.setClassName(View.class.getName()); 5249 event.setPackageName(getContext().getPackageName()); 5250 event.setEnabled(isEnabled()); 5251 event.setContentDescription(mContentDescription); 5252 5253 switch (event.getEventType()) { 5254 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 5255 ArrayList<View> focusablesTempList = (mAttachInfo != null) 5256 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 5257 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 5258 event.setItemCount(focusablesTempList.size()); 5259 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 5260 if (mAttachInfo != null) { 5261 focusablesTempList.clear(); 5262 } 5263 } break; 5264 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 5265 CharSequence text = getIterableTextForAccessibility(); 5266 if (text != null && text.length() > 0) { 5267 event.setFromIndex(getAccessibilitySelectionStart()); 5268 event.setToIndex(getAccessibilitySelectionEnd()); 5269 event.setItemCount(text.length()); 5270 } 5271 } break; 5272 } 5273 } 5274 5275 /** 5276 * Returns an {@link AccessibilityNodeInfo} representing this view from the 5277 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 5278 * This method is responsible for obtaining an accessibility node info from a 5279 * pool of reusable instances and calling 5280 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 5281 * initialize the former. 5282 * <p> 5283 * Note: The client is responsible for recycling the obtained instance by calling 5284 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 5285 * </p> 5286 * 5287 * @return A populated {@link AccessibilityNodeInfo}. 5288 * 5289 * @see AccessibilityNodeInfo 5290 */ 5291 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 5292 if (mAccessibilityDelegate != null) { 5293 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 5294 } else { 5295 return createAccessibilityNodeInfoInternal(); 5296 } 5297 } 5298 5299 /** 5300 * @see #createAccessibilityNodeInfo() 5301 */ 5302 AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 5303 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 5304 if (provider != null) { 5305 return provider.createAccessibilityNodeInfo(View.NO_ID); 5306 } else { 5307 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 5308 onInitializeAccessibilityNodeInfo(info); 5309 return info; 5310 } 5311 } 5312 5313 /** 5314 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 5315 * The base implementation sets: 5316 * <ul> 5317 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 5318 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 5319 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 5320 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 5321 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 5322 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 5323 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 5324 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 5325 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 5326 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 5327 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 5328 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 5329 * </ul> 5330 * <p> 5331 * Subclasses should override this method, call the super implementation, 5332 * and set additional attributes. 5333 * </p> 5334 * <p> 5335 * If an {@link AccessibilityDelegate} has been specified via calling 5336 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5337 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 5338 * is responsible for handling this call. 5339 * </p> 5340 * 5341 * @param info The instance to initialize. 5342 */ 5343 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 5344 if (mAccessibilityDelegate != null) { 5345 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 5346 } else { 5347 onInitializeAccessibilityNodeInfoInternal(info); 5348 } 5349 } 5350 5351 /** 5352 * Gets the location of this view in screen coordintates. 5353 * 5354 * @param outRect The output location 5355 */ 5356 void getBoundsOnScreen(Rect outRect) { 5357 if (mAttachInfo == null) { 5358 return; 5359 } 5360 5361 RectF position = mAttachInfo.mTmpTransformRect; 5362 position.set(0, 0, mRight - mLeft, mBottom - mTop); 5363 5364 if (!hasIdentityMatrix()) { 5365 getMatrix().mapRect(position); 5366 } 5367 5368 position.offset(mLeft, mTop); 5369 5370 ViewParent parent = mParent; 5371 while (parent instanceof View) { 5372 View parentView = (View) parent; 5373 5374 position.offset(-parentView.mScrollX, -parentView.mScrollY); 5375 5376 if (!parentView.hasIdentityMatrix()) { 5377 parentView.getMatrix().mapRect(position); 5378 } 5379 5380 position.offset(parentView.mLeft, parentView.mTop); 5381 5382 parent = parentView.mParent; 5383 } 5384 5385 if (parent instanceof ViewRootImpl) { 5386 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 5387 position.offset(0, -viewRootImpl.mCurScrollY); 5388 } 5389 5390 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 5391 5392 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f), 5393 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f)); 5394 } 5395 5396 /** 5397 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 5398 * 5399 * Note: Called from the default {@link AccessibilityDelegate}. 5400 */ 5401 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 5402 Rect bounds = mAttachInfo.mTmpInvalRect; 5403 5404 getDrawingRect(bounds); 5405 info.setBoundsInParent(bounds); 5406 5407 getBoundsOnScreen(bounds); 5408 info.setBoundsInScreen(bounds); 5409 5410 ViewParent parent = getParentForAccessibility(); 5411 if (parent instanceof View) { 5412 info.setParent((View) parent); 5413 } 5414 5415 if (mID != View.NO_ID) { 5416 View rootView = getRootView(); 5417 if (rootView == null) { 5418 rootView = this; 5419 } 5420 View label = rootView.findLabelForView(this, mID); 5421 if (label != null) { 5422 info.setLabeledBy(label); 5423 } 5424 5425 if ((mAttachInfo.mAccessibilityFetchFlags 5426 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 5427 && Resources.resourceHasPackage(mID)) { 5428 try { 5429 String viewId = getResources().getResourceName(mID); 5430 info.setViewIdResourceName(viewId); 5431 } catch (Resources.NotFoundException nfe) { 5432 /* ignore */ 5433 } 5434 } 5435 } 5436 5437 if (mLabelForId != View.NO_ID) { 5438 View rootView = getRootView(); 5439 if (rootView == null) { 5440 rootView = this; 5441 } 5442 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 5443 if (labeled != null) { 5444 info.setLabelFor(labeled); 5445 } 5446 } 5447 5448 info.setVisibleToUser(isVisibleToUser()); 5449 5450 info.setPackageName(mContext.getPackageName()); 5451 info.setClassName(View.class.getName()); 5452 info.setContentDescription(getContentDescription()); 5453 5454 info.setEnabled(isEnabled()); 5455 info.setClickable(isClickable()); 5456 info.setFocusable(isFocusable()); 5457 info.setFocused(isFocused()); 5458 info.setAccessibilityFocused(isAccessibilityFocused()); 5459 info.setSelected(isSelected()); 5460 info.setLongClickable(isLongClickable()); 5461 info.setLiveRegion(getAccessibilityLiveRegion()); 5462 5463 // TODO: These make sense only if we are in an AdapterView but all 5464 // views can be selected. Maybe from accessibility perspective 5465 // we should report as selectable view in an AdapterView. 5466 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 5467 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 5468 5469 if (isFocusable()) { 5470 if (isFocused()) { 5471 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 5472 } else { 5473 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 5474 } 5475 } 5476 5477 if (!isAccessibilityFocused()) { 5478 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 5479 } else { 5480 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 5481 } 5482 5483 if (isClickable() && isEnabled()) { 5484 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 5485 } 5486 5487 if (isLongClickable() && isEnabled()) { 5488 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 5489 } 5490 5491 CharSequence text = getIterableTextForAccessibility(); 5492 if (text != null && text.length() > 0) { 5493 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 5494 5495 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 5496 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 5497 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 5498 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 5499 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 5500 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 5501 } 5502 } 5503 5504 private View findLabelForView(View view, int labeledId) { 5505 if (mMatchLabelForPredicate == null) { 5506 mMatchLabelForPredicate = new MatchLabelForPredicate(); 5507 } 5508 mMatchLabelForPredicate.mLabeledId = labeledId; 5509 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 5510 } 5511 5512 /** 5513 * Computes whether this view is visible to the user. Such a view is 5514 * attached, visible, all its predecessors are visible, it is not clipped 5515 * entirely by its predecessors, and has an alpha greater than zero. 5516 * 5517 * @return Whether the view is visible on the screen. 5518 * 5519 * @hide 5520 */ 5521 protected boolean isVisibleToUser() { 5522 return isVisibleToUser(null); 5523 } 5524 5525 /** 5526 * Computes whether the given portion of this view is visible to the user. 5527 * Such a view is attached, visible, all its predecessors are visible, 5528 * has an alpha greater than zero, and the specified portion is not 5529 * clipped entirely by its predecessors. 5530 * 5531 * @param boundInView the portion of the view to test; coordinates should be relative; may be 5532 * <code>null</code>, and the entire view will be tested in this case. 5533 * When <code>true</code> is returned by the function, the actual visible 5534 * region will be stored in this parameter; that is, if boundInView is fully 5535 * contained within the view, no modification will be made, otherwise regions 5536 * outside of the visible area of the view will be clipped. 5537 * 5538 * @return Whether the specified portion of the view is visible on the screen. 5539 * 5540 * @hide 5541 */ 5542 protected boolean isVisibleToUser(Rect boundInView) { 5543 if (mAttachInfo != null) { 5544 // Attached to invisible window means this view is not visible. 5545 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 5546 return false; 5547 } 5548 // An invisible predecessor or one with alpha zero means 5549 // that this view is not visible to the user. 5550 Object current = this; 5551 while (current instanceof View) { 5552 View view = (View) current; 5553 // We have attach info so this view is attached and there is no 5554 // need to check whether we reach to ViewRootImpl on the way up. 5555 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 5556 view.getVisibility() != VISIBLE) { 5557 return false; 5558 } 5559 current = view.mParent; 5560 } 5561 // Check if the view is entirely covered by its predecessors. 5562 Rect visibleRect = mAttachInfo.mTmpInvalRect; 5563 Point offset = mAttachInfo.mPoint; 5564 if (!getGlobalVisibleRect(visibleRect, offset)) { 5565 return false; 5566 } 5567 // Check if the visible portion intersects the rectangle of interest. 5568 if (boundInView != null) { 5569 visibleRect.offset(-offset.x, -offset.y); 5570 return boundInView.intersect(visibleRect); 5571 } 5572 return true; 5573 } 5574 return false; 5575 } 5576 5577 /** 5578 * Returns the delegate for implementing accessibility support via 5579 * composition. For more details see {@link AccessibilityDelegate}. 5580 * 5581 * @return The delegate, or null if none set. 5582 * 5583 * @hide 5584 */ 5585 public AccessibilityDelegate getAccessibilityDelegate() { 5586 return mAccessibilityDelegate; 5587 } 5588 5589 /** 5590 * Sets a delegate for implementing accessibility support via composition as 5591 * opposed to inheritance. The delegate's primary use is for implementing 5592 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}. 5593 * 5594 * @param delegate The delegate instance. 5595 * 5596 * @see AccessibilityDelegate 5597 */ 5598 public void setAccessibilityDelegate(AccessibilityDelegate delegate) { 5599 mAccessibilityDelegate = delegate; 5600 } 5601 5602 /** 5603 * Gets the provider for managing a virtual view hierarchy rooted at this View 5604 * and reported to {@link android.accessibilityservice.AccessibilityService}s 5605 * that explore the window content. 5606 * <p> 5607 * If this method returns an instance, this instance is responsible for managing 5608 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 5609 * View including the one representing the View itself. Similarly the returned 5610 * instance is responsible for performing accessibility actions on any virtual 5611 * view or the root view itself. 5612 * </p> 5613 * <p> 5614 * If an {@link AccessibilityDelegate} has been specified via calling 5615 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5616 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 5617 * is responsible for handling this call. 5618 * </p> 5619 * 5620 * @return The provider. 5621 * 5622 * @see AccessibilityNodeProvider 5623 */ 5624 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 5625 if (mAccessibilityDelegate != null) { 5626 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 5627 } else { 5628 return null; 5629 } 5630 } 5631 5632 /** 5633 * Gets the unique identifier of this view on the screen for accessibility purposes. 5634 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 5635 * 5636 * @return The view accessibility id. 5637 * 5638 * @hide 5639 */ 5640 public int getAccessibilityViewId() { 5641 if (mAccessibilityViewId == NO_ID) { 5642 mAccessibilityViewId = sNextAccessibilityViewId++; 5643 } 5644 return mAccessibilityViewId; 5645 } 5646 5647 /** 5648 * Gets the unique identifier of the window in which this View reseides. 5649 * 5650 * @return The window accessibility id. 5651 * 5652 * @hide 5653 */ 5654 public int getAccessibilityWindowId() { 5655 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId 5656 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 5657 } 5658 5659 /** 5660 * Gets the {@link View} description. It briefly describes the view and is 5661 * primarily used for accessibility support. Set this property to enable 5662 * better accessibility support for your application. This is especially 5663 * true for views that do not have textual representation (For example, 5664 * ImageButton). 5665 * 5666 * @return The content description. 5667 * 5668 * @attr ref android.R.styleable#View_contentDescription 5669 */ 5670 @ViewDebug.ExportedProperty(category = "accessibility") 5671 public CharSequence getContentDescription() { 5672 return mContentDescription; 5673 } 5674 5675 /** 5676 * Sets the {@link View} description. It briefly describes the view and is 5677 * primarily used for accessibility support. Set this property to enable 5678 * better accessibility support for your application. This is especially 5679 * true for views that do not have textual representation (For example, 5680 * ImageButton). 5681 * 5682 * @param contentDescription The content description. 5683 * 5684 * @attr ref android.R.styleable#View_contentDescription 5685 */ 5686 @RemotableViewMethod 5687 public void setContentDescription(CharSequence contentDescription) { 5688 if (mContentDescription == null) { 5689 if (contentDescription == null) { 5690 return; 5691 } 5692 } else if (mContentDescription.equals(contentDescription)) { 5693 return; 5694 } 5695 mContentDescription = contentDescription; 5696 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 5697 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 5698 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 5699 notifySubtreeAccessibilityStateChangedIfNeeded(); 5700 } else { 5701 notifyViewAccessibilityStateChangedIfNeeded( 5702 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 5703 } 5704 } 5705 5706 /** 5707 * Gets the id of a view for which this view serves as a label for 5708 * accessibility purposes. 5709 * 5710 * @return The labeled view id. 5711 */ 5712 @ViewDebug.ExportedProperty(category = "accessibility") 5713 public int getLabelFor() { 5714 return mLabelForId; 5715 } 5716 5717 /** 5718 * Sets the id of a view for which this view serves as a label for 5719 * accessibility purposes. 5720 * 5721 * @param id The labeled view id. 5722 */ 5723 @RemotableViewMethod 5724 public void setLabelFor(int id) { 5725 mLabelForId = id; 5726 if (mLabelForId != View.NO_ID 5727 && mID == View.NO_ID) { 5728 mID = generateViewId(); 5729 } 5730 } 5731 5732 /** 5733 * Invoked whenever this view loses focus, either by losing window focus or by losing 5734 * focus within its window. This method can be used to clear any state tied to the 5735 * focus. For instance, if a button is held pressed with the trackball and the window 5736 * loses focus, this method can be used to cancel the press. 5737 * 5738 * Subclasses of View overriding this method should always call super.onFocusLost(). 5739 * 5740 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 5741 * @see #onWindowFocusChanged(boolean) 5742 * 5743 * @hide pending API council approval 5744 */ 5745 protected void onFocusLost() { 5746 resetPressedState(); 5747 } 5748 5749 private void resetPressedState() { 5750 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 5751 return; 5752 } 5753 5754 if (isPressed()) { 5755 setPressed(false); 5756 5757 if (!mHasPerformedLongPress) { 5758 removeLongPressCallback(); 5759 } 5760 } 5761 } 5762 5763 /** 5764 * Returns true if this view has focus 5765 * 5766 * @return True if this view has focus, false otherwise. 5767 */ 5768 @ViewDebug.ExportedProperty(category = "focus") 5769 public boolean isFocused() { 5770 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 5771 } 5772 5773 /** 5774 * Find the view in the hierarchy rooted at this view that currently has 5775 * focus. 5776 * 5777 * @return The view that currently has focus, or null if no focused view can 5778 * be found. 5779 */ 5780 public View findFocus() { 5781 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 5782 } 5783 5784 /** 5785 * Indicates whether this view is one of the set of scrollable containers in 5786 * its window. 5787 * 5788 * @return whether this view is one of the set of scrollable containers in 5789 * its window 5790 * 5791 * @attr ref android.R.styleable#View_isScrollContainer 5792 */ 5793 public boolean isScrollContainer() { 5794 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 5795 } 5796 5797 /** 5798 * Change whether this view is one of the set of scrollable containers in 5799 * its window. This will be used to determine whether the window can 5800 * resize or must pan when a soft input area is open -- scrollable 5801 * containers allow the window to use resize mode since the container 5802 * will appropriately shrink. 5803 * 5804 * @attr ref android.R.styleable#View_isScrollContainer 5805 */ 5806 public void setScrollContainer(boolean isScrollContainer) { 5807 if (isScrollContainer) { 5808 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 5809 mAttachInfo.mScrollContainers.add(this); 5810 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 5811 } 5812 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 5813 } else { 5814 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 5815 mAttachInfo.mScrollContainers.remove(this); 5816 } 5817 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 5818 } 5819 } 5820 5821 /** 5822 * Returns the quality of the drawing cache. 5823 * 5824 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 5825 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 5826 * 5827 * @see #setDrawingCacheQuality(int) 5828 * @see #setDrawingCacheEnabled(boolean) 5829 * @see #isDrawingCacheEnabled() 5830 * 5831 * @attr ref android.R.styleable#View_drawingCacheQuality 5832 */ 5833 @DrawingCacheQuality 5834 public int getDrawingCacheQuality() { 5835 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 5836 } 5837 5838 /** 5839 * Set the drawing cache quality of this view. This value is used only when the 5840 * drawing cache is enabled 5841 * 5842 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 5843 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 5844 * 5845 * @see #getDrawingCacheQuality() 5846 * @see #setDrawingCacheEnabled(boolean) 5847 * @see #isDrawingCacheEnabled() 5848 * 5849 * @attr ref android.R.styleable#View_drawingCacheQuality 5850 */ 5851 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) { 5852 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 5853 } 5854 5855 /** 5856 * Returns whether the screen should remain on, corresponding to the current 5857 * value of {@link #KEEP_SCREEN_ON}. 5858 * 5859 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 5860 * 5861 * @see #setKeepScreenOn(boolean) 5862 * 5863 * @attr ref android.R.styleable#View_keepScreenOn 5864 */ 5865 public boolean getKeepScreenOn() { 5866 return (mViewFlags & KEEP_SCREEN_ON) != 0; 5867 } 5868 5869 /** 5870 * Controls whether the screen should remain on, modifying the 5871 * value of {@link #KEEP_SCREEN_ON}. 5872 * 5873 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 5874 * 5875 * @see #getKeepScreenOn() 5876 * 5877 * @attr ref android.R.styleable#View_keepScreenOn 5878 */ 5879 public void setKeepScreenOn(boolean keepScreenOn) { 5880 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 5881 } 5882 5883 /** 5884 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 5885 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5886 * 5887 * @attr ref android.R.styleable#View_nextFocusLeft 5888 */ 5889 public int getNextFocusLeftId() { 5890 return mNextFocusLeftId; 5891 } 5892 5893 /** 5894 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 5895 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 5896 * decide automatically. 5897 * 5898 * @attr ref android.R.styleable#View_nextFocusLeft 5899 */ 5900 public void setNextFocusLeftId(int nextFocusLeftId) { 5901 mNextFocusLeftId = nextFocusLeftId; 5902 } 5903 5904 /** 5905 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 5906 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5907 * 5908 * @attr ref android.R.styleable#View_nextFocusRight 5909 */ 5910 public int getNextFocusRightId() { 5911 return mNextFocusRightId; 5912 } 5913 5914 /** 5915 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 5916 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 5917 * decide automatically. 5918 * 5919 * @attr ref android.R.styleable#View_nextFocusRight 5920 */ 5921 public void setNextFocusRightId(int nextFocusRightId) { 5922 mNextFocusRightId = nextFocusRightId; 5923 } 5924 5925 /** 5926 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 5927 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5928 * 5929 * @attr ref android.R.styleable#View_nextFocusUp 5930 */ 5931 public int getNextFocusUpId() { 5932 return mNextFocusUpId; 5933 } 5934 5935 /** 5936 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 5937 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 5938 * decide automatically. 5939 * 5940 * @attr ref android.R.styleable#View_nextFocusUp 5941 */ 5942 public void setNextFocusUpId(int nextFocusUpId) { 5943 mNextFocusUpId = nextFocusUpId; 5944 } 5945 5946 /** 5947 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 5948 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5949 * 5950 * @attr ref android.R.styleable#View_nextFocusDown 5951 */ 5952 public int getNextFocusDownId() { 5953 return mNextFocusDownId; 5954 } 5955 5956 /** 5957 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 5958 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 5959 * decide automatically. 5960 * 5961 * @attr ref android.R.styleable#View_nextFocusDown 5962 */ 5963 public void setNextFocusDownId(int nextFocusDownId) { 5964 mNextFocusDownId = nextFocusDownId; 5965 } 5966 5967 /** 5968 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 5969 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 5970 * 5971 * @attr ref android.R.styleable#View_nextFocusForward 5972 */ 5973 public int getNextFocusForwardId() { 5974 return mNextFocusForwardId; 5975 } 5976 5977 /** 5978 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 5979 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 5980 * decide automatically. 5981 * 5982 * @attr ref android.R.styleable#View_nextFocusForward 5983 */ 5984 public void setNextFocusForwardId(int nextFocusForwardId) { 5985 mNextFocusForwardId = nextFocusForwardId; 5986 } 5987 5988 /** 5989 * Returns the visibility of this view and all of its ancestors 5990 * 5991 * @return True if this view and all of its ancestors are {@link #VISIBLE} 5992 */ 5993 public boolean isShown() { 5994 View current = this; 5995 //noinspection ConstantConditions 5996 do { 5997 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 5998 return false; 5999 } 6000 ViewParent parent = current.mParent; 6001 if (parent == null) { 6002 return false; // We are not attached to the view root 6003 } 6004 if (!(parent instanceof View)) { 6005 return true; 6006 } 6007 current = (View) parent; 6008 } while (current != null); 6009 6010 return false; 6011 } 6012 6013 /** 6014 * Called by the view hierarchy when the content insets for a window have 6015 * changed, to allow it to adjust its content to fit within those windows. 6016 * The content insets tell you the space that the status bar, input method, 6017 * and other system windows infringe on the application's window. 6018 * 6019 * <p>You do not normally need to deal with this function, since the default 6020 * window decoration given to applications takes care of applying it to the 6021 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 6022 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 6023 * and your content can be placed under those system elements. You can then 6024 * use this method within your view hierarchy if you have parts of your UI 6025 * which you would like to ensure are not being covered. 6026 * 6027 * <p>The default implementation of this method simply applies the content 6028 * insets to the view's padding, consuming that content (modifying the 6029 * insets to be 0), and returning true. This behavior is off by default, but can 6030 * be enabled through {@link #setFitsSystemWindows(boolean)}. 6031 * 6032 * <p>This function's traversal down the hierarchy is depth-first. The same content 6033 * insets object is propagated down the hierarchy, so any changes made to it will 6034 * be seen by all following views (including potentially ones above in 6035 * the hierarchy since this is a depth-first traversal). The first view 6036 * that returns true will abort the entire traversal. 6037 * 6038 * <p>The default implementation works well for a situation where it is 6039 * used with a container that covers the entire window, allowing it to 6040 * apply the appropriate insets to its content on all edges. If you need 6041 * a more complicated layout (such as two different views fitting system 6042 * windows, one on the top of the window, and one on the bottom), 6043 * you can override the method and handle the insets however you would like. 6044 * Note that the insets provided by the framework are always relative to the 6045 * far edges of the window, not accounting for the location of the called view 6046 * within that window. (In fact when this method is called you do not yet know 6047 * where the layout will place the view, as it is done before layout happens.) 6048 * 6049 * <p>Note: unlike many View methods, there is no dispatch phase to this 6050 * call. If you are overriding it in a ViewGroup and want to allow the 6051 * call to continue to your children, you must be sure to call the super 6052 * implementation. 6053 * 6054 * <p>Here is a sample layout that makes use of fitting system windows 6055 * to have controls for a video view placed inside of the window decorations 6056 * that it hides and shows. This can be used with code like the second 6057 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 6058 * 6059 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 6060 * 6061 * @param insets Current content insets of the window. Prior to 6062 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 6063 * the insets or else you and Android will be unhappy. 6064 * 6065 * @return {@code true} if this view applied the insets and it should not 6066 * continue propagating further down the hierarchy, {@code false} otherwise. 6067 * @see #getFitsSystemWindows() 6068 * @see #setFitsSystemWindows(boolean) 6069 * @see #setSystemUiVisibility(int) 6070 * 6071 * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply 6072 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use 6073 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)} 6074 * to implement handling their own insets. 6075 */ 6076 protected boolean fitSystemWindows(Rect insets) { 6077 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) { 6078 // If we're not in the process of dispatching the newer apply insets call, 6079 // that means we're not in the compatibility path. Dispatch into the newer 6080 // apply insets path and take things from there. 6081 try { 6082 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS; 6083 return !dispatchApplyWindowInsets(new WindowInsets(insets)).hasInsets(); 6084 } finally { 6085 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS; 6086 } 6087 } else { 6088 // We're being called from the newer apply insets path. 6089 // Perform the standard fallback behavior. 6090 return fitSystemWindowsInt(insets); 6091 } 6092 } 6093 6094 private boolean fitSystemWindowsInt(Rect insets) { 6095 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 6096 mUserPaddingStart = UNDEFINED_PADDING; 6097 mUserPaddingEnd = UNDEFINED_PADDING; 6098 Rect localInsets = sThreadLocal.get(); 6099 if (localInsets == null) { 6100 localInsets = new Rect(); 6101 sThreadLocal.set(localInsets); 6102 } 6103 boolean res = computeFitSystemWindows(insets, localInsets); 6104 mUserPaddingLeftInitial = localInsets.left; 6105 mUserPaddingRightInitial = localInsets.right; 6106 internalSetPadding(localInsets.left, localInsets.top, 6107 localInsets.right, localInsets.bottom); 6108 return res; 6109 } 6110 return false; 6111 } 6112 6113 /** 6114 * Called when the view should apply {@link WindowInsets} according to its internal policy. 6115 * 6116 * <p>This method should be overridden by views that wish to apply a policy different from or 6117 * in addition to the default behavior. Clients that wish to force a view subtree 6118 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p> 6119 * 6120 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set 6121 * it will be called during dispatch instead of this method. The listener may optionally 6122 * call this method from its own implementation if it wishes to apply the view's default 6123 * insets policy in addition to its own.</p> 6124 * 6125 * <p>Implementations of this method should either return the insets parameter unchanged 6126 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed 6127 * that this view applied itself. This allows new inset types added in future platform 6128 * versions to pass through existing implementations unchanged without being erroneously 6129 * consumed.</p> 6130 * 6131 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows} 6132 * property is set then the view will consume the system window insets and apply them 6133 * as padding for the view.</p> 6134 * 6135 * @param insets Insets to apply 6136 * @return The supplied insets with any applied insets consumed 6137 */ 6138 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 6139 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) { 6140 // We weren't called from within a direct call to fitSystemWindows, 6141 // call into it as a fallback in case we're in a class that overrides it 6142 // and has logic to perform. 6143 if (fitSystemWindows(insets.getSystemWindowInsets())) { 6144 return insets.cloneWithSystemWindowInsetsConsumed(); 6145 } 6146 } else { 6147 // We were called from within a direct call to fitSystemWindows. 6148 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) { 6149 return insets.cloneWithSystemWindowInsetsConsumed(); 6150 } 6151 } 6152 return insets; 6153 } 6154 6155 /** 6156 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying 6157 * window insets to this view. The listener's 6158 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 6159 * method will be called instead of the view's 6160 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 6161 * 6162 * @param listener Listener to set 6163 * 6164 * @see #onApplyWindowInsets(WindowInsets) 6165 */ 6166 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) { 6167 getListenerInfo().mOnApplyWindowInsetsListener = listener; 6168 } 6169 6170 /** 6171 * Request to apply the given window insets to this view or another view in its subtree. 6172 * 6173 * <p>This method should be called by clients wishing to apply insets corresponding to areas 6174 * obscured by window decorations or overlays. This can include the status and navigation bars, 6175 * action bars, input methods and more. New inset categories may be added in the future. 6176 * The method returns the insets provided minus any that were applied by this view or its 6177 * children.</p> 6178 * 6179 * <p>Clients wishing to provide custom behavior should override the 6180 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a 6181 * {@link OnApplyWindowInsetsListener} via the 6182 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener} 6183 * method.</p> 6184 * 6185 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method. 6186 * </p> 6187 * 6188 * @param insets Insets to apply 6189 * @return The provided insets minus the insets that were consumed 6190 */ 6191 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { 6192 try { 6193 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS; 6194 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) { 6195 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets); 6196 } else { 6197 return onApplyWindowInsets(insets); 6198 } 6199 } finally { 6200 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS; 6201 } 6202 } 6203 6204 /** 6205 * @hide Compute the insets that should be consumed by this view and the ones 6206 * that should propagate to those under it. 6207 */ 6208 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 6209 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 6210 || mAttachInfo == null 6211 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 6212 && !mAttachInfo.mOverscanRequested)) { 6213 outLocalInsets.set(inoutInsets); 6214 inoutInsets.set(0, 0, 0, 0); 6215 return true; 6216 } else { 6217 // The application wants to take care of fitting system window for 6218 // the content... however we still need to take care of any overscan here. 6219 final Rect overscan = mAttachInfo.mOverscanInsets; 6220 outLocalInsets.set(overscan); 6221 inoutInsets.left -= overscan.left; 6222 inoutInsets.top -= overscan.top; 6223 inoutInsets.right -= overscan.right; 6224 inoutInsets.bottom -= overscan.bottom; 6225 return false; 6226 } 6227 } 6228 6229 /** 6230 * Sets whether or not this view should account for system screen decorations 6231 * such as the status bar and inset its content; that is, controlling whether 6232 * the default implementation of {@link #fitSystemWindows(Rect)} will be 6233 * executed. See that method for more details. 6234 * 6235 * <p>Note that if you are providing your own implementation of 6236 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 6237 * flag to true -- your implementation will be overriding the default 6238 * implementation that checks this flag. 6239 * 6240 * @param fitSystemWindows If true, then the default implementation of 6241 * {@link #fitSystemWindows(Rect)} will be executed. 6242 * 6243 * @attr ref android.R.styleable#View_fitsSystemWindows 6244 * @see #getFitsSystemWindows() 6245 * @see #fitSystemWindows(Rect) 6246 * @see #setSystemUiVisibility(int) 6247 */ 6248 public void setFitsSystemWindows(boolean fitSystemWindows) { 6249 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 6250 } 6251 6252 /** 6253 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 6254 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 6255 * will be executed. 6256 * 6257 * @return {@code true} if the default implementation of 6258 * {@link #fitSystemWindows(Rect)} will be executed. 6259 * 6260 * @attr ref android.R.styleable#View_fitsSystemWindows 6261 * @see #setFitsSystemWindows(boolean) 6262 * @see #fitSystemWindows(Rect) 6263 * @see #setSystemUiVisibility(int) 6264 */ 6265 public boolean getFitsSystemWindows() { 6266 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 6267 } 6268 6269 /** @hide */ 6270 public boolean fitsSystemWindows() { 6271 return getFitsSystemWindows(); 6272 } 6273 6274 /** 6275 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 6276 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions. 6277 */ 6278 public void requestFitSystemWindows() { 6279 if (mParent != null) { 6280 mParent.requestFitSystemWindows(); 6281 } 6282 } 6283 6284 /** 6285 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed. 6286 */ 6287 public void requestApplyInsets() { 6288 requestFitSystemWindows(); 6289 } 6290 6291 /** 6292 * For use by PhoneWindow to make its own system window fitting optional. 6293 * @hide 6294 */ 6295 public void makeOptionalFitsSystemWindows() { 6296 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 6297 } 6298 6299 /** 6300 * Returns the visibility status for this view. 6301 * 6302 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 6303 * @attr ref android.R.styleable#View_visibility 6304 */ 6305 @ViewDebug.ExportedProperty(mapping = { 6306 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 6307 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 6308 @ViewDebug.IntToString(from = GONE, to = "GONE") 6309 }) 6310 @Visibility 6311 public int getVisibility() { 6312 return mViewFlags & VISIBILITY_MASK; 6313 } 6314 6315 /** 6316 * Set the enabled state of this view. 6317 * 6318 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 6319 * @attr ref android.R.styleable#View_visibility 6320 */ 6321 @RemotableViewMethod 6322 public void setVisibility(@Visibility int visibility) { 6323 setFlags(visibility, VISIBILITY_MASK); 6324 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false); 6325 } 6326 6327 /** 6328 * Returns the enabled status for this view. The interpretation of the 6329 * enabled state varies by subclass. 6330 * 6331 * @return True if this view is enabled, false otherwise. 6332 */ 6333 @ViewDebug.ExportedProperty 6334 public boolean isEnabled() { 6335 return (mViewFlags & ENABLED_MASK) == ENABLED; 6336 } 6337 6338 /** 6339 * Set the enabled state of this view. The interpretation of the enabled 6340 * state varies by subclass. 6341 * 6342 * @param enabled True if this view is enabled, false otherwise. 6343 */ 6344 @RemotableViewMethod 6345 public void setEnabled(boolean enabled) { 6346 if (enabled == isEnabled()) return; 6347 6348 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 6349 6350 /* 6351 * The View most likely has to change its appearance, so refresh 6352 * the drawable state. 6353 */ 6354 refreshDrawableState(); 6355 6356 // Invalidate too, since the default behavior for views is to be 6357 // be drawn at 50% alpha rather than to change the drawable. 6358 invalidate(true); 6359 6360 if (!enabled) { 6361 cancelPendingInputEvents(); 6362 } 6363 } 6364 6365 /** 6366 * Set whether this view can receive the focus. 6367 * 6368 * Setting this to false will also ensure that this view is not focusable 6369 * in touch mode. 6370 * 6371 * @param focusable If true, this view can receive the focus. 6372 * 6373 * @see #setFocusableInTouchMode(boolean) 6374 * @attr ref android.R.styleable#View_focusable 6375 */ 6376 public void setFocusable(boolean focusable) { 6377 if (!focusable) { 6378 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 6379 } 6380 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 6381 } 6382 6383 /** 6384 * Set whether this view can receive focus while in touch mode. 6385 * 6386 * Setting this to true will also ensure that this view is focusable. 6387 * 6388 * @param focusableInTouchMode If true, this view can receive the focus while 6389 * in touch mode. 6390 * 6391 * @see #setFocusable(boolean) 6392 * @attr ref android.R.styleable#View_focusableInTouchMode 6393 */ 6394 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 6395 // Focusable in touch mode should always be set before the focusable flag 6396 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 6397 // which, in touch mode, will not successfully request focus on this view 6398 // because the focusable in touch mode flag is not set 6399 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 6400 if (focusableInTouchMode) { 6401 setFlags(FOCUSABLE, FOCUSABLE_MASK); 6402 } 6403 } 6404 6405 /** 6406 * Set whether this view should have sound effects enabled for events such as 6407 * clicking and touching. 6408 * 6409 * <p>You may wish to disable sound effects for a view if you already play sounds, 6410 * for instance, a dial key that plays dtmf tones. 6411 * 6412 * @param soundEffectsEnabled whether sound effects are enabled for this view. 6413 * @see #isSoundEffectsEnabled() 6414 * @see #playSoundEffect(int) 6415 * @attr ref android.R.styleable#View_soundEffectsEnabled 6416 */ 6417 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 6418 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 6419 } 6420 6421 /** 6422 * @return whether this view should have sound effects enabled for events such as 6423 * clicking and touching. 6424 * 6425 * @see #setSoundEffectsEnabled(boolean) 6426 * @see #playSoundEffect(int) 6427 * @attr ref android.R.styleable#View_soundEffectsEnabled 6428 */ 6429 @ViewDebug.ExportedProperty 6430 public boolean isSoundEffectsEnabled() { 6431 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 6432 } 6433 6434 /** 6435 * Set whether this view should have haptic feedback for events such as 6436 * long presses. 6437 * 6438 * <p>You may wish to disable haptic feedback if your view already controls 6439 * its own haptic feedback. 6440 * 6441 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 6442 * @see #isHapticFeedbackEnabled() 6443 * @see #performHapticFeedback(int) 6444 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 6445 */ 6446 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 6447 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 6448 } 6449 6450 /** 6451 * @return whether this view should have haptic feedback enabled for events 6452 * long presses. 6453 * 6454 * @see #setHapticFeedbackEnabled(boolean) 6455 * @see #performHapticFeedback(int) 6456 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 6457 */ 6458 @ViewDebug.ExportedProperty 6459 public boolean isHapticFeedbackEnabled() { 6460 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 6461 } 6462 6463 /** 6464 * Returns the layout direction for this view. 6465 * 6466 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 6467 * {@link #LAYOUT_DIRECTION_RTL}, 6468 * {@link #LAYOUT_DIRECTION_INHERIT} or 6469 * {@link #LAYOUT_DIRECTION_LOCALE}. 6470 * 6471 * @attr ref android.R.styleable#View_layoutDirection 6472 * 6473 * @hide 6474 */ 6475 @ViewDebug.ExportedProperty(category = "layout", mapping = { 6476 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 6477 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 6478 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 6479 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 6480 }) 6481 @LayoutDir 6482 public int getRawLayoutDirection() { 6483 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 6484 } 6485 6486 /** 6487 * Set the layout direction for this view. This will propagate a reset of layout direction 6488 * resolution to the view's children and resolve layout direction for this view. 6489 * 6490 * @param layoutDirection the layout direction to set. Should be one of: 6491 * 6492 * {@link #LAYOUT_DIRECTION_LTR}, 6493 * {@link #LAYOUT_DIRECTION_RTL}, 6494 * {@link #LAYOUT_DIRECTION_INHERIT}, 6495 * {@link #LAYOUT_DIRECTION_LOCALE}. 6496 * 6497 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 6498 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 6499 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 6500 * 6501 * @attr ref android.R.styleable#View_layoutDirection 6502 */ 6503 @RemotableViewMethod 6504 public void setLayoutDirection(@LayoutDir int layoutDirection) { 6505 if (getRawLayoutDirection() != layoutDirection) { 6506 // Reset the current layout direction and the resolved one 6507 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 6508 resetRtlProperties(); 6509 // Set the new layout direction (filtered) 6510 mPrivateFlags2 |= 6511 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 6512 // We need to resolve all RTL properties as they all depend on layout direction 6513 resolveRtlPropertiesIfNeeded(); 6514 requestLayout(); 6515 invalidate(true); 6516 } 6517 } 6518 6519 /** 6520 * Returns the resolved layout direction for this view. 6521 * 6522 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 6523 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 6524 * 6525 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 6526 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 6527 * 6528 * @attr ref android.R.styleable#View_layoutDirection 6529 */ 6530 @ViewDebug.ExportedProperty(category = "layout", mapping = { 6531 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 6532 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 6533 }) 6534 @ResolvedLayoutDir 6535 public int getLayoutDirection() { 6536 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 6537 if (targetSdkVersion < JELLY_BEAN_MR1) { 6538 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 6539 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 6540 } 6541 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 6542 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 6543 } 6544 6545 /** 6546 * Indicates whether or not this view's layout is right-to-left. This is resolved from 6547 * layout attribute and/or the inherited value from the parent 6548 * 6549 * @return true if the layout is right-to-left. 6550 * 6551 * @hide 6552 */ 6553 @ViewDebug.ExportedProperty(category = "layout") 6554 public boolean isLayoutRtl() { 6555 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 6556 } 6557 6558 /** 6559 * Indicates whether the view is currently tracking transient state that the 6560 * app should not need to concern itself with saving and restoring, but that 6561 * the framework should take special note to preserve when possible. 6562 * 6563 * <p>A view with transient state cannot be trivially rebound from an external 6564 * data source, such as an adapter binding item views in a list. This may be 6565 * because the view is performing an animation, tracking user selection 6566 * of content, or similar.</p> 6567 * 6568 * @return true if the view has transient state 6569 */ 6570 @ViewDebug.ExportedProperty(category = "layout") 6571 public boolean hasTransientState() { 6572 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 6573 } 6574 6575 /** 6576 * Set whether this view is currently tracking transient state that the 6577 * framework should attempt to preserve when possible. This flag is reference counted, 6578 * so every call to setHasTransientState(true) should be paired with a later call 6579 * to setHasTransientState(false). 6580 * 6581 * <p>A view with transient state cannot be trivially rebound from an external 6582 * data source, such as an adapter binding item views in a list. This may be 6583 * because the view is performing an animation, tracking user selection 6584 * of content, or similar.</p> 6585 * 6586 * @param hasTransientState true if this view has transient state 6587 */ 6588 public void setHasTransientState(boolean hasTransientState) { 6589 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 6590 mTransientStateCount - 1; 6591 if (mTransientStateCount < 0) { 6592 mTransientStateCount = 0; 6593 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 6594 "unmatched pair of setHasTransientState calls"); 6595 } else if ((hasTransientState && mTransientStateCount == 1) || 6596 (!hasTransientState && mTransientStateCount == 0)) { 6597 // update flag if we've just incremented up from 0 or decremented down to 0 6598 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 6599 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 6600 if (mParent != null) { 6601 try { 6602 mParent.childHasTransientStateChanged(this, hasTransientState); 6603 } catch (AbstractMethodError e) { 6604 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 6605 " does not fully implement ViewParent", e); 6606 } 6607 } 6608 } 6609 } 6610 6611 /** 6612 * Returns true if this view is currently attached to a window. 6613 */ 6614 public boolean isAttachedToWindow() { 6615 return mAttachInfo != null; 6616 } 6617 6618 /** 6619 * Returns true if this view has been through at least one layout since it 6620 * was last attached to or detached from a window. 6621 */ 6622 public boolean isLaidOut() { 6623 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 6624 } 6625 6626 /** 6627 * If this view doesn't do any drawing on its own, set this flag to 6628 * allow further optimizations. By default, this flag is not set on 6629 * View, but could be set on some View subclasses such as ViewGroup. 6630 * 6631 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 6632 * you should clear this flag. 6633 * 6634 * @param willNotDraw whether or not this View draw on its own 6635 */ 6636 public void setWillNotDraw(boolean willNotDraw) { 6637 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 6638 } 6639 6640 /** 6641 * Returns whether or not this View draws on its own. 6642 * 6643 * @return true if this view has nothing to draw, false otherwise 6644 */ 6645 @ViewDebug.ExportedProperty(category = "drawing") 6646 public boolean willNotDraw() { 6647 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 6648 } 6649 6650 /** 6651 * When a View's drawing cache is enabled, drawing is redirected to an 6652 * offscreen bitmap. Some views, like an ImageView, must be able to 6653 * bypass this mechanism if they already draw a single bitmap, to avoid 6654 * unnecessary usage of the memory. 6655 * 6656 * @param willNotCacheDrawing true if this view does not cache its 6657 * drawing, false otherwise 6658 */ 6659 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 6660 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 6661 } 6662 6663 /** 6664 * Returns whether or not this View can cache its drawing or not. 6665 * 6666 * @return true if this view does not cache its drawing, false otherwise 6667 */ 6668 @ViewDebug.ExportedProperty(category = "drawing") 6669 public boolean willNotCacheDrawing() { 6670 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 6671 } 6672 6673 /** 6674 * Indicates whether this view reacts to click events or not. 6675 * 6676 * @return true if the view is clickable, false otherwise 6677 * 6678 * @see #setClickable(boolean) 6679 * @attr ref android.R.styleable#View_clickable 6680 */ 6681 @ViewDebug.ExportedProperty 6682 public boolean isClickable() { 6683 return (mViewFlags & CLICKABLE) == CLICKABLE; 6684 } 6685 6686 /** 6687 * Enables or disables click events for this view. When a view 6688 * is clickable it will change its state to "pressed" on every click. 6689 * Subclasses should set the view clickable to visually react to 6690 * user's clicks. 6691 * 6692 * @param clickable true to make the view clickable, false otherwise 6693 * 6694 * @see #isClickable() 6695 * @attr ref android.R.styleable#View_clickable 6696 */ 6697 public void setClickable(boolean clickable) { 6698 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 6699 } 6700 6701 /** 6702 * Indicates whether this view reacts to long click events or not. 6703 * 6704 * @return true if the view is long clickable, false otherwise 6705 * 6706 * @see #setLongClickable(boolean) 6707 * @attr ref android.R.styleable#View_longClickable 6708 */ 6709 public boolean isLongClickable() { 6710 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 6711 } 6712 6713 /** 6714 * Enables or disables long click events for this view. When a view is long 6715 * clickable it reacts to the user holding down the button for a longer 6716 * duration than a tap. This event can either launch the listener or a 6717 * context menu. 6718 * 6719 * @param longClickable true to make the view long clickable, false otherwise 6720 * @see #isLongClickable() 6721 * @attr ref android.R.styleable#View_longClickable 6722 */ 6723 public void setLongClickable(boolean longClickable) { 6724 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 6725 } 6726 6727 /** 6728 * Sets the pressed state for this view. 6729 * 6730 * @see #isClickable() 6731 * @see #setClickable(boolean) 6732 * 6733 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 6734 * the View's internal state from a previously set "pressed" state. 6735 */ 6736 public void setPressed(boolean pressed) { 6737 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 6738 6739 if (pressed) { 6740 mPrivateFlags |= PFLAG_PRESSED; 6741 } else { 6742 mPrivateFlags &= ~PFLAG_PRESSED; 6743 } 6744 6745 if (needsRefresh) { 6746 refreshDrawableState(); 6747 } 6748 dispatchSetPressed(pressed); 6749 } 6750 6751 /** 6752 * Dispatch setPressed to all of this View's children. 6753 * 6754 * @see #setPressed(boolean) 6755 * 6756 * @param pressed The new pressed state 6757 */ 6758 protected void dispatchSetPressed(boolean pressed) { 6759 } 6760 6761 /** 6762 * Indicates whether the view is currently in pressed state. Unless 6763 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 6764 * the pressed state. 6765 * 6766 * @see #setPressed(boolean) 6767 * @see #isClickable() 6768 * @see #setClickable(boolean) 6769 * 6770 * @return true if the view is currently pressed, false otherwise 6771 */ 6772 public boolean isPressed() { 6773 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 6774 } 6775 6776 /** 6777 * Indicates whether this view will save its state (that is, 6778 * whether its {@link #onSaveInstanceState} method will be called). 6779 * 6780 * @return Returns true if the view state saving is enabled, else false. 6781 * 6782 * @see #setSaveEnabled(boolean) 6783 * @attr ref android.R.styleable#View_saveEnabled 6784 */ 6785 public boolean isSaveEnabled() { 6786 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 6787 } 6788 6789 /** 6790 * Controls whether the saving of this view's state is 6791 * enabled (that is, whether its {@link #onSaveInstanceState} method 6792 * will be called). Note that even if freezing is enabled, the 6793 * view still must have an id assigned to it (via {@link #setId(int)}) 6794 * for its state to be saved. This flag can only disable the 6795 * saving of this view; any child views may still have their state saved. 6796 * 6797 * @param enabled Set to false to <em>disable</em> state saving, or true 6798 * (the default) to allow it. 6799 * 6800 * @see #isSaveEnabled() 6801 * @see #setId(int) 6802 * @see #onSaveInstanceState() 6803 * @attr ref android.R.styleable#View_saveEnabled 6804 */ 6805 public void setSaveEnabled(boolean enabled) { 6806 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 6807 } 6808 6809 /** 6810 * Gets whether the framework should discard touches when the view's 6811 * window is obscured by another visible window. 6812 * Refer to the {@link View} security documentation for more details. 6813 * 6814 * @return True if touch filtering is enabled. 6815 * 6816 * @see #setFilterTouchesWhenObscured(boolean) 6817 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 6818 */ 6819 @ViewDebug.ExportedProperty 6820 public boolean getFilterTouchesWhenObscured() { 6821 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 6822 } 6823 6824 /** 6825 * Sets whether the framework should discard touches when the view's 6826 * window is obscured by another visible window. 6827 * Refer to the {@link View} security documentation for more details. 6828 * 6829 * @param enabled True if touch filtering should be enabled. 6830 * 6831 * @see #getFilterTouchesWhenObscured 6832 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 6833 */ 6834 public void setFilterTouchesWhenObscured(boolean enabled) { 6835 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 6836 FILTER_TOUCHES_WHEN_OBSCURED); 6837 } 6838 6839 /** 6840 * Indicates whether the entire hierarchy under this view will save its 6841 * state when a state saving traversal occurs from its parent. The default 6842 * is true; if false, these views will not be saved unless 6843 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 6844 * 6845 * @return Returns true if the view state saving from parent is enabled, else false. 6846 * 6847 * @see #setSaveFromParentEnabled(boolean) 6848 */ 6849 public boolean isSaveFromParentEnabled() { 6850 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 6851 } 6852 6853 /** 6854 * Controls whether the entire hierarchy under this view will save its 6855 * state when a state saving traversal occurs from its parent. The default 6856 * is true; if false, these views will not be saved unless 6857 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 6858 * 6859 * @param enabled Set to false to <em>disable</em> state saving, or true 6860 * (the default) to allow it. 6861 * 6862 * @see #isSaveFromParentEnabled() 6863 * @see #setId(int) 6864 * @see #onSaveInstanceState() 6865 */ 6866 public void setSaveFromParentEnabled(boolean enabled) { 6867 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 6868 } 6869 6870 6871 /** 6872 * Returns whether this View is able to take focus. 6873 * 6874 * @return True if this view can take focus, or false otherwise. 6875 * @attr ref android.R.styleable#View_focusable 6876 */ 6877 @ViewDebug.ExportedProperty(category = "focus") 6878 public final boolean isFocusable() { 6879 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 6880 } 6881 6882 /** 6883 * When a view is focusable, it may not want to take focus when in touch mode. 6884 * For example, a button would like focus when the user is navigating via a D-pad 6885 * so that the user can click on it, but once the user starts touching the screen, 6886 * the button shouldn't take focus 6887 * @return Whether the view is focusable in touch mode. 6888 * @attr ref android.R.styleable#View_focusableInTouchMode 6889 */ 6890 @ViewDebug.ExportedProperty 6891 public final boolean isFocusableInTouchMode() { 6892 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 6893 } 6894 6895 /** 6896 * Find the nearest view in the specified direction that can take focus. 6897 * This does not actually give focus to that view. 6898 * 6899 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 6900 * 6901 * @return The nearest focusable in the specified direction, or null if none 6902 * can be found. 6903 */ 6904 public View focusSearch(@FocusRealDirection int direction) { 6905 if (mParent != null) { 6906 return mParent.focusSearch(this, direction); 6907 } else { 6908 return null; 6909 } 6910 } 6911 6912 /** 6913 * This method is the last chance for the focused view and its ancestors to 6914 * respond to an arrow key. This is called when the focused view did not 6915 * consume the key internally, nor could the view system find a new view in 6916 * the requested direction to give focus to. 6917 * 6918 * @param focused The currently focused view. 6919 * @param direction The direction focus wants to move. One of FOCUS_UP, 6920 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 6921 * @return True if the this view consumed this unhandled move. 6922 */ 6923 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) { 6924 return false; 6925 } 6926 6927 /** 6928 * If a user manually specified the next view id for a particular direction, 6929 * use the root to look up the view. 6930 * @param root The root view of the hierarchy containing this view. 6931 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 6932 * or FOCUS_BACKWARD. 6933 * @return The user specified next view, or null if there is none. 6934 */ 6935 View findUserSetNextFocus(View root, @FocusDirection int direction) { 6936 switch (direction) { 6937 case FOCUS_LEFT: 6938 if (mNextFocusLeftId == View.NO_ID) return null; 6939 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 6940 case FOCUS_RIGHT: 6941 if (mNextFocusRightId == View.NO_ID) return null; 6942 return findViewInsideOutShouldExist(root, mNextFocusRightId); 6943 case FOCUS_UP: 6944 if (mNextFocusUpId == View.NO_ID) return null; 6945 return findViewInsideOutShouldExist(root, mNextFocusUpId); 6946 case FOCUS_DOWN: 6947 if (mNextFocusDownId == View.NO_ID) return null; 6948 return findViewInsideOutShouldExist(root, mNextFocusDownId); 6949 case FOCUS_FORWARD: 6950 if (mNextFocusForwardId == View.NO_ID) return null; 6951 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 6952 case FOCUS_BACKWARD: { 6953 if (mID == View.NO_ID) return null; 6954 final int id = mID; 6955 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 6956 @Override 6957 public boolean apply(View t) { 6958 return t.mNextFocusForwardId == id; 6959 } 6960 }); 6961 } 6962 } 6963 return null; 6964 } 6965 6966 private View findViewInsideOutShouldExist(View root, int id) { 6967 if (mMatchIdPredicate == null) { 6968 mMatchIdPredicate = new MatchIdPredicate(); 6969 } 6970 mMatchIdPredicate.mId = id; 6971 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 6972 if (result == null) { 6973 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 6974 } 6975 return result; 6976 } 6977 6978 /** 6979 * Find and return all focusable views that are descendants of this view, 6980 * possibly including this view if it is focusable itself. 6981 * 6982 * @param direction The direction of the focus 6983 * @return A list of focusable views 6984 */ 6985 public ArrayList<View> getFocusables(@FocusDirection int direction) { 6986 ArrayList<View> result = new ArrayList<View>(24); 6987 addFocusables(result, direction); 6988 return result; 6989 } 6990 6991 /** 6992 * Add any focusable views that are descendants of this view (possibly 6993 * including this view if it is focusable itself) to views. If we are in touch mode, 6994 * only add views that are also focusable in touch mode. 6995 * 6996 * @param views Focusable views found so far 6997 * @param direction The direction of the focus 6998 */ 6999 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) { 7000 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); 7001 } 7002 7003 /** 7004 * Adds any focusable views that are descendants of this view (possibly 7005 * including this view if it is focusable itself) to views. This method 7006 * adds all focusable views regardless if we are in touch mode or 7007 * only views focusable in touch mode if we are in touch mode or 7008 * only views that can take accessibility focus if accessibility is enabeld 7009 * depending on the focusable mode paramater. 7010 * 7011 * @param views Focusable views found so far or null if all we are interested is 7012 * the number of focusables. 7013 * @param direction The direction of the focus. 7014 * @param focusableMode The type of focusables to be added. 7015 * 7016 * @see #FOCUSABLES_ALL 7017 * @see #FOCUSABLES_TOUCH_MODE 7018 */ 7019 public void addFocusables(ArrayList<View> views, @FocusDirection int direction, 7020 @FocusableMode int focusableMode) { 7021 if (views == null) { 7022 return; 7023 } 7024 if (!isFocusable()) { 7025 return; 7026 } 7027 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 7028 && isInTouchMode() && !isFocusableInTouchMode()) { 7029 return; 7030 } 7031 views.add(this); 7032 } 7033 7034 /** 7035 * Finds the Views that contain given text. The containment is case insensitive. 7036 * The search is performed by either the text that the View renders or the content 7037 * description that describes the view for accessibility purposes and the view does 7038 * not render or both. Clients can specify how the search is to be performed via 7039 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 7040 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 7041 * 7042 * @param outViews The output list of matching Views. 7043 * @param searched The text to match against. 7044 * 7045 * @see #FIND_VIEWS_WITH_TEXT 7046 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 7047 * @see #setContentDescription(CharSequence) 7048 */ 7049 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, 7050 @FindViewFlags int flags) { 7051 if (getAccessibilityNodeProvider() != null) { 7052 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 7053 outViews.add(this); 7054 } 7055 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 7056 && (searched != null && searched.length() > 0) 7057 && (mContentDescription != null && mContentDescription.length() > 0)) { 7058 String searchedLowerCase = searched.toString().toLowerCase(); 7059 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 7060 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 7061 outViews.add(this); 7062 } 7063 } 7064 } 7065 7066 /** 7067 * Find and return all touchable views that are descendants of this view, 7068 * possibly including this view if it is touchable itself. 7069 * 7070 * @return A list of touchable views 7071 */ 7072 public ArrayList<View> getTouchables() { 7073 ArrayList<View> result = new ArrayList<View>(); 7074 addTouchables(result); 7075 return result; 7076 } 7077 7078 /** 7079 * Add any touchable views that are descendants of this view (possibly 7080 * including this view if it is touchable itself) to views. 7081 * 7082 * @param views Touchable views found so far 7083 */ 7084 public void addTouchables(ArrayList<View> views) { 7085 final int viewFlags = mViewFlags; 7086 7087 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 7088 && (viewFlags & ENABLED_MASK) == ENABLED) { 7089 views.add(this); 7090 } 7091 } 7092 7093 /** 7094 * Returns whether this View is accessibility focused. 7095 * 7096 * @return True if this View is accessibility focused. 7097 */ 7098 public boolean isAccessibilityFocused() { 7099 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 7100 } 7101 7102 /** 7103 * Call this to try to give accessibility focus to this view. 7104 * 7105 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 7106 * returns false or the view is no visible or the view already has accessibility 7107 * focus. 7108 * 7109 * See also {@link #focusSearch(int)}, which is what you call to say that you 7110 * have focus, and you want your parent to look for the next one. 7111 * 7112 * @return Whether this view actually took accessibility focus. 7113 * 7114 * @hide 7115 */ 7116 public boolean requestAccessibilityFocus() { 7117 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 7118 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 7119 return false; 7120 } 7121 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 7122 return false; 7123 } 7124 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 7125 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 7126 ViewRootImpl viewRootImpl = getViewRootImpl(); 7127 if (viewRootImpl != null) { 7128 viewRootImpl.setAccessibilityFocus(this, null); 7129 } 7130 invalidate(); 7131 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 7132 return true; 7133 } 7134 return false; 7135 } 7136 7137 /** 7138 * Call this to try to clear accessibility focus of this view. 7139 * 7140 * See also {@link #focusSearch(int)}, which is what you call to say that you 7141 * have focus, and you want your parent to look for the next one. 7142 * 7143 * @hide 7144 */ 7145 public void clearAccessibilityFocus() { 7146 clearAccessibilityFocusNoCallbacks(); 7147 // Clear the global reference of accessibility focus if this 7148 // view or any of its descendants had accessibility focus. 7149 ViewRootImpl viewRootImpl = getViewRootImpl(); 7150 if (viewRootImpl != null) { 7151 View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 7152 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 7153 viewRootImpl.setAccessibilityFocus(null, null); 7154 } 7155 } 7156 } 7157 7158 private void sendAccessibilityHoverEvent(int eventType) { 7159 // Since we are not delivering to a client accessibility events from not 7160 // important views (unless the clinet request that) we need to fire the 7161 // event from the deepest view exposed to the client. As a consequence if 7162 // the user crosses a not exposed view the client will see enter and exit 7163 // of the exposed predecessor followed by and enter and exit of that same 7164 // predecessor when entering and exiting the not exposed descendant. This 7165 // is fine since the client has a clear idea which view is hovered at the 7166 // price of a couple more events being sent. This is a simple and 7167 // working solution. 7168 View source = this; 7169 while (true) { 7170 if (source.includeForAccessibility()) { 7171 source.sendAccessibilityEvent(eventType); 7172 return; 7173 } 7174 ViewParent parent = source.getParent(); 7175 if (parent instanceof View) { 7176 source = (View) parent; 7177 } else { 7178 return; 7179 } 7180 } 7181 } 7182 7183 /** 7184 * Clears accessibility focus without calling any callback methods 7185 * normally invoked in {@link #clearAccessibilityFocus()}. This method 7186 * is used for clearing accessibility focus when giving this focus to 7187 * another view. 7188 */ 7189 void clearAccessibilityFocusNoCallbacks() { 7190 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 7191 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 7192 invalidate(); 7193 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 7194 } 7195 } 7196 7197 /** 7198 * Call this to try to give focus to a specific view or to one of its 7199 * descendants. 7200 * 7201 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 7202 * false), or if it is focusable and it is not focusable in touch mode 7203 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 7204 * 7205 * See also {@link #focusSearch(int)}, which is what you call to say that you 7206 * have focus, and you want your parent to look for the next one. 7207 * 7208 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 7209 * {@link #FOCUS_DOWN} and <code>null</code>. 7210 * 7211 * @return Whether this view or one of its descendants actually took focus. 7212 */ 7213 public final boolean requestFocus() { 7214 return requestFocus(View.FOCUS_DOWN); 7215 } 7216 7217 /** 7218 * Call this to try to give focus to a specific view or to one of its 7219 * descendants and give it a hint about what direction focus is heading. 7220 * 7221 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 7222 * false), or if it is focusable and it is not focusable in touch mode 7223 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 7224 * 7225 * See also {@link #focusSearch(int)}, which is what you call to say that you 7226 * have focus, and you want your parent to look for the next one. 7227 * 7228 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 7229 * <code>null</code> set for the previously focused rectangle. 7230 * 7231 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 7232 * @return Whether this view or one of its descendants actually took focus. 7233 */ 7234 public final boolean requestFocus(int direction) { 7235 return requestFocus(direction, null); 7236 } 7237 7238 /** 7239 * Call this to try to give focus to a specific view or to one of its descendants 7240 * and give it hints about the direction and a specific rectangle that the focus 7241 * is coming from. The rectangle can help give larger views a finer grained hint 7242 * about where focus is coming from, and therefore, where to show selection, or 7243 * forward focus change internally. 7244 * 7245 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 7246 * false), or if it is focusable and it is not focusable in touch mode 7247 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 7248 * 7249 * A View will not take focus if it is not visible. 7250 * 7251 * A View will not take focus if one of its parents has 7252 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 7253 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 7254 * 7255 * See also {@link #focusSearch(int)}, which is what you call to say that you 7256 * have focus, and you want your parent to look for the next one. 7257 * 7258 * You may wish to override this method if your custom {@link View} has an internal 7259 * {@link View} that it wishes to forward the request to. 7260 * 7261 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 7262 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 7263 * to give a finer grained hint about where focus is coming from. May be null 7264 * if there is no hint. 7265 * @return Whether this view or one of its descendants actually took focus. 7266 */ 7267 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 7268 return requestFocusNoSearch(direction, previouslyFocusedRect); 7269 } 7270 7271 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 7272 // need to be focusable 7273 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 7274 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 7275 return false; 7276 } 7277 7278 // need to be focusable in touch mode if in touch mode 7279 if (isInTouchMode() && 7280 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 7281 return false; 7282 } 7283 7284 // need to not have any parents blocking us 7285 if (hasAncestorThatBlocksDescendantFocus()) { 7286 return false; 7287 } 7288 7289 handleFocusGainInternal(direction, previouslyFocusedRect); 7290 return true; 7291 } 7292 7293 /** 7294 * Call this to try to give focus to a specific view or to one of its descendants. This is a 7295 * special variant of {@link #requestFocus() } that will allow views that are not focuable in 7296 * touch mode to request focus when they are touched. 7297 * 7298 * @return Whether this view or one of its descendants actually took focus. 7299 * 7300 * @see #isInTouchMode() 7301 * 7302 */ 7303 public final boolean requestFocusFromTouch() { 7304 // Leave touch mode if we need to 7305 if (isInTouchMode()) { 7306 ViewRootImpl viewRoot = getViewRootImpl(); 7307 if (viewRoot != null) { 7308 viewRoot.ensureTouchMode(false); 7309 } 7310 } 7311 return requestFocus(View.FOCUS_DOWN); 7312 } 7313 7314 /** 7315 * @return Whether any ancestor of this view blocks descendant focus. 7316 */ 7317 private boolean hasAncestorThatBlocksDescendantFocus() { 7318 ViewParent ancestor = mParent; 7319 while (ancestor instanceof ViewGroup) { 7320 final ViewGroup vgAncestor = (ViewGroup) ancestor; 7321 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { 7322 return true; 7323 } else { 7324 ancestor = vgAncestor.getParent(); 7325 } 7326 } 7327 return false; 7328 } 7329 7330 /** 7331 * Gets the mode for determining whether this View is important for accessibility 7332 * which is if it fires accessibility events and if it is reported to 7333 * accessibility services that query the screen. 7334 * 7335 * @return The mode for determining whether a View is important for accessibility. 7336 * 7337 * @attr ref android.R.styleable#View_importantForAccessibility 7338 * 7339 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 7340 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 7341 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 7342 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 7343 */ 7344 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 7345 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 7346 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 7347 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 7348 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 7349 to = "noHideDescendants") 7350 }) 7351 public int getImportantForAccessibility() { 7352 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 7353 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 7354 } 7355 7356 /** 7357 * Sets the live region mode for this view. This indicates to accessibility 7358 * services whether they should automatically notify the user about changes 7359 * to the view's content description or text, or to the content descriptions 7360 * or text of the view's children (where applicable). 7361 * <p> 7362 * For example, in a login screen with a TextView that displays an "incorrect 7363 * password" notification, that view should be marked as a live region with 7364 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 7365 * <p> 7366 * To disable change notifications for this view, use 7367 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 7368 * mode for most views. 7369 * <p> 7370 * To indicate that the user should be notified of changes, use 7371 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 7372 * <p> 7373 * If the view's changes should interrupt ongoing speech and notify the user 7374 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 7375 * 7376 * @param mode The live region mode for this view, one of: 7377 * <ul> 7378 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 7379 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 7380 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 7381 * </ul> 7382 * @attr ref android.R.styleable#View_accessibilityLiveRegion 7383 */ 7384 public void setAccessibilityLiveRegion(int mode) { 7385 if (mode != getAccessibilityLiveRegion()) { 7386 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 7387 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 7388 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 7389 notifyViewAccessibilityStateChangedIfNeeded( 7390 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7391 } 7392 } 7393 7394 /** 7395 * Gets the live region mode for this View. 7396 * 7397 * @return The live region mode for the view. 7398 * 7399 * @attr ref android.R.styleable#View_accessibilityLiveRegion 7400 * 7401 * @see #setAccessibilityLiveRegion(int) 7402 */ 7403 public int getAccessibilityLiveRegion() { 7404 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 7405 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 7406 } 7407 7408 /** 7409 * Sets how to determine whether this view is important for accessibility 7410 * which is if it fires accessibility events and if it is reported to 7411 * accessibility services that query the screen. 7412 * 7413 * @param mode How to determine whether this view is important for accessibility. 7414 * 7415 * @attr ref android.R.styleable#View_importantForAccessibility 7416 * 7417 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 7418 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 7419 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 7420 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 7421 */ 7422 public void setImportantForAccessibility(int mode) { 7423 final int oldMode = getImportantForAccessibility(); 7424 if (mode != oldMode) { 7425 // If we're moving between AUTO and another state, we might not need 7426 // to send a subtree changed notification. We'll store the computed 7427 // importance, since we'll need to check it later to make sure. 7428 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 7429 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 7430 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 7431 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 7432 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 7433 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 7434 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 7435 notifySubtreeAccessibilityStateChangedIfNeeded(); 7436 } else { 7437 notifyViewAccessibilityStateChangedIfNeeded( 7438 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7439 } 7440 } 7441 } 7442 7443 /** 7444 * Computes whether this view should be exposed for accessibility. In 7445 * general, views that are interactive or provide information are exposed 7446 * while views that serve only as containers are hidden. 7447 * <p> 7448 * If an ancestor of this view has importance 7449 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method 7450 * returns <code>false</code>. 7451 * <p> 7452 * Otherwise, the value is computed according to the view's 7453 * {@link #getImportantForAccessibility()} value: 7454 * <ol> 7455 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or 7456 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false 7457 * </code> 7458 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code> 7459 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if 7460 * view satisfies any of the following: 7461 * <ul> 7462 * <li>Is actionable, e.g. {@link #isClickable()}, 7463 * {@link #isLongClickable()}, or {@link #isFocusable()} 7464 * <li>Has an {@link AccessibilityDelegate} 7465 * <li>Has an interaction listener, e.g. {@link OnTouchListener}, 7466 * {@link OnKeyListener}, etc. 7467 * <li>Is an accessibility live region, e.g. 7468 * {@link #getAccessibilityLiveRegion()} is not 7469 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. 7470 * </ul> 7471 * </ol> 7472 * 7473 * @return Whether the view is exposed for accessibility. 7474 * @see #setImportantForAccessibility(int) 7475 * @see #getImportantForAccessibility() 7476 */ 7477 public boolean isImportantForAccessibility() { 7478 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 7479 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 7480 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 7481 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 7482 return false; 7483 } 7484 7485 // Check parent mode to ensure we're not hidden. 7486 ViewParent parent = mParent; 7487 while (parent instanceof View) { 7488 if (((View) parent).getImportantForAccessibility() 7489 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 7490 return false; 7491 } 7492 parent = parent.getParent(); 7493 } 7494 7495 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 7496 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 7497 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE; 7498 } 7499 7500 /** 7501 * Gets the parent for accessibility purposes. Note that the parent for 7502 * accessibility is not necessary the immediate parent. It is the first 7503 * predecessor that is important for accessibility. 7504 * 7505 * @return The parent for accessibility purposes. 7506 */ 7507 public ViewParent getParentForAccessibility() { 7508 if (mParent instanceof View) { 7509 View parentView = (View) mParent; 7510 if (parentView.includeForAccessibility()) { 7511 return mParent; 7512 } else { 7513 return mParent.getParentForAccessibility(); 7514 } 7515 } 7516 return null; 7517 } 7518 7519 /** 7520 * Adds the children of a given View for accessibility. Since some Views are 7521 * not important for accessibility the children for accessibility are not 7522 * necessarily direct children of the view, rather they are the first level of 7523 * descendants important for accessibility. 7524 * 7525 * @param children The list of children for accessibility. 7526 */ 7527 public void addChildrenForAccessibility(ArrayList<View> children) { 7528 7529 } 7530 7531 /** 7532 * Whether to regard this view for accessibility. A view is regarded for 7533 * accessibility if it is important for accessibility or the querying 7534 * accessibility service has explicitly requested that view not 7535 * important for accessibility are regarded. 7536 * 7537 * @return Whether to regard the view for accessibility. 7538 * 7539 * @hide 7540 */ 7541 public boolean includeForAccessibility() { 7542 if (mAttachInfo != null) { 7543 return (mAttachInfo.mAccessibilityFetchFlags 7544 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 7545 || isImportantForAccessibility(); 7546 } 7547 return false; 7548 } 7549 7550 /** 7551 * Returns whether the View is considered actionable from 7552 * accessibility perspective. Such view are important for 7553 * accessibility. 7554 * 7555 * @return True if the view is actionable for accessibility. 7556 * 7557 * @hide 7558 */ 7559 public boolean isActionableForAccessibility() { 7560 return (isClickable() || isLongClickable() || isFocusable()); 7561 } 7562 7563 /** 7564 * Returns whether the View has registered callbacks which makes it 7565 * important for accessibility. 7566 * 7567 * @return True if the view is actionable for accessibility. 7568 */ 7569 private boolean hasListenersForAccessibility() { 7570 ListenerInfo info = getListenerInfo(); 7571 return mTouchDelegate != null || info.mOnKeyListener != null 7572 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 7573 || info.mOnHoverListener != null || info.mOnDragListener != null; 7574 } 7575 7576 /** 7577 * Notifies that the accessibility state of this view changed. The change 7578 * is local to this view and does not represent structural changes such 7579 * as children and parent. For example, the view became focusable. The 7580 * notification is at at most once every 7581 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 7582 * to avoid unnecessary load to the system. Also once a view has a pending 7583 * notification this method is a NOP until the notification has been sent. 7584 * 7585 * @hide 7586 */ 7587 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 7588 if (!AccessibilityManager.getInstance(mContext).isEnabled()) { 7589 return; 7590 } 7591 if (mSendViewStateChangedAccessibilityEvent == null) { 7592 mSendViewStateChangedAccessibilityEvent = 7593 new SendViewStateChangedAccessibilityEvent(); 7594 } 7595 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType); 7596 } 7597 7598 /** 7599 * Notifies that the accessibility state of this view changed. The change 7600 * is *not* local to this view and does represent structural changes such 7601 * as children and parent. For example, the view size changed. The 7602 * notification is at at most once every 7603 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 7604 * to avoid unnecessary load to the system. Also once a view has a pending 7605 * notifucation this method is a NOP until the notification has been sent. 7606 * 7607 * @hide 7608 */ 7609 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 7610 if (!AccessibilityManager.getInstance(mContext).isEnabled()) { 7611 return; 7612 } 7613 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 7614 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 7615 if (mParent != null) { 7616 try { 7617 mParent.notifySubtreeAccessibilityStateChanged( 7618 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 7619 } catch (AbstractMethodError e) { 7620 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 7621 " does not fully implement ViewParent", e); 7622 } 7623 } 7624 } 7625 } 7626 7627 /** 7628 * Reset the flag indicating the accessibility state of the subtree rooted 7629 * at this view changed. 7630 */ 7631 void resetSubtreeAccessibilityStateChanged() { 7632 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 7633 } 7634 7635 /** 7636 * Performs the specified accessibility action on the view. For 7637 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 7638 * <p> 7639 * If an {@link AccessibilityDelegate} has been specified via calling 7640 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 7641 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 7642 * is responsible for handling this call. 7643 * </p> 7644 * 7645 * @param action The action to perform. 7646 * @param arguments Optional action arguments. 7647 * @return Whether the action was performed. 7648 */ 7649 public boolean performAccessibilityAction(int action, Bundle arguments) { 7650 if (mAccessibilityDelegate != null) { 7651 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 7652 } else { 7653 return performAccessibilityActionInternal(action, arguments); 7654 } 7655 } 7656 7657 /** 7658 * @see #performAccessibilityAction(int, Bundle) 7659 * 7660 * Note: Called from the default {@link AccessibilityDelegate}. 7661 */ 7662 boolean performAccessibilityActionInternal(int action, Bundle arguments) { 7663 switch (action) { 7664 case AccessibilityNodeInfo.ACTION_CLICK: { 7665 if (isClickable()) { 7666 performClick(); 7667 return true; 7668 } 7669 } break; 7670 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 7671 if (isLongClickable()) { 7672 performLongClick(); 7673 return true; 7674 } 7675 } break; 7676 case AccessibilityNodeInfo.ACTION_FOCUS: { 7677 if (!hasFocus()) { 7678 // Get out of touch mode since accessibility 7679 // wants to move focus around. 7680 getViewRootImpl().ensureTouchMode(false); 7681 return requestFocus(); 7682 } 7683 } break; 7684 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 7685 if (hasFocus()) { 7686 clearFocus(); 7687 return !isFocused(); 7688 } 7689 } break; 7690 case AccessibilityNodeInfo.ACTION_SELECT: { 7691 if (!isSelected()) { 7692 setSelected(true); 7693 return isSelected(); 7694 } 7695 } break; 7696 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 7697 if (isSelected()) { 7698 setSelected(false); 7699 return !isSelected(); 7700 } 7701 } break; 7702 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 7703 if (!isAccessibilityFocused()) { 7704 return requestAccessibilityFocus(); 7705 } 7706 } break; 7707 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 7708 if (isAccessibilityFocused()) { 7709 clearAccessibilityFocus(); 7710 return true; 7711 } 7712 } break; 7713 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 7714 if (arguments != null) { 7715 final int granularity = arguments.getInt( 7716 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 7717 final boolean extendSelection = arguments.getBoolean( 7718 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 7719 return traverseAtGranularity(granularity, true, extendSelection); 7720 } 7721 } break; 7722 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 7723 if (arguments != null) { 7724 final int granularity = arguments.getInt( 7725 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 7726 final boolean extendSelection = arguments.getBoolean( 7727 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 7728 return traverseAtGranularity(granularity, false, extendSelection); 7729 } 7730 } break; 7731 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 7732 CharSequence text = getIterableTextForAccessibility(); 7733 if (text == null) { 7734 return false; 7735 } 7736 final int start = (arguments != null) ? arguments.getInt( 7737 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 7738 final int end = (arguments != null) ? arguments.getInt( 7739 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 7740 // Only cursor position can be specified (selection length == 0) 7741 if ((getAccessibilitySelectionStart() != start 7742 || getAccessibilitySelectionEnd() != end) 7743 && (start == end)) { 7744 setAccessibilitySelection(start, end); 7745 notifyViewAccessibilityStateChangedIfNeeded( 7746 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7747 return true; 7748 } 7749 } break; 7750 } 7751 return false; 7752 } 7753 7754 private boolean traverseAtGranularity(int granularity, boolean forward, 7755 boolean extendSelection) { 7756 CharSequence text = getIterableTextForAccessibility(); 7757 if (text == null || text.length() == 0) { 7758 return false; 7759 } 7760 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 7761 if (iterator == null) { 7762 return false; 7763 } 7764 int current = getAccessibilitySelectionEnd(); 7765 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 7766 current = forward ? 0 : text.length(); 7767 } 7768 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 7769 if (range == null) { 7770 return false; 7771 } 7772 final int segmentStart = range[0]; 7773 final int segmentEnd = range[1]; 7774 int selectionStart; 7775 int selectionEnd; 7776 if (extendSelection && isAccessibilitySelectionExtendable()) { 7777 selectionStart = getAccessibilitySelectionStart(); 7778 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 7779 selectionStart = forward ? segmentStart : segmentEnd; 7780 } 7781 selectionEnd = forward ? segmentEnd : segmentStart; 7782 } else { 7783 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 7784 } 7785 setAccessibilitySelection(selectionStart, selectionEnd); 7786 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 7787 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 7788 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 7789 return true; 7790 } 7791 7792 /** 7793 * Gets the text reported for accessibility purposes. 7794 * 7795 * @return The accessibility text. 7796 * 7797 * @hide 7798 */ 7799 public CharSequence getIterableTextForAccessibility() { 7800 return getContentDescription(); 7801 } 7802 7803 /** 7804 * Gets whether accessibility selection can be extended. 7805 * 7806 * @return If selection is extensible. 7807 * 7808 * @hide 7809 */ 7810 public boolean isAccessibilitySelectionExtendable() { 7811 return false; 7812 } 7813 7814 /** 7815 * @hide 7816 */ 7817 public int getAccessibilitySelectionStart() { 7818 return mAccessibilityCursorPosition; 7819 } 7820 7821 /** 7822 * @hide 7823 */ 7824 public int getAccessibilitySelectionEnd() { 7825 return getAccessibilitySelectionStart(); 7826 } 7827 7828 /** 7829 * @hide 7830 */ 7831 public void setAccessibilitySelection(int start, int end) { 7832 if (start == end && end == mAccessibilityCursorPosition) { 7833 return; 7834 } 7835 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 7836 mAccessibilityCursorPosition = start; 7837 } else { 7838 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 7839 } 7840 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 7841 } 7842 7843 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 7844 int fromIndex, int toIndex) { 7845 if (mParent == null) { 7846 return; 7847 } 7848 AccessibilityEvent event = AccessibilityEvent.obtain( 7849 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 7850 onInitializeAccessibilityEvent(event); 7851 onPopulateAccessibilityEvent(event); 7852 event.setFromIndex(fromIndex); 7853 event.setToIndex(toIndex); 7854 event.setAction(action); 7855 event.setMovementGranularity(granularity); 7856 mParent.requestSendAccessibilityEvent(this, event); 7857 } 7858 7859 /** 7860 * @hide 7861 */ 7862 public TextSegmentIterator getIteratorForGranularity(int granularity) { 7863 switch (granularity) { 7864 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 7865 CharSequence text = getIterableTextForAccessibility(); 7866 if (text != null && text.length() > 0) { 7867 CharacterTextSegmentIterator iterator = 7868 CharacterTextSegmentIterator.getInstance( 7869 mContext.getResources().getConfiguration().locale); 7870 iterator.initialize(text.toString()); 7871 return iterator; 7872 } 7873 } break; 7874 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 7875 CharSequence text = getIterableTextForAccessibility(); 7876 if (text != null && text.length() > 0) { 7877 WordTextSegmentIterator iterator = 7878 WordTextSegmentIterator.getInstance( 7879 mContext.getResources().getConfiguration().locale); 7880 iterator.initialize(text.toString()); 7881 return iterator; 7882 } 7883 } break; 7884 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 7885 CharSequence text = getIterableTextForAccessibility(); 7886 if (text != null && text.length() > 0) { 7887 ParagraphTextSegmentIterator iterator = 7888 ParagraphTextSegmentIterator.getInstance(); 7889 iterator.initialize(text.toString()); 7890 return iterator; 7891 } 7892 } break; 7893 } 7894 return null; 7895 } 7896 7897 /** 7898 * @hide 7899 */ 7900 public void dispatchStartTemporaryDetach() { 7901 onStartTemporaryDetach(); 7902 } 7903 7904 /** 7905 * This is called when a container is going to temporarily detach a child, with 7906 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 7907 * It will either be followed by {@link #onFinishTemporaryDetach()} or 7908 * {@link #onDetachedFromWindow()} when the container is done. 7909 */ 7910 public void onStartTemporaryDetach() { 7911 removeUnsetPressCallback(); 7912 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 7913 } 7914 7915 /** 7916 * @hide 7917 */ 7918 public void dispatchFinishTemporaryDetach() { 7919 onFinishTemporaryDetach(); 7920 } 7921 7922 /** 7923 * Called after {@link #onStartTemporaryDetach} when the container is done 7924 * changing the view. 7925 */ 7926 public void onFinishTemporaryDetach() { 7927 } 7928 7929 /** 7930 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 7931 * for this view's window. Returns null if the view is not currently attached 7932 * to the window. Normally you will not need to use this directly, but 7933 * just use the standard high-level event callbacks like 7934 * {@link #onKeyDown(int, KeyEvent)}. 7935 */ 7936 public KeyEvent.DispatcherState getKeyDispatcherState() { 7937 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 7938 } 7939 7940 /** 7941 * Dispatch a key event before it is processed by any input method 7942 * associated with the view hierarchy. This can be used to intercept 7943 * key events in special situations before the IME consumes them; a 7944 * typical example would be handling the BACK key to update the application's 7945 * UI instead of allowing the IME to see it and close itself. 7946 * 7947 * @param event The key event to be dispatched. 7948 * @return True if the event was handled, false otherwise. 7949 */ 7950 public boolean dispatchKeyEventPreIme(KeyEvent event) { 7951 return onKeyPreIme(event.getKeyCode(), event); 7952 } 7953 7954 /** 7955 * Dispatch a key event to the next view on the focus path. This path runs 7956 * from the top of the view tree down to the currently focused view. If this 7957 * view has focus, it will dispatch to itself. Otherwise it will dispatch 7958 * the next node down the focus path. This method also fires any key 7959 * listeners. 7960 * 7961 * @param event The key event to be dispatched. 7962 * @return True if the event was handled, false otherwise. 7963 */ 7964 public boolean dispatchKeyEvent(KeyEvent event) { 7965 if (mInputEventConsistencyVerifier != null) { 7966 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 7967 } 7968 7969 // Give any attached key listener a first crack at the event. 7970 //noinspection SimplifiableIfStatement 7971 ListenerInfo li = mListenerInfo; 7972 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 7973 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 7974 return true; 7975 } 7976 7977 if (event.dispatch(this, mAttachInfo != null 7978 ? mAttachInfo.mKeyDispatchState : null, this)) { 7979 return true; 7980 } 7981 7982 if (mInputEventConsistencyVerifier != null) { 7983 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 7984 } 7985 return false; 7986 } 7987 7988 /** 7989 * Dispatches a key shortcut event. 7990 * 7991 * @param event The key event to be dispatched. 7992 * @return True if the event was handled by the view, false otherwise. 7993 */ 7994 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7995 return onKeyShortcut(event.getKeyCode(), event); 7996 } 7997 7998 /** 7999 * Pass the touch screen motion event down to the target view, or this 8000 * view if it is the target. 8001 * 8002 * @param event The motion event to be dispatched. 8003 * @return True if the event was handled by the view, false otherwise. 8004 */ 8005 public boolean dispatchTouchEvent(MotionEvent event) { 8006 boolean result = false; 8007 8008 if (mInputEventConsistencyVerifier != null) { 8009 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 8010 } 8011 8012 final int actionMasked = event.getActionMasked(); 8013 if (actionMasked == MotionEvent.ACTION_DOWN) { 8014 // Defensive cleanup for new gesture 8015 stopNestedScroll(); 8016 } 8017 8018 if (onFilterTouchEventForSecurity(event)) { 8019 //noinspection SimplifiableIfStatement 8020 ListenerInfo li = mListenerInfo; 8021 if (li != null && li.mOnTouchListener != null 8022 && (mViewFlags & ENABLED_MASK) == ENABLED 8023 && li.mOnTouchListener.onTouch(this, event)) { 8024 result = true; 8025 } 8026 8027 if (!result && onTouchEvent(event)) { 8028 result = true; 8029 } 8030 } 8031 8032 if (!result && mInputEventConsistencyVerifier != null) { 8033 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 8034 } 8035 8036 // Clean up after nested scrolls if this is the end of a gesture; 8037 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest 8038 // of the gesture. 8039 if (actionMasked == MotionEvent.ACTION_UP || 8040 actionMasked == MotionEvent.ACTION_CANCEL || 8041 (actionMasked == MotionEvent.ACTION_DOWN && !result)) { 8042 stopNestedScroll(); 8043 } 8044 8045 return result; 8046 } 8047 8048 /** 8049 * Filter the touch event to apply security policies. 8050 * 8051 * @param event The motion event to be filtered. 8052 * @return True if the event should be dispatched, false if the event should be dropped. 8053 * 8054 * @see #getFilterTouchesWhenObscured 8055 */ 8056 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 8057 //noinspection RedundantIfStatement 8058 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 8059 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 8060 // Window is obscured, drop this touch. 8061 return false; 8062 } 8063 return true; 8064 } 8065 8066 /** 8067 * Pass a trackball motion event down to the focused view. 8068 * 8069 * @param event The motion event to be dispatched. 8070 * @return True if the event was handled by the view, false otherwise. 8071 */ 8072 public boolean dispatchTrackballEvent(MotionEvent event) { 8073 if (mInputEventConsistencyVerifier != null) { 8074 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 8075 } 8076 8077 return onTrackballEvent(event); 8078 } 8079 8080 /** 8081 * Dispatch a generic motion event. 8082 * <p> 8083 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 8084 * are delivered to the view under the pointer. All other generic motion events are 8085 * delivered to the focused view. Hover events are handled specially and are delivered 8086 * to {@link #onHoverEvent(MotionEvent)}. 8087 * </p> 8088 * 8089 * @param event The motion event to be dispatched. 8090 * @return True if the event was handled by the view, false otherwise. 8091 */ 8092 public boolean dispatchGenericMotionEvent(MotionEvent event) { 8093 if (mInputEventConsistencyVerifier != null) { 8094 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 8095 } 8096 8097 final int source = event.getSource(); 8098 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 8099 final int action = event.getAction(); 8100 if (action == MotionEvent.ACTION_HOVER_ENTER 8101 || action == MotionEvent.ACTION_HOVER_MOVE 8102 || action == MotionEvent.ACTION_HOVER_EXIT) { 8103 if (dispatchHoverEvent(event)) { 8104 return true; 8105 } 8106 } else if (dispatchGenericPointerEvent(event)) { 8107 return true; 8108 } 8109 } else if (dispatchGenericFocusedEvent(event)) { 8110 return true; 8111 } 8112 8113 if (dispatchGenericMotionEventInternal(event)) { 8114 return true; 8115 } 8116 8117 if (mInputEventConsistencyVerifier != null) { 8118 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 8119 } 8120 return false; 8121 } 8122 8123 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 8124 //noinspection SimplifiableIfStatement 8125 ListenerInfo li = mListenerInfo; 8126 if (li != null && li.mOnGenericMotionListener != null 8127 && (mViewFlags & ENABLED_MASK) == ENABLED 8128 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 8129 return true; 8130 } 8131 8132 if (onGenericMotionEvent(event)) { 8133 return true; 8134 } 8135 8136 if (mInputEventConsistencyVerifier != null) { 8137 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 8138 } 8139 return false; 8140 } 8141 8142 /** 8143 * Dispatch a hover event. 8144 * <p> 8145 * Do not call this method directly. 8146 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 8147 * </p> 8148 * 8149 * @param event The motion event to be dispatched. 8150 * @return True if the event was handled by the view, false otherwise. 8151 */ 8152 protected boolean dispatchHoverEvent(MotionEvent event) { 8153 ListenerInfo li = mListenerInfo; 8154 //noinspection SimplifiableIfStatement 8155 if (li != null && li.mOnHoverListener != null 8156 && (mViewFlags & ENABLED_MASK) == ENABLED 8157 && li.mOnHoverListener.onHover(this, event)) { 8158 return true; 8159 } 8160 8161 return onHoverEvent(event); 8162 } 8163 8164 /** 8165 * Returns true if the view has a child to which it has recently sent 8166 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 8167 * it does not have a hovered child, then it must be the innermost hovered view. 8168 * @hide 8169 */ 8170 protected boolean hasHoveredChild() { 8171 return false; 8172 } 8173 8174 /** 8175 * Dispatch a generic motion event to the view under the first pointer. 8176 * <p> 8177 * Do not call this method directly. 8178 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 8179 * </p> 8180 * 8181 * @param event The motion event to be dispatched. 8182 * @return True if the event was handled by the view, false otherwise. 8183 */ 8184 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 8185 return false; 8186 } 8187 8188 /** 8189 * Dispatch a generic motion event to the currently focused view. 8190 * <p> 8191 * Do not call this method directly. 8192 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 8193 * </p> 8194 * 8195 * @param event The motion event to be dispatched. 8196 * @return True if the event was handled by the view, false otherwise. 8197 */ 8198 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 8199 return false; 8200 } 8201 8202 /** 8203 * Dispatch a pointer event. 8204 * <p> 8205 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 8206 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 8207 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 8208 * and should not be expected to handle other pointing device features. 8209 * </p> 8210 * 8211 * @param event The motion event to be dispatched. 8212 * @return True if the event was handled by the view, false otherwise. 8213 * @hide 8214 */ 8215 public final boolean dispatchPointerEvent(MotionEvent event) { 8216 if (event.isTouchEvent()) { 8217 return dispatchTouchEvent(event); 8218 } else { 8219 return dispatchGenericMotionEvent(event); 8220 } 8221 } 8222 8223 /** 8224 * Called when the window containing this view gains or loses window focus. 8225 * ViewGroups should override to route to their children. 8226 * 8227 * @param hasFocus True if the window containing this view now has focus, 8228 * false otherwise. 8229 */ 8230 public void dispatchWindowFocusChanged(boolean hasFocus) { 8231 onWindowFocusChanged(hasFocus); 8232 } 8233 8234 /** 8235 * Called when the window containing this view gains or loses focus. Note 8236 * that this is separate from view focus: to receive key events, both 8237 * your view and its window must have focus. If a window is displayed 8238 * on top of yours that takes input focus, then your own window will lose 8239 * focus but the view focus will remain unchanged. 8240 * 8241 * @param hasWindowFocus True if the window containing this view now has 8242 * focus, false otherwise. 8243 */ 8244 public void onWindowFocusChanged(boolean hasWindowFocus) { 8245 InputMethodManager imm = InputMethodManager.peekInstance(); 8246 if (!hasWindowFocus) { 8247 if (isPressed()) { 8248 setPressed(false); 8249 } 8250 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 8251 imm.focusOut(this); 8252 } 8253 removeLongPressCallback(); 8254 removeTapCallback(); 8255 onFocusLost(); 8256 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 8257 imm.focusIn(this); 8258 } 8259 refreshDrawableState(); 8260 } 8261 8262 /** 8263 * Returns true if this view is in a window that currently has window focus. 8264 * Note that this is not the same as the view itself having focus. 8265 * 8266 * @return True if this view is in a window that currently has window focus. 8267 */ 8268 public boolean hasWindowFocus() { 8269 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 8270 } 8271 8272 /** 8273 * Dispatch a view visibility change down the view hierarchy. 8274 * ViewGroups should override to route to their children. 8275 * @param changedView The view whose visibility changed. Could be 'this' or 8276 * an ancestor view. 8277 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 8278 * {@link #INVISIBLE} or {@link #GONE}. 8279 */ 8280 protected void dispatchVisibilityChanged(@NonNull View changedView, 8281 @Visibility int visibility) { 8282 onVisibilityChanged(changedView, visibility); 8283 } 8284 8285 /** 8286 * Called when the visibility of the view or an ancestor of the view is changed. 8287 * @param changedView The view whose visibility changed. Could be 'this' or 8288 * an ancestor view. 8289 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 8290 * {@link #INVISIBLE} or {@link #GONE}. 8291 */ 8292 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { 8293 if (visibility == VISIBLE) { 8294 if (mAttachInfo != null) { 8295 initialAwakenScrollBars(); 8296 } else { 8297 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH; 8298 } 8299 } 8300 } 8301 8302 /** 8303 * Dispatch a hint about whether this view is displayed. For instance, when 8304 * a View moves out of the screen, it might receives a display hint indicating 8305 * the view is not displayed. Applications should not <em>rely</em> on this hint 8306 * as there is no guarantee that they will receive one. 8307 * 8308 * @param hint A hint about whether or not this view is displayed: 8309 * {@link #VISIBLE} or {@link #INVISIBLE}. 8310 */ 8311 public void dispatchDisplayHint(@Visibility int hint) { 8312 onDisplayHint(hint); 8313 } 8314 8315 /** 8316 * Gives this view a hint about whether is displayed or not. For instance, when 8317 * a View moves out of the screen, it might receives a display hint indicating 8318 * the view is not displayed. Applications should not <em>rely</em> on this hint 8319 * as there is no guarantee that they will receive one. 8320 * 8321 * @param hint A hint about whether or not this view is displayed: 8322 * {@link #VISIBLE} or {@link #INVISIBLE}. 8323 */ 8324 protected void onDisplayHint(@Visibility int hint) { 8325 } 8326 8327 /** 8328 * Dispatch a window visibility change down the view hierarchy. 8329 * ViewGroups should override to route to their children. 8330 * 8331 * @param visibility The new visibility of the window. 8332 * 8333 * @see #onWindowVisibilityChanged(int) 8334 */ 8335 public void dispatchWindowVisibilityChanged(@Visibility int visibility) { 8336 onWindowVisibilityChanged(visibility); 8337 } 8338 8339 /** 8340 * Called when the window containing has change its visibility 8341 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 8342 * that this tells you whether or not your window is being made visible 8343 * to the window manager; this does <em>not</em> tell you whether or not 8344 * your window is obscured by other windows on the screen, even if it 8345 * is itself visible. 8346 * 8347 * @param visibility The new visibility of the window. 8348 */ 8349 protected void onWindowVisibilityChanged(@Visibility int visibility) { 8350 if (visibility == VISIBLE) { 8351 initialAwakenScrollBars(); 8352 } 8353 } 8354 8355 /** 8356 * Returns the current visibility of the window this view is attached to 8357 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 8358 * 8359 * @return Returns the current visibility of the view's window. 8360 */ 8361 @Visibility 8362 public int getWindowVisibility() { 8363 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 8364 } 8365 8366 /** 8367 * Retrieve the overall visible display size in which the window this view is 8368 * attached to has been positioned in. This takes into account screen 8369 * decorations above the window, for both cases where the window itself 8370 * is being position inside of them or the window is being placed under 8371 * then and covered insets are used for the window to position its content 8372 * inside. In effect, this tells you the available area where content can 8373 * be placed and remain visible to users. 8374 * 8375 * <p>This function requires an IPC back to the window manager to retrieve 8376 * the requested information, so should not be used in performance critical 8377 * code like drawing. 8378 * 8379 * @param outRect Filled in with the visible display frame. If the view 8380 * is not attached to a window, this is simply the raw display size. 8381 */ 8382 public void getWindowVisibleDisplayFrame(Rect outRect) { 8383 if (mAttachInfo != null) { 8384 try { 8385 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 8386 } catch (RemoteException e) { 8387 return; 8388 } 8389 // XXX This is really broken, and probably all needs to be done 8390 // in the window manager, and we need to know more about whether 8391 // we want the area behind or in front of the IME. 8392 final Rect insets = mAttachInfo.mVisibleInsets; 8393 outRect.left += insets.left; 8394 outRect.top += insets.top; 8395 outRect.right -= insets.right; 8396 outRect.bottom -= insets.bottom; 8397 return; 8398 } 8399 // The view is not attached to a display so we don't have a context. 8400 // Make a best guess about the display size. 8401 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 8402 d.getRectSize(outRect); 8403 } 8404 8405 /** 8406 * Dispatch a notification about a resource configuration change down 8407 * the view hierarchy. 8408 * ViewGroups should override to route to their children. 8409 * 8410 * @param newConfig The new resource configuration. 8411 * 8412 * @see #onConfigurationChanged(android.content.res.Configuration) 8413 */ 8414 public void dispatchConfigurationChanged(Configuration newConfig) { 8415 onConfigurationChanged(newConfig); 8416 } 8417 8418 /** 8419 * Called when the current configuration of the resources being used 8420 * by the application have changed. You can use this to decide when 8421 * to reload resources that can changed based on orientation and other 8422 * configuration characterstics. You only need to use this if you are 8423 * not relying on the normal {@link android.app.Activity} mechanism of 8424 * recreating the activity instance upon a configuration change. 8425 * 8426 * @param newConfig The new resource configuration. 8427 */ 8428 protected void onConfigurationChanged(Configuration newConfig) { 8429 } 8430 8431 /** 8432 * Private function to aggregate all per-view attributes in to the view 8433 * root. 8434 */ 8435 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 8436 performCollectViewAttributes(attachInfo, visibility); 8437 } 8438 8439 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 8440 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 8441 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 8442 attachInfo.mKeepScreenOn = true; 8443 } 8444 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 8445 ListenerInfo li = mListenerInfo; 8446 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 8447 attachInfo.mHasSystemUiListeners = true; 8448 } 8449 } 8450 } 8451 8452 void needGlobalAttributesUpdate(boolean force) { 8453 final AttachInfo ai = mAttachInfo; 8454 if (ai != null && !ai.mRecomputeGlobalAttributes) { 8455 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 8456 || ai.mHasSystemUiListeners) { 8457 ai.mRecomputeGlobalAttributes = true; 8458 } 8459 } 8460 } 8461 8462 /** 8463 * Returns whether the device is currently in touch mode. Touch mode is entered 8464 * once the user begins interacting with the device by touch, and affects various 8465 * things like whether focus is always visible to the user. 8466 * 8467 * @return Whether the device is in touch mode. 8468 */ 8469 @ViewDebug.ExportedProperty 8470 public boolean isInTouchMode() { 8471 if (mAttachInfo != null) { 8472 return mAttachInfo.mInTouchMode; 8473 } else { 8474 return ViewRootImpl.isInTouchMode(); 8475 } 8476 } 8477 8478 /** 8479 * Returns the context the view is running in, through which it can 8480 * access the current theme, resources, etc. 8481 * 8482 * @return The view's Context. 8483 */ 8484 @ViewDebug.CapturedViewProperty 8485 public final Context getContext() { 8486 return mContext; 8487 } 8488 8489 /** 8490 * Handle a key event before it is processed by any input method 8491 * associated with the view hierarchy. This can be used to intercept 8492 * key events in special situations before the IME consumes them; a 8493 * typical example would be handling the BACK key to update the application's 8494 * UI instead of allowing the IME to see it and close itself. 8495 * 8496 * @param keyCode The value in event.getKeyCode(). 8497 * @param event Description of the key event. 8498 * @return If you handled the event, return true. If you want to allow the 8499 * event to be handled by the next receiver, return false. 8500 */ 8501 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 8502 return false; 8503 } 8504 8505 /** 8506 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 8507 * KeyEvent.Callback.onKeyDown()}: perform press of the view 8508 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 8509 * is released, if the view is enabled and clickable. 8510 * 8511 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8512 * although some may elect to do so in some situations. Do not rely on this to 8513 * catch software key presses. 8514 * 8515 * @param keyCode A key code that represents the button pressed, from 8516 * {@link android.view.KeyEvent}. 8517 * @param event The KeyEvent object that defines the button action. 8518 */ 8519 public boolean onKeyDown(int keyCode, KeyEvent event) { 8520 boolean result = false; 8521 8522 if (KeyEvent.isConfirmKey(keyCode)) { 8523 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 8524 return true; 8525 } 8526 // Long clickable items don't necessarily have to be clickable 8527 if (((mViewFlags & CLICKABLE) == CLICKABLE || 8528 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && 8529 (event.getRepeatCount() == 0)) { 8530 setPressed(true); 8531 checkForLongClick(0); 8532 return true; 8533 } 8534 } 8535 return result; 8536 } 8537 8538 /** 8539 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 8540 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 8541 * the event). 8542 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8543 * although some may elect to do so in some situations. Do not rely on this to 8544 * catch software key presses. 8545 */ 8546 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 8547 return false; 8548 } 8549 8550 /** 8551 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 8552 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 8553 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or 8554 * {@link KeyEvent#KEYCODE_ENTER} is released. 8555 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8556 * although some may elect to do so in some situations. Do not rely on this to 8557 * catch software key presses. 8558 * 8559 * @param keyCode A key code that represents the button pressed, from 8560 * {@link android.view.KeyEvent}. 8561 * @param event The KeyEvent object that defines the button action. 8562 */ 8563 public boolean onKeyUp(int keyCode, KeyEvent event) { 8564 if (KeyEvent.isConfirmKey(keyCode)) { 8565 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 8566 return true; 8567 } 8568 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 8569 setPressed(false); 8570 8571 if (!mHasPerformedLongPress) { 8572 // This is a tap, so remove the longpress check 8573 removeLongPressCallback(); 8574 return performClick(); 8575 } 8576 } 8577 } 8578 return false; 8579 } 8580 8581 /** 8582 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 8583 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 8584 * the event). 8585 * <p>Key presses in software keyboards will generally NOT trigger this listener, 8586 * although some may elect to do so in some situations. Do not rely on this to 8587 * catch software key presses. 8588 * 8589 * @param keyCode A key code that represents the button pressed, from 8590 * {@link android.view.KeyEvent}. 8591 * @param repeatCount The number of times the action was made. 8592 * @param event The KeyEvent object that defines the button action. 8593 */ 8594 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 8595 return false; 8596 } 8597 8598 /** 8599 * Called on the focused view when a key shortcut event is not handled. 8600 * Override this method to implement local key shortcuts for the View. 8601 * Key shortcuts can also be implemented by setting the 8602 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 8603 * 8604 * @param keyCode The value in event.getKeyCode(). 8605 * @param event Description of the key event. 8606 * @return If you handled the event, return true. If you want to allow the 8607 * event to be handled by the next receiver, return false. 8608 */ 8609 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 8610 return false; 8611 } 8612 8613 /** 8614 * Check whether the called view is a text editor, in which case it 8615 * would make sense to automatically display a soft input window for 8616 * it. Subclasses should override this if they implement 8617 * {@link #onCreateInputConnection(EditorInfo)} to return true if 8618 * a call on that method would return a non-null InputConnection, and 8619 * they are really a first-class editor that the user would normally 8620 * start typing on when the go into a window containing your view. 8621 * 8622 * <p>The default implementation always returns false. This does 8623 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 8624 * will not be called or the user can not otherwise perform edits on your 8625 * view; it is just a hint to the system that this is not the primary 8626 * purpose of this view. 8627 * 8628 * @return Returns true if this view is a text editor, else false. 8629 */ 8630 public boolean onCheckIsTextEditor() { 8631 return false; 8632 } 8633 8634 /** 8635 * Create a new InputConnection for an InputMethod to interact 8636 * with the view. The default implementation returns null, since it doesn't 8637 * support input methods. You can override this to implement such support. 8638 * This is only needed for views that take focus and text input. 8639 * 8640 * <p>When implementing this, you probably also want to implement 8641 * {@link #onCheckIsTextEditor()} to indicate you will return a 8642 * non-null InputConnection.</p> 8643 * 8644 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo} 8645 * object correctly and in its entirety, so that the connected IME can rely 8646 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart} 8647 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members 8648 * must be filled in with the correct cursor position for IMEs to work correctly 8649 * with your application.</p> 8650 * 8651 * @param outAttrs Fill in with attribute information about the connection. 8652 */ 8653 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 8654 return null; 8655 } 8656 8657 /** 8658 * Called by the {@link android.view.inputmethod.InputMethodManager} 8659 * when a view who is not the current 8660 * input connection target is trying to make a call on the manager. The 8661 * default implementation returns false; you can override this to return 8662 * true for certain views if you are performing InputConnection proxying 8663 * to them. 8664 * @param view The View that is making the InputMethodManager call. 8665 * @return Return true to allow the call, false to reject. 8666 */ 8667 public boolean checkInputConnectionProxy(View view) { 8668 return false; 8669 } 8670 8671 /** 8672 * Show the context menu for this view. It is not safe to hold on to the 8673 * menu after returning from this method. 8674 * 8675 * You should normally not overload this method. Overload 8676 * {@link #onCreateContextMenu(ContextMenu)} or define an 8677 * {@link OnCreateContextMenuListener} to add items to the context menu. 8678 * 8679 * @param menu The context menu to populate 8680 */ 8681 public void createContextMenu(ContextMenu menu) { 8682 ContextMenuInfo menuInfo = getContextMenuInfo(); 8683 8684 // Sets the current menu info so all items added to menu will have 8685 // my extra info set. 8686 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 8687 8688 onCreateContextMenu(menu); 8689 ListenerInfo li = mListenerInfo; 8690 if (li != null && li.mOnCreateContextMenuListener != null) { 8691 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 8692 } 8693 8694 // Clear the extra information so subsequent items that aren't mine don't 8695 // have my extra info. 8696 ((MenuBuilder)menu).setCurrentMenuInfo(null); 8697 8698 if (mParent != null) { 8699 mParent.createContextMenu(menu); 8700 } 8701 } 8702 8703 /** 8704 * Views should implement this if they have extra information to associate 8705 * with the context menu. The return result is supplied as a parameter to 8706 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 8707 * callback. 8708 * 8709 * @return Extra information about the item for which the context menu 8710 * should be shown. This information will vary across different 8711 * subclasses of View. 8712 */ 8713 protected ContextMenuInfo getContextMenuInfo() { 8714 return null; 8715 } 8716 8717 /** 8718 * Views should implement this if the view itself is going to add items to 8719 * the context menu. 8720 * 8721 * @param menu the context menu to populate 8722 */ 8723 protected void onCreateContextMenu(ContextMenu menu) { 8724 } 8725 8726 /** 8727 * Implement this method to handle trackball motion events. The 8728 * <em>relative</em> movement of the trackball since the last event 8729 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 8730 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 8731 * that a movement of 1 corresponds to the user pressing one DPAD key (so 8732 * they will often be fractional values, representing the more fine-grained 8733 * movement information available from a trackball). 8734 * 8735 * @param event The motion event. 8736 * @return True if the event was handled, false otherwise. 8737 */ 8738 public boolean onTrackballEvent(MotionEvent event) { 8739 return false; 8740 } 8741 8742 /** 8743 * Implement this method to handle generic motion events. 8744 * <p> 8745 * Generic motion events describe joystick movements, mouse hovers, track pad 8746 * touches, scroll wheel movements and other input events. The 8747 * {@link MotionEvent#getSource() source} of the motion event specifies 8748 * the class of input that was received. Implementations of this method 8749 * must examine the bits in the source before processing the event. 8750 * The following code example shows how this is done. 8751 * </p><p> 8752 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 8753 * are delivered to the view under the pointer. All other generic motion events are 8754 * delivered to the focused view. 8755 * </p> 8756 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 8757 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 8758 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 8759 * // process the joystick movement... 8760 * return true; 8761 * } 8762 * } 8763 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 8764 * switch (event.getAction()) { 8765 * case MotionEvent.ACTION_HOVER_MOVE: 8766 * // process the mouse hover movement... 8767 * return true; 8768 * case MotionEvent.ACTION_SCROLL: 8769 * // process the scroll wheel movement... 8770 * return true; 8771 * } 8772 * } 8773 * return super.onGenericMotionEvent(event); 8774 * }</pre> 8775 * 8776 * @param event The generic motion event being processed. 8777 * @return True if the event was handled, false otherwise. 8778 */ 8779 public boolean onGenericMotionEvent(MotionEvent event) { 8780 return false; 8781 } 8782 8783 /** 8784 * Implement this method to handle hover events. 8785 * <p> 8786 * This method is called whenever a pointer is hovering into, over, or out of the 8787 * bounds of a view and the view is not currently being touched. 8788 * Hover events are represented as pointer events with action 8789 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 8790 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 8791 * </p> 8792 * <ul> 8793 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 8794 * when the pointer enters the bounds of the view.</li> 8795 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 8796 * when the pointer has already entered the bounds of the view and has moved.</li> 8797 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 8798 * when the pointer has exited the bounds of the view or when the pointer is 8799 * about to go down due to a button click, tap, or similar user action that 8800 * causes the view to be touched.</li> 8801 * </ul> 8802 * <p> 8803 * The view should implement this method to return true to indicate that it is 8804 * handling the hover event, such as by changing its drawable state. 8805 * </p><p> 8806 * The default implementation calls {@link #setHovered} to update the hovered state 8807 * of the view when a hover enter or hover exit event is received, if the view 8808 * is enabled and is clickable. The default implementation also sends hover 8809 * accessibility events. 8810 * </p> 8811 * 8812 * @param event The motion event that describes the hover. 8813 * @return True if the view handled the hover event. 8814 * 8815 * @see #isHovered 8816 * @see #setHovered 8817 * @see #onHoverChanged 8818 */ 8819 public boolean onHoverEvent(MotionEvent event) { 8820 // The root view may receive hover (or touch) events that are outside the bounds of 8821 // the window. This code ensures that we only send accessibility events for 8822 // hovers that are actually within the bounds of the root view. 8823 final int action = event.getActionMasked(); 8824 if (!mSendingHoverAccessibilityEvents) { 8825 if ((action == MotionEvent.ACTION_HOVER_ENTER 8826 || action == MotionEvent.ACTION_HOVER_MOVE) 8827 && !hasHoveredChild() 8828 && pointInView(event.getX(), event.getY())) { 8829 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 8830 mSendingHoverAccessibilityEvents = true; 8831 } 8832 } else { 8833 if (action == MotionEvent.ACTION_HOVER_EXIT 8834 || (action == MotionEvent.ACTION_MOVE 8835 && !pointInView(event.getX(), event.getY()))) { 8836 mSendingHoverAccessibilityEvents = false; 8837 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 8838 } 8839 } 8840 8841 if (isHoverable()) { 8842 switch (action) { 8843 case MotionEvent.ACTION_HOVER_ENTER: 8844 setHovered(true); 8845 break; 8846 case MotionEvent.ACTION_HOVER_EXIT: 8847 setHovered(false); 8848 break; 8849 } 8850 8851 // Dispatch the event to onGenericMotionEvent before returning true. 8852 // This is to provide compatibility with existing applications that 8853 // handled HOVER_MOVE events in onGenericMotionEvent and that would 8854 // break because of the new default handling for hoverable views 8855 // in onHoverEvent. 8856 // Note that onGenericMotionEvent will be called by default when 8857 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 8858 dispatchGenericMotionEventInternal(event); 8859 // The event was already handled by calling setHovered(), so always 8860 // return true. 8861 return true; 8862 } 8863 8864 return false; 8865 } 8866 8867 /** 8868 * Returns true if the view should handle {@link #onHoverEvent} 8869 * by calling {@link #setHovered} to change its hovered state. 8870 * 8871 * @return True if the view is hoverable. 8872 */ 8873 private boolean isHoverable() { 8874 final int viewFlags = mViewFlags; 8875 if ((viewFlags & ENABLED_MASK) == DISABLED) { 8876 return false; 8877 } 8878 8879 return (viewFlags & CLICKABLE) == CLICKABLE 8880 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 8881 } 8882 8883 /** 8884 * Returns true if the view is currently hovered. 8885 * 8886 * @return True if the view is currently hovered. 8887 * 8888 * @see #setHovered 8889 * @see #onHoverChanged 8890 */ 8891 @ViewDebug.ExportedProperty 8892 public boolean isHovered() { 8893 return (mPrivateFlags & PFLAG_HOVERED) != 0; 8894 } 8895 8896 /** 8897 * Sets whether the view is currently hovered. 8898 * <p> 8899 * Calling this method also changes the drawable state of the view. This 8900 * enables the view to react to hover by using different drawable resources 8901 * to change its appearance. 8902 * </p><p> 8903 * The {@link #onHoverChanged} method is called when the hovered state changes. 8904 * </p> 8905 * 8906 * @param hovered True if the view is hovered. 8907 * 8908 * @see #isHovered 8909 * @see #onHoverChanged 8910 */ 8911 public void setHovered(boolean hovered) { 8912 if (hovered) { 8913 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 8914 mPrivateFlags |= PFLAG_HOVERED; 8915 refreshDrawableState(); 8916 onHoverChanged(true); 8917 } 8918 } else { 8919 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 8920 mPrivateFlags &= ~PFLAG_HOVERED; 8921 refreshDrawableState(); 8922 onHoverChanged(false); 8923 } 8924 } 8925 } 8926 8927 /** 8928 * Implement this method to handle hover state changes. 8929 * <p> 8930 * This method is called whenever the hover state changes as a result of a 8931 * call to {@link #setHovered}. 8932 * </p> 8933 * 8934 * @param hovered The current hover state, as returned by {@link #isHovered}. 8935 * 8936 * @see #isHovered 8937 * @see #setHovered 8938 */ 8939 public void onHoverChanged(boolean hovered) { 8940 } 8941 8942 /** 8943 * Implement this method to handle touch screen motion events. 8944 * <p> 8945 * If this method is used to detect click actions, it is recommended that 8946 * the actions be performed by implementing and calling 8947 * {@link #performClick()}. This will ensure consistent system behavior, 8948 * including: 8949 * <ul> 8950 * <li>obeying click sound preferences 8951 * <li>dispatching OnClickListener calls 8952 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 8953 * accessibility features are enabled 8954 * </ul> 8955 * 8956 * @param event The motion event. 8957 * @return True if the event was handled, false otherwise. 8958 */ 8959 public boolean onTouchEvent(MotionEvent event) { 8960 final float x = event.getX(); 8961 final float y = event.getY(); 8962 final int viewFlags = mViewFlags; 8963 8964 if ((viewFlags & ENABLED_MASK) == DISABLED) { 8965 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 8966 clearHotspot(R.attr.state_pressed); 8967 setPressed(false); 8968 } 8969 // A disabled view that is clickable still consumes the touch 8970 // events, it just doesn't respond to them. 8971 return (((viewFlags & CLICKABLE) == CLICKABLE || 8972 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 8973 } 8974 8975 if (mTouchDelegate != null) { 8976 if (mTouchDelegate.onTouchEvent(event)) { 8977 return true; 8978 } 8979 } 8980 8981 if (((viewFlags & CLICKABLE) == CLICKABLE || 8982 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 8983 switch (event.getAction()) { 8984 case MotionEvent.ACTION_UP: 8985 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 8986 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 8987 // take focus if we don't have it already and we should in 8988 // touch mode. 8989 boolean focusTaken = false; 8990 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 8991 focusTaken = requestFocus(); 8992 } 8993 8994 if (prepressed) { 8995 // The button is being released before we actually 8996 // showed it as pressed. Make it show the pressed 8997 // state now (before scheduling the click) to ensure 8998 // the user sees it. 8999 setHotspot(R.attr.state_pressed, x, y); 9000 setPressed(true); 9001 } 9002 9003 if (!mHasPerformedLongPress) { 9004 // This is a tap, so remove the longpress check 9005 removeLongPressCallback(); 9006 9007 // Only perform take click actions if we were in the pressed state 9008 if (!focusTaken) { 9009 // Use a Runnable and post this rather than calling 9010 // performClick directly. This lets other visual state 9011 // of the view update before click actions start. 9012 if (mPerformClick == null) { 9013 mPerformClick = new PerformClick(); 9014 } 9015 if (!post(mPerformClick)) { 9016 performClick(); 9017 } 9018 } 9019 } 9020 9021 if (mUnsetPressedState == null) { 9022 mUnsetPressedState = new UnsetPressedState(); 9023 } 9024 9025 if (prepressed) { 9026 postDelayed(mUnsetPressedState, 9027 ViewConfiguration.getPressedStateDuration()); 9028 } else if (!post(mUnsetPressedState)) { 9029 // If the post failed, unpress right now 9030 mUnsetPressedState.run(); 9031 } 9032 9033 removeTapCallback(); 9034 } else { 9035 clearHotspot(R.attr.state_pressed); 9036 } 9037 break; 9038 9039 case MotionEvent.ACTION_DOWN: 9040 mHasPerformedLongPress = false; 9041 9042 if (performButtonActionOnTouchDown(event)) { 9043 break; 9044 } 9045 9046 // Walk up the hierarchy to determine if we're inside a scrolling container. 9047 boolean isInScrollingContainer = isInScrollingContainer(); 9048 9049 // For views inside a scrolling container, delay the pressed feedback for 9050 // a short period in case this is a scroll. 9051 if (isInScrollingContainer) { 9052 mPrivateFlags |= PFLAG_PREPRESSED; 9053 if (mPendingCheckForTap == null) { 9054 mPendingCheckForTap = new CheckForTap(); 9055 } 9056 mPendingCheckForTap.x = event.getX(); 9057 mPendingCheckForTap.y = event.getY(); 9058 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 9059 } else { 9060 // Not inside a scrolling container, so show the feedback right away 9061 setHotspot(R.attr.state_pressed, x, y); 9062 setPressed(true); 9063 checkForLongClick(0); 9064 } 9065 break; 9066 9067 case MotionEvent.ACTION_CANCEL: 9068 clearHotspot(R.attr.state_pressed); 9069 setPressed(false); 9070 removeTapCallback(); 9071 removeLongPressCallback(); 9072 break; 9073 9074 case MotionEvent.ACTION_MOVE: 9075 setHotspot(R.attr.state_pressed, x, y); 9076 9077 // Be lenient about moving outside of buttons 9078 if (!pointInView(x, y, mTouchSlop)) { 9079 // Outside button 9080 removeTapCallback(); 9081 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 9082 // Remove any future long press/tap checks 9083 removeLongPressCallback(); 9084 9085 setPressed(false); 9086 } 9087 } 9088 break; 9089 } 9090 9091 return true; 9092 } 9093 9094 return false; 9095 } 9096 9097 private void setHotspot(int id, float x, float y) { 9098 final Drawable bg = mBackground; 9099 if (bg != null && bg.supportsHotspots()) { 9100 bg.setHotspot(id, x, y); 9101 } 9102 } 9103 9104 private void clearHotspot(int id) { 9105 final Drawable bg = mBackground; 9106 if (bg != null && bg.supportsHotspots()) { 9107 bg.removeHotspot(id); 9108 } 9109 } 9110 9111 /** 9112 * @hide 9113 */ 9114 public boolean isInScrollingContainer() { 9115 ViewParent p = getParent(); 9116 while (p != null && p instanceof ViewGroup) { 9117 if (((ViewGroup) p).shouldDelayChildPressedState()) { 9118 return true; 9119 } 9120 p = p.getParent(); 9121 } 9122 return false; 9123 } 9124 9125 /** 9126 * Remove the longpress detection timer. 9127 */ 9128 private void removeLongPressCallback() { 9129 if (mPendingCheckForLongPress != null) { 9130 removeCallbacks(mPendingCheckForLongPress); 9131 } 9132 } 9133 9134 /** 9135 * Remove the pending click action 9136 */ 9137 private void removePerformClickCallback() { 9138 if (mPerformClick != null) { 9139 removeCallbacks(mPerformClick); 9140 } 9141 } 9142 9143 /** 9144 * Remove the prepress detection timer. 9145 */ 9146 private void removeUnsetPressCallback() { 9147 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 9148 clearHotspot(R.attr.state_pressed); 9149 setPressed(false); 9150 removeCallbacks(mUnsetPressedState); 9151 } 9152 } 9153 9154 /** 9155 * Remove the tap detection timer. 9156 */ 9157 private void removeTapCallback() { 9158 if (mPendingCheckForTap != null) { 9159 mPrivateFlags &= ~PFLAG_PREPRESSED; 9160 removeCallbacks(mPendingCheckForTap); 9161 } 9162 } 9163 9164 /** 9165 * Cancels a pending long press. Your subclass can use this if you 9166 * want the context menu to come up if the user presses and holds 9167 * at the same place, but you don't want it to come up if they press 9168 * and then move around enough to cause scrolling. 9169 */ 9170 public void cancelLongPress() { 9171 removeLongPressCallback(); 9172 9173 /* 9174 * The prepressed state handled by the tap callback is a display 9175 * construct, but the tap callback will post a long press callback 9176 * less its own timeout. Remove it here. 9177 */ 9178 removeTapCallback(); 9179 } 9180 9181 /** 9182 * Remove the pending callback for sending a 9183 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 9184 */ 9185 private void removeSendViewScrolledAccessibilityEventCallback() { 9186 if (mSendViewScrolledAccessibilityEvent != null) { 9187 removeCallbacks(mSendViewScrolledAccessibilityEvent); 9188 mSendViewScrolledAccessibilityEvent.mIsPending = false; 9189 } 9190 } 9191 9192 /** 9193 * Sets the TouchDelegate for this View. 9194 */ 9195 public void setTouchDelegate(TouchDelegate delegate) { 9196 mTouchDelegate = delegate; 9197 } 9198 9199 /** 9200 * Gets the TouchDelegate for this View. 9201 */ 9202 public TouchDelegate getTouchDelegate() { 9203 return mTouchDelegate; 9204 } 9205 9206 /** 9207 * Set flags controlling behavior of this view. 9208 * 9209 * @param flags Constant indicating the value which should be set 9210 * @param mask Constant indicating the bit range that should be changed 9211 */ 9212 void setFlags(int flags, int mask) { 9213 final boolean accessibilityEnabled = 9214 AccessibilityManager.getInstance(mContext).isEnabled(); 9215 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 9216 9217 int old = mViewFlags; 9218 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 9219 9220 int changed = mViewFlags ^ old; 9221 if (changed == 0) { 9222 return; 9223 } 9224 int privateFlags = mPrivateFlags; 9225 9226 /* Check if the FOCUSABLE bit has changed */ 9227 if (((changed & FOCUSABLE_MASK) != 0) && 9228 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { 9229 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 9230 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 9231 /* Give up focus if we are no longer focusable */ 9232 clearFocus(); 9233 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 9234 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 9235 /* 9236 * Tell the view system that we are now available to take focus 9237 * if no one else already has it. 9238 */ 9239 if (mParent != null) mParent.focusableViewAvailable(this); 9240 } 9241 } 9242 9243 final int newVisibility = flags & VISIBILITY_MASK; 9244 if (newVisibility == VISIBLE) { 9245 if ((changed & VISIBILITY_MASK) != 0) { 9246 /* 9247 * If this view is becoming visible, invalidate it in case it changed while 9248 * it was not visible. Marking it drawn ensures that the invalidation will 9249 * go through. 9250 */ 9251 mPrivateFlags |= PFLAG_DRAWN; 9252 invalidate(true); 9253 9254 needGlobalAttributesUpdate(true); 9255 9256 // a view becoming visible is worth notifying the parent 9257 // about in case nothing has focus. even if this specific view 9258 // isn't focusable, it may contain something that is, so let 9259 // the root view try to give this focus if nothing else does. 9260 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 9261 mParent.focusableViewAvailable(this); 9262 } 9263 } 9264 } 9265 9266 /* Check if the GONE bit has changed */ 9267 if ((changed & GONE) != 0) { 9268 needGlobalAttributesUpdate(false); 9269 requestLayout(); 9270 9271 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 9272 if (hasFocus()) clearFocus(); 9273 clearAccessibilityFocus(); 9274 destroyDrawingCache(); 9275 if (mParent instanceof View) { 9276 // GONE views noop invalidation, so invalidate the parent 9277 ((View) mParent).invalidate(true); 9278 } 9279 // Mark the view drawn to ensure that it gets invalidated properly the next 9280 // time it is visible and gets invalidated 9281 mPrivateFlags |= PFLAG_DRAWN; 9282 } 9283 if (mAttachInfo != null) { 9284 mAttachInfo.mViewVisibilityChanged = true; 9285 } 9286 } 9287 9288 /* Check if the VISIBLE bit has changed */ 9289 if ((changed & INVISIBLE) != 0) { 9290 needGlobalAttributesUpdate(false); 9291 /* 9292 * If this view is becoming invisible, set the DRAWN flag so that 9293 * the next invalidate() will not be skipped. 9294 */ 9295 mPrivateFlags |= PFLAG_DRAWN; 9296 9297 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 9298 // root view becoming invisible shouldn't clear focus and accessibility focus 9299 if (getRootView() != this) { 9300 if (hasFocus()) clearFocus(); 9301 clearAccessibilityFocus(); 9302 } 9303 } 9304 if (mAttachInfo != null) { 9305 mAttachInfo.mViewVisibilityChanged = true; 9306 } 9307 } 9308 9309 if ((changed & VISIBILITY_MASK) != 0) { 9310 // If the view is invisible, cleanup its display list to free up resources 9311 if (newVisibility != VISIBLE && mAttachInfo != null) { 9312 cleanupDraw(); 9313 } 9314 9315 if (mParent instanceof ViewGroup) { 9316 ((ViewGroup) mParent).onChildVisibilityChanged(this, 9317 (changed & VISIBILITY_MASK), newVisibility); 9318 ((View) mParent).invalidate(true); 9319 } else if (mParent != null) { 9320 mParent.invalidateChild(this, null); 9321 } 9322 dispatchVisibilityChanged(this, newVisibility); 9323 9324 notifySubtreeAccessibilityStateChangedIfNeeded(); 9325 } 9326 9327 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 9328 destroyDrawingCache(); 9329 } 9330 9331 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 9332 destroyDrawingCache(); 9333 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 9334 invalidateParentCaches(); 9335 } 9336 9337 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 9338 destroyDrawingCache(); 9339 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 9340 } 9341 9342 if ((changed & DRAW_MASK) != 0) { 9343 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 9344 if (mBackground != null) { 9345 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 9346 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; 9347 } else { 9348 mPrivateFlags |= PFLAG_SKIP_DRAW; 9349 } 9350 } else { 9351 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 9352 } 9353 requestLayout(); 9354 invalidate(true); 9355 } 9356 9357 if ((changed & KEEP_SCREEN_ON) != 0) { 9358 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 9359 mParent.recomputeViewAttributes(this); 9360 } 9361 } 9362 9363 if (accessibilityEnabled) { 9364 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0 9365 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) { 9366 if (oldIncludeForAccessibility != includeForAccessibility()) { 9367 notifySubtreeAccessibilityStateChangedIfNeeded(); 9368 } else { 9369 notifyViewAccessibilityStateChangedIfNeeded( 9370 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9371 } 9372 } else if ((changed & ENABLED_MASK) != 0) { 9373 notifyViewAccessibilityStateChangedIfNeeded( 9374 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9375 } 9376 } 9377 } 9378 9379 /** 9380 * Change the view's z order in the tree, so it's on top of other sibling 9381 * views. This ordering change may affect layout, if the parent container 9382 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 9383 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 9384 * method should be followed by calls to {@link #requestLayout()} and 9385 * {@link View#invalidate()} on the view's parent to force the parent to redraw 9386 * with the new child ordering. 9387 * 9388 * @see ViewGroup#bringChildToFront(View) 9389 */ 9390 public void bringToFront() { 9391 if (mParent != null) { 9392 mParent.bringChildToFront(this); 9393 } 9394 } 9395 9396 /** 9397 * This is called in response to an internal scroll in this view (i.e., the 9398 * view scrolled its own contents). This is typically as a result of 9399 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 9400 * called. 9401 * 9402 * @param l Current horizontal scroll origin. 9403 * @param t Current vertical scroll origin. 9404 * @param oldl Previous horizontal scroll origin. 9405 * @param oldt Previous vertical scroll origin. 9406 */ 9407 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 9408 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 9409 postSendViewScrolledAccessibilityEventCallback(); 9410 } 9411 9412 mBackgroundSizeChanged = true; 9413 9414 final AttachInfo ai = mAttachInfo; 9415 if (ai != null) { 9416 ai.mViewScrollChanged = true; 9417 } 9418 } 9419 9420 /** 9421 * Interface definition for a callback to be invoked when the layout bounds of a view 9422 * changes due to layout processing. 9423 */ 9424 public interface OnLayoutChangeListener { 9425 /** 9426 * Called when the layout bounds of a view changes due to layout processing. 9427 * 9428 * @param v The view whose bounds have changed. 9429 * @param left The new value of the view's left property. 9430 * @param top The new value of the view's top property. 9431 * @param right The new value of the view's right property. 9432 * @param bottom The new value of the view's bottom property. 9433 * @param oldLeft The previous value of the view's left property. 9434 * @param oldTop The previous value of the view's top property. 9435 * @param oldRight The previous value of the view's right property. 9436 * @param oldBottom The previous value of the view's bottom property. 9437 */ 9438 void onLayoutChange(View v, int left, int top, int right, int bottom, 9439 int oldLeft, int oldTop, int oldRight, int oldBottom); 9440 } 9441 9442 /** 9443 * This is called during layout when the size of this view has changed. If 9444 * you were just added to the view hierarchy, you're called with the old 9445 * values of 0. 9446 * 9447 * @param w Current width of this view. 9448 * @param h Current height of this view. 9449 * @param oldw Old width of this view. 9450 * @param oldh Old height of this view. 9451 */ 9452 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 9453 } 9454 9455 /** 9456 * Called by draw to draw the child views. This may be overridden 9457 * by derived classes to gain control just before its children are drawn 9458 * (but after its own view has been drawn). 9459 * @param canvas the canvas on which to draw the view 9460 */ 9461 protected void dispatchDraw(Canvas canvas) { 9462 9463 } 9464 9465 /** 9466 * Gets the parent of this view. Note that the parent is a 9467 * ViewParent and not necessarily a View. 9468 * 9469 * @return Parent of this view. 9470 */ 9471 public final ViewParent getParent() { 9472 return mParent; 9473 } 9474 9475 /** 9476 * Set the horizontal scrolled position of your view. This will cause a call to 9477 * {@link #onScrollChanged(int, int, int, int)} and the view will be 9478 * invalidated. 9479 * @param value the x position to scroll to 9480 */ 9481 public void setScrollX(int value) { 9482 scrollTo(value, mScrollY); 9483 } 9484 9485 /** 9486 * Set the vertical scrolled position of your view. This will cause a call to 9487 * {@link #onScrollChanged(int, int, int, int)} and the view will be 9488 * invalidated. 9489 * @param value the y position to scroll to 9490 */ 9491 public void setScrollY(int value) { 9492 scrollTo(mScrollX, value); 9493 } 9494 9495 /** 9496 * Return the scrolled left position of this view. This is the left edge of 9497 * the displayed part of your view. You do not need to draw any pixels 9498 * farther left, since those are outside of the frame of your view on 9499 * screen. 9500 * 9501 * @return The left edge of the displayed part of your view, in pixels. 9502 */ 9503 public final int getScrollX() { 9504 return mScrollX; 9505 } 9506 9507 /** 9508 * Return the scrolled top position of this view. This is the top edge of 9509 * the displayed part of your view. You do not need to draw any pixels above 9510 * it, since those are outside of the frame of your view on screen. 9511 * 9512 * @return The top edge of the displayed part of your view, in pixels. 9513 */ 9514 public final int getScrollY() { 9515 return mScrollY; 9516 } 9517 9518 /** 9519 * Return the width of the your view. 9520 * 9521 * @return The width of your view, in pixels. 9522 */ 9523 @ViewDebug.ExportedProperty(category = "layout") 9524 public final int getWidth() { 9525 return mRight - mLeft; 9526 } 9527 9528 /** 9529 * Return the height of your view. 9530 * 9531 * @return The height of your view, in pixels. 9532 */ 9533 @ViewDebug.ExportedProperty(category = "layout") 9534 public final int getHeight() { 9535 return mBottom - mTop; 9536 } 9537 9538 /** 9539 * Return the visible drawing bounds of your view. Fills in the output 9540 * rectangle with the values from getScrollX(), getScrollY(), 9541 * getWidth(), and getHeight(). These bounds do not account for any 9542 * transformation properties currently set on the view, such as 9543 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 9544 * 9545 * @param outRect The (scrolled) drawing bounds of the view. 9546 */ 9547 public void getDrawingRect(Rect outRect) { 9548 outRect.left = mScrollX; 9549 outRect.top = mScrollY; 9550 outRect.right = mScrollX + (mRight - mLeft); 9551 outRect.bottom = mScrollY + (mBottom - mTop); 9552 } 9553 9554 /** 9555 * Like {@link #getMeasuredWidthAndState()}, but only returns the 9556 * raw width component (that is the result is masked by 9557 * {@link #MEASURED_SIZE_MASK}). 9558 * 9559 * @return The raw measured width of this view. 9560 */ 9561 public final int getMeasuredWidth() { 9562 return mMeasuredWidth & MEASURED_SIZE_MASK; 9563 } 9564 9565 /** 9566 * Return the full width measurement information for this view as computed 9567 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 9568 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 9569 * This should be used during measurement and layout calculations only. Use 9570 * {@link #getWidth()} to see how wide a view is after layout. 9571 * 9572 * @return The measured width of this view as a bit mask. 9573 */ 9574 public final int getMeasuredWidthAndState() { 9575 return mMeasuredWidth; 9576 } 9577 9578 /** 9579 * Like {@link #getMeasuredHeightAndState()}, but only returns the 9580 * raw width component (that is the result is masked by 9581 * {@link #MEASURED_SIZE_MASK}). 9582 * 9583 * @return The raw measured height of this view. 9584 */ 9585 public final int getMeasuredHeight() { 9586 return mMeasuredHeight & MEASURED_SIZE_MASK; 9587 } 9588 9589 /** 9590 * Return the full height measurement information for this view as computed 9591 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 9592 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 9593 * This should be used during measurement and layout calculations only. Use 9594 * {@link #getHeight()} to see how wide a view is after layout. 9595 * 9596 * @return The measured width of this view as a bit mask. 9597 */ 9598 public final int getMeasuredHeightAndState() { 9599 return mMeasuredHeight; 9600 } 9601 9602 /** 9603 * Return only the state bits of {@link #getMeasuredWidthAndState()} 9604 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 9605 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 9606 * and the height component is at the shifted bits 9607 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 9608 */ 9609 public final int getMeasuredState() { 9610 return (mMeasuredWidth&MEASURED_STATE_MASK) 9611 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 9612 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 9613 } 9614 9615 /** 9616 * The transform matrix of this view, which is calculated based on the current 9617 * roation, scale, and pivot properties. 9618 * 9619 * @see #getRotation() 9620 * @see #getScaleX() 9621 * @see #getScaleY() 9622 * @see #getPivotX() 9623 * @see #getPivotY() 9624 * @return The current transform matrix for the view 9625 */ 9626 public Matrix getMatrix() { 9627 ensureTransformationInfo(); 9628 final Matrix matrix = mTransformationInfo.mMatrix; 9629 mRenderNode.getMatrix(matrix); 9630 return matrix; 9631 } 9632 9633 /** 9634 * Returns true if the transform matrix is the identity matrix. 9635 * Recomputes the matrix if necessary. 9636 * 9637 * @return True if the transform matrix is the identity matrix, false otherwise. 9638 */ 9639 final boolean hasIdentityMatrix() { 9640 return mRenderNode.hasIdentityMatrix(); 9641 } 9642 9643 void ensureTransformationInfo() { 9644 if (mTransformationInfo == null) { 9645 mTransformationInfo = new TransformationInfo(); 9646 } 9647 } 9648 9649 /** 9650 * Utility method to retrieve the inverse of the current mMatrix property. 9651 * We cache the matrix to avoid recalculating it when transform properties 9652 * have not changed. 9653 * 9654 * @return The inverse of the current matrix of this view. 9655 */ 9656 final Matrix getInverseMatrix() { 9657 ensureTransformationInfo(); 9658 if (mTransformationInfo.mInverseMatrix == null) { 9659 mTransformationInfo.mInverseMatrix = new Matrix(); 9660 } 9661 final Matrix matrix = mTransformationInfo.mInverseMatrix; 9662 mRenderNode.getInverseMatrix(matrix); 9663 return matrix; 9664 } 9665 9666 /** 9667 * Gets the distance along the Z axis from the camera to this view. 9668 * 9669 * @see #setCameraDistance(float) 9670 * 9671 * @return The distance along the Z axis. 9672 */ 9673 public float getCameraDistance() { 9674 final float dpi = mResources.getDisplayMetrics().densityDpi; 9675 return -(mRenderNode.getCameraDistance() * dpi); 9676 } 9677 9678 /** 9679 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 9680 * views are drawn) from the camera to this view. The camera's distance 9681 * affects 3D transformations, for instance rotations around the X and Y 9682 * axis. If the rotationX or rotationY properties are changed and this view is 9683 * large (more than half the size of the screen), it is recommended to always 9684 * use a camera distance that's greater than the height (X axis rotation) or 9685 * the width (Y axis rotation) of this view.</p> 9686 * 9687 * <p>The distance of the camera from the view plane can have an affect on the 9688 * perspective distortion of the view when it is rotated around the x or y axis. 9689 * For example, a large distance will result in a large viewing angle, and there 9690 * will not be much perspective distortion of the view as it rotates. A short 9691 * distance may cause much more perspective distortion upon rotation, and can 9692 * also result in some drawing artifacts if the rotated view ends up partially 9693 * behind the camera (which is why the recommendation is to use a distance at 9694 * least as far as the size of the view, if the view is to be rotated.)</p> 9695 * 9696 * <p>The distance is expressed in "depth pixels." The default distance depends 9697 * on the screen density. For instance, on a medium density display, the 9698 * default distance is 1280. On a high density display, the default distance 9699 * is 1920.</p> 9700 * 9701 * <p>If you want to specify a distance that leads to visually consistent 9702 * results across various densities, use the following formula:</p> 9703 * <pre> 9704 * float scale = context.getResources().getDisplayMetrics().density; 9705 * view.setCameraDistance(distance * scale); 9706 * </pre> 9707 * 9708 * <p>The density scale factor of a high density display is 1.5, 9709 * and 1920 = 1280 * 1.5.</p> 9710 * 9711 * @param distance The distance in "depth pixels", if negative the opposite 9712 * value is used 9713 * 9714 * @see #setRotationX(float) 9715 * @see #setRotationY(float) 9716 */ 9717 public void setCameraDistance(float distance) { 9718 final float dpi = mResources.getDisplayMetrics().densityDpi; 9719 9720 invalidateViewProperty(true, false); 9721 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); 9722 invalidateViewProperty(false, false); 9723 9724 invalidateParentIfNeededAndWasQuickRejected(); 9725 } 9726 9727 /** 9728 * The degrees that the view is rotated around the pivot point. 9729 * 9730 * @see #setRotation(float) 9731 * @see #getPivotX() 9732 * @see #getPivotY() 9733 * 9734 * @return The degrees of rotation. 9735 */ 9736 @ViewDebug.ExportedProperty(category = "drawing") 9737 public float getRotation() { 9738 return mRenderNode.getRotation(); 9739 } 9740 9741 /** 9742 * Sets the degrees that the view is rotated around the pivot point. Increasing values 9743 * result in clockwise rotation. 9744 * 9745 * @param rotation The degrees of rotation. 9746 * 9747 * @see #getRotation() 9748 * @see #getPivotX() 9749 * @see #getPivotY() 9750 * @see #setRotationX(float) 9751 * @see #setRotationY(float) 9752 * 9753 * @attr ref android.R.styleable#View_rotation 9754 */ 9755 public void setRotation(float rotation) { 9756 if (rotation != getRotation()) { 9757 // Double-invalidation is necessary to capture view's old and new areas 9758 invalidateViewProperty(true, false); 9759 mRenderNode.setRotation(rotation); 9760 invalidateViewProperty(false, true); 9761 9762 invalidateParentIfNeededAndWasQuickRejected(); 9763 } 9764 } 9765 9766 /** 9767 * The degrees that the view is rotated around the vertical axis through the pivot point. 9768 * 9769 * @see #getPivotX() 9770 * @see #getPivotY() 9771 * @see #setRotationY(float) 9772 * 9773 * @return The degrees of Y rotation. 9774 */ 9775 @ViewDebug.ExportedProperty(category = "drawing") 9776 public float getRotationY() { 9777 return mRenderNode.getRotationY(); 9778 } 9779 9780 /** 9781 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 9782 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 9783 * down the y axis. 9784 * 9785 * When rotating large views, it is recommended to adjust the camera distance 9786 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 9787 * 9788 * @param rotationY The degrees of Y rotation. 9789 * 9790 * @see #getRotationY() 9791 * @see #getPivotX() 9792 * @see #getPivotY() 9793 * @see #setRotation(float) 9794 * @see #setRotationX(float) 9795 * @see #setCameraDistance(float) 9796 * 9797 * @attr ref android.R.styleable#View_rotationY 9798 */ 9799 public void setRotationY(float rotationY) { 9800 if (rotationY != getRotationY()) { 9801 invalidateViewProperty(true, false); 9802 mRenderNode.setRotationY(rotationY); 9803 invalidateViewProperty(false, true); 9804 9805 invalidateParentIfNeededAndWasQuickRejected(); 9806 } 9807 } 9808 9809 /** 9810 * The degrees that the view is rotated around the horizontal axis through the pivot point. 9811 * 9812 * @see #getPivotX() 9813 * @see #getPivotY() 9814 * @see #setRotationX(float) 9815 * 9816 * @return The degrees of X rotation. 9817 */ 9818 @ViewDebug.ExportedProperty(category = "drawing") 9819 public float getRotationX() { 9820 return mRenderNode.getRotationX(); 9821 } 9822 9823 /** 9824 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 9825 * Increasing values result in clockwise rotation from the viewpoint of looking down the 9826 * x axis. 9827 * 9828 * When rotating large views, it is recommended to adjust the camera distance 9829 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 9830 * 9831 * @param rotationX The degrees of X rotation. 9832 * 9833 * @see #getRotationX() 9834 * @see #getPivotX() 9835 * @see #getPivotY() 9836 * @see #setRotation(float) 9837 * @see #setRotationY(float) 9838 * @see #setCameraDistance(float) 9839 * 9840 * @attr ref android.R.styleable#View_rotationX 9841 */ 9842 public void setRotationX(float rotationX) { 9843 if (rotationX != getRotationX()) { 9844 invalidateViewProperty(true, false); 9845 mRenderNode.setRotationX(rotationX); 9846 invalidateViewProperty(false, true); 9847 9848 invalidateParentIfNeededAndWasQuickRejected(); 9849 } 9850 } 9851 9852 /** 9853 * The amount that the view is scaled in x around the pivot point, as a proportion of 9854 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 9855 * 9856 * <p>By default, this is 1.0f. 9857 * 9858 * @see #getPivotX() 9859 * @see #getPivotY() 9860 * @return The scaling factor. 9861 */ 9862 @ViewDebug.ExportedProperty(category = "drawing") 9863 public float getScaleX() { 9864 return mRenderNode.getScaleX(); 9865 } 9866 9867 /** 9868 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 9869 * the view's unscaled width. A value of 1 means that no scaling is applied. 9870 * 9871 * @param scaleX The scaling factor. 9872 * @see #getPivotX() 9873 * @see #getPivotY() 9874 * 9875 * @attr ref android.R.styleable#View_scaleX 9876 */ 9877 public void setScaleX(float scaleX) { 9878 if (scaleX != getScaleX()) { 9879 invalidateViewProperty(true, false); 9880 mRenderNode.setScaleX(scaleX); 9881 invalidateViewProperty(false, true); 9882 9883 invalidateParentIfNeededAndWasQuickRejected(); 9884 } 9885 } 9886 9887 /** 9888 * The amount that the view is scaled in y around the pivot point, as a proportion of 9889 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 9890 * 9891 * <p>By default, this is 1.0f. 9892 * 9893 * @see #getPivotX() 9894 * @see #getPivotY() 9895 * @return The scaling factor. 9896 */ 9897 @ViewDebug.ExportedProperty(category = "drawing") 9898 public float getScaleY() { 9899 return mRenderNode.getScaleY(); 9900 } 9901 9902 /** 9903 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 9904 * the view's unscaled width. A value of 1 means that no scaling is applied. 9905 * 9906 * @param scaleY The scaling factor. 9907 * @see #getPivotX() 9908 * @see #getPivotY() 9909 * 9910 * @attr ref android.R.styleable#View_scaleY 9911 */ 9912 public void setScaleY(float scaleY) { 9913 if (scaleY != getScaleY()) { 9914 invalidateViewProperty(true, false); 9915 mRenderNode.setScaleY(scaleY); 9916 invalidateViewProperty(false, true); 9917 9918 invalidateParentIfNeededAndWasQuickRejected(); 9919 } 9920 } 9921 9922 /** 9923 * The x location of the point around which the view is {@link #setRotation(float) rotated} 9924 * and {@link #setScaleX(float) scaled}. 9925 * 9926 * @see #getRotation() 9927 * @see #getScaleX() 9928 * @see #getScaleY() 9929 * @see #getPivotY() 9930 * @return The x location of the pivot point. 9931 * 9932 * @attr ref android.R.styleable#View_transformPivotX 9933 */ 9934 @ViewDebug.ExportedProperty(category = "drawing") 9935 public float getPivotX() { 9936 return mRenderNode.getPivotX(); 9937 } 9938 9939 /** 9940 * Sets the x location of the point around which the view is 9941 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 9942 * By default, the pivot point is centered on the object. 9943 * Setting this property disables this behavior and causes the view to use only the 9944 * explicitly set pivotX and pivotY values. 9945 * 9946 * @param pivotX The x location of the pivot point. 9947 * @see #getRotation() 9948 * @see #getScaleX() 9949 * @see #getScaleY() 9950 * @see #getPivotY() 9951 * 9952 * @attr ref android.R.styleable#View_transformPivotX 9953 */ 9954 public void setPivotX(float pivotX) { 9955 if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { 9956 invalidateViewProperty(true, false); 9957 mRenderNode.setPivotX(pivotX); 9958 invalidateViewProperty(false, true); 9959 9960 invalidateParentIfNeededAndWasQuickRejected(); 9961 } 9962 } 9963 9964 /** 9965 * The y location of the point around which the view is {@link #setRotation(float) rotated} 9966 * and {@link #setScaleY(float) scaled}. 9967 * 9968 * @see #getRotation() 9969 * @see #getScaleX() 9970 * @see #getScaleY() 9971 * @see #getPivotY() 9972 * @return The y location of the pivot point. 9973 * 9974 * @attr ref android.R.styleable#View_transformPivotY 9975 */ 9976 @ViewDebug.ExportedProperty(category = "drawing") 9977 public float getPivotY() { 9978 return mRenderNode.getPivotY(); 9979 } 9980 9981 /** 9982 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 9983 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 9984 * Setting this property disables this behavior and causes the view to use only the 9985 * explicitly set pivotX and pivotY values. 9986 * 9987 * @param pivotY The y location of the pivot point. 9988 * @see #getRotation() 9989 * @see #getScaleX() 9990 * @see #getScaleY() 9991 * @see #getPivotY() 9992 * 9993 * @attr ref android.R.styleable#View_transformPivotY 9994 */ 9995 public void setPivotY(float pivotY) { 9996 if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { 9997 invalidateViewProperty(true, false); 9998 mRenderNode.setPivotY(pivotY); 9999 invalidateViewProperty(false, true); 10000 10001 invalidateParentIfNeededAndWasQuickRejected(); 10002 } 10003 } 10004 10005 /** 10006 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 10007 * completely transparent and 1 means the view is completely opaque. 10008 * 10009 * <p>By default this is 1.0f. 10010 * @return The opacity of the view. 10011 */ 10012 @ViewDebug.ExportedProperty(category = "drawing") 10013 public float getAlpha() { 10014 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 10015 } 10016 10017 /** 10018 * Returns whether this View has content which overlaps. 10019 * 10020 * <p>This function, intended to be overridden by specific View types, is an optimization when 10021 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 10022 * an offscreen buffer and then composited into place, which can be expensive. If the view has 10023 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 10024 * directly. An example of overlapping rendering is a TextView with a background image, such as 10025 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 10026 * ImageView with only the foreground image. The default implementation returns true; subclasses 10027 * should override if they have cases which can be optimized.</p> 10028 * 10029 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas} 10030 * necessitates that a View return true if it uses the methods internally without passing the 10031 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p> 10032 * 10033 * @return true if the content in this view might overlap, false otherwise. 10034 */ 10035 public boolean hasOverlappingRendering() { 10036 return true; 10037 } 10038 10039 /** 10040 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is 10041 * completely transparent and 1 means the view is completely opaque.</p> 10042 * 10043 * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant 10044 * performance implications, especially for large views. It is best to use the alpha property 10045 * sparingly and transiently, as in the case of fading animations.</p> 10046 * 10047 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 10048 * strongly recommended for performance reasons to either override 10049 * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a 10050 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p> 10051 * 10052 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 10053 * responsible for applying the opacity itself.</p> 10054 * 10055 * <p>Note that if the view is backed by a 10056 * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a 10057 * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than 10058 * 1.0 will supercede the alpha of the layer paint.</p> 10059 * 10060 * @param alpha The opacity of the view. 10061 * 10062 * @see #hasOverlappingRendering() 10063 * @see #setLayerType(int, android.graphics.Paint) 10064 * 10065 * @attr ref android.R.styleable#View_alpha 10066 */ 10067 public void setAlpha(float alpha) { 10068 ensureTransformationInfo(); 10069 if (mTransformationInfo.mAlpha != alpha) { 10070 mTransformationInfo.mAlpha = alpha; 10071 if (onSetAlpha((int) (alpha * 255))) { 10072 mPrivateFlags |= PFLAG_ALPHA_SET; 10073 // subclass is handling alpha - don't optimize rendering cache invalidation 10074 invalidateParentCaches(); 10075 invalidate(true); 10076 } else { 10077 mPrivateFlags &= ~PFLAG_ALPHA_SET; 10078 invalidateViewProperty(true, false); 10079 mRenderNode.setAlpha(getFinalAlpha()); 10080 } 10081 } 10082 } 10083 10084 /** 10085 * Faster version of setAlpha() which performs the same steps except there are 10086 * no calls to invalidate(). The caller of this function should perform proper invalidation 10087 * on the parent and this object. The return value indicates whether the subclass handles 10088 * alpha (the return value for onSetAlpha()). 10089 * 10090 * @param alpha The new value for the alpha property 10091 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 10092 * the new value for the alpha property is different from the old value 10093 */ 10094 boolean setAlphaNoInvalidation(float alpha) { 10095 ensureTransformationInfo(); 10096 if (mTransformationInfo.mAlpha != alpha) { 10097 mTransformationInfo.mAlpha = alpha; 10098 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 10099 if (subclassHandlesAlpha) { 10100 mPrivateFlags |= PFLAG_ALPHA_SET; 10101 return true; 10102 } else { 10103 mPrivateFlags &= ~PFLAG_ALPHA_SET; 10104 mRenderNode.setAlpha(getFinalAlpha()); 10105 } 10106 } 10107 return false; 10108 } 10109 10110 /** 10111 * This property is hidden and intended only for use by the Fade transition, which 10112 * animates it to produce a visual translucency that does not side-effect (or get 10113 * affected by) the real alpha property. This value is composited with the other 10114 * alpha value (and the AlphaAnimation value, when that is present) to produce 10115 * a final visual translucency result, which is what is passed into the DisplayList. 10116 * 10117 * @hide 10118 */ 10119 public void setTransitionAlpha(float alpha) { 10120 ensureTransformationInfo(); 10121 if (mTransformationInfo.mTransitionAlpha != alpha) { 10122 mTransformationInfo.mTransitionAlpha = alpha; 10123 mPrivateFlags &= ~PFLAG_ALPHA_SET; 10124 invalidateViewProperty(true, false); 10125 mRenderNode.setAlpha(getFinalAlpha()); 10126 } 10127 } 10128 10129 /** 10130 * Calculates the visual alpha of this view, which is a combination of the actual 10131 * alpha value and the transitionAlpha value (if set). 10132 */ 10133 private float getFinalAlpha() { 10134 if (mTransformationInfo != null) { 10135 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 10136 } 10137 return 1; 10138 } 10139 10140 /** 10141 * This property is hidden and intended only for use by the Fade transition, which 10142 * animates it to produce a visual translucency that does not side-effect (or get 10143 * affected by) the real alpha property. This value is composited with the other 10144 * alpha value (and the AlphaAnimation value, when that is present) to produce 10145 * a final visual translucency result, which is what is passed into the DisplayList. 10146 * 10147 * @hide 10148 */ 10149 public float getTransitionAlpha() { 10150 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 10151 } 10152 10153 /** 10154 * Top position of this view relative to its parent. 10155 * 10156 * @return The top of this view, in pixels. 10157 */ 10158 @ViewDebug.CapturedViewProperty 10159 public final int getTop() { 10160 return mTop; 10161 } 10162 10163 /** 10164 * Sets the top 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 top The top of this view, in pixels. 10169 */ 10170 public final void setTop(int top) { 10171 if (top != mTop) { 10172 final boolean matrixIsIdentity = hasIdentityMatrix(); 10173 if (matrixIsIdentity) { 10174 if (mAttachInfo != null) { 10175 int minTop; 10176 int yLoc; 10177 if (top < mTop) { 10178 minTop = top; 10179 yLoc = top - mTop; 10180 } else { 10181 minTop = mTop; 10182 yLoc = 0; 10183 } 10184 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 10185 } 10186 } else { 10187 // Double-invalidation is necessary to capture view's old and new areas 10188 invalidate(true); 10189 } 10190 10191 int width = mRight - mLeft; 10192 int oldHeight = mBottom - mTop; 10193 10194 mTop = top; 10195 mRenderNode.setTop(mTop); 10196 10197 sizeChange(width, mBottom - mTop, width, oldHeight); 10198 10199 if (!matrixIsIdentity) { 10200 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10201 invalidate(true); 10202 } 10203 mBackgroundSizeChanged = true; 10204 invalidateParentIfNeeded(); 10205 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10206 // View was rejected last time it was drawn by its parent; this may have changed 10207 invalidateParentIfNeeded(); 10208 } 10209 } 10210 } 10211 10212 /** 10213 * Bottom position of this view relative to its parent. 10214 * 10215 * @return The bottom of this view, in pixels. 10216 */ 10217 @ViewDebug.CapturedViewProperty 10218 public final int getBottom() { 10219 return mBottom; 10220 } 10221 10222 /** 10223 * True if this view has changed since the last time being drawn. 10224 * 10225 * @return The dirty state of this view. 10226 */ 10227 public boolean isDirty() { 10228 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 10229 } 10230 10231 /** 10232 * Sets the bottom position of this view relative to its parent. This method is meant to be 10233 * called by the layout system and should not generally be called otherwise, because the 10234 * property may be changed at any time by the layout. 10235 * 10236 * @param bottom The bottom of this view, in pixels. 10237 */ 10238 public final void setBottom(int bottom) { 10239 if (bottom != mBottom) { 10240 final boolean matrixIsIdentity = hasIdentityMatrix(); 10241 if (matrixIsIdentity) { 10242 if (mAttachInfo != null) { 10243 int maxBottom; 10244 if (bottom < mBottom) { 10245 maxBottom = mBottom; 10246 } else { 10247 maxBottom = bottom; 10248 } 10249 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 10250 } 10251 } else { 10252 // Double-invalidation is necessary to capture view's old and new areas 10253 invalidate(true); 10254 } 10255 10256 int width = mRight - mLeft; 10257 int oldHeight = mBottom - mTop; 10258 10259 mBottom = bottom; 10260 mRenderNode.setBottom(mBottom); 10261 10262 sizeChange(width, mBottom - mTop, width, oldHeight); 10263 10264 if (!matrixIsIdentity) { 10265 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10266 invalidate(true); 10267 } 10268 mBackgroundSizeChanged = true; 10269 invalidateParentIfNeeded(); 10270 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10271 // View was rejected last time it was drawn by its parent; this may have changed 10272 invalidateParentIfNeeded(); 10273 } 10274 } 10275 } 10276 10277 /** 10278 * Left position of this view relative to its parent. 10279 * 10280 * @return The left edge of this view, in pixels. 10281 */ 10282 @ViewDebug.CapturedViewProperty 10283 public final int getLeft() { 10284 return mLeft; 10285 } 10286 10287 /** 10288 * Sets the left position of this view relative to its parent. This method is meant to be called 10289 * by the layout system and should not generally be called otherwise, because the property 10290 * may be changed at any time by the layout. 10291 * 10292 * @param left The left of this view, in pixels. 10293 */ 10294 public final void setLeft(int left) { 10295 if (left != mLeft) { 10296 final boolean matrixIsIdentity = hasIdentityMatrix(); 10297 if (matrixIsIdentity) { 10298 if (mAttachInfo != null) { 10299 int minLeft; 10300 int xLoc; 10301 if (left < mLeft) { 10302 minLeft = left; 10303 xLoc = left - mLeft; 10304 } else { 10305 minLeft = mLeft; 10306 xLoc = 0; 10307 } 10308 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 10309 } 10310 } else { 10311 // Double-invalidation is necessary to capture view's old and new areas 10312 invalidate(true); 10313 } 10314 10315 int oldWidth = mRight - mLeft; 10316 int height = mBottom - mTop; 10317 10318 mLeft = left; 10319 mRenderNode.setLeft(left); 10320 10321 sizeChange(mRight - mLeft, height, oldWidth, height); 10322 10323 if (!matrixIsIdentity) { 10324 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10325 invalidate(true); 10326 } 10327 mBackgroundSizeChanged = true; 10328 invalidateParentIfNeeded(); 10329 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10330 // View was rejected last time it was drawn by its parent; this may have changed 10331 invalidateParentIfNeeded(); 10332 } 10333 } 10334 } 10335 10336 /** 10337 * Right position of this view relative to its parent. 10338 * 10339 * @return The right edge of this view, in pixels. 10340 */ 10341 @ViewDebug.CapturedViewProperty 10342 public final int getRight() { 10343 return mRight; 10344 } 10345 10346 /** 10347 * Sets the right position of this view relative to its parent. This method is meant to be called 10348 * by the layout system and should not generally be called otherwise, because the property 10349 * may be changed at any time by the layout. 10350 * 10351 * @param right The right of this view, in pixels. 10352 */ 10353 public final void setRight(int right) { 10354 if (right != mRight) { 10355 final boolean matrixIsIdentity = hasIdentityMatrix(); 10356 if (matrixIsIdentity) { 10357 if (mAttachInfo != null) { 10358 int maxRight; 10359 if (right < mRight) { 10360 maxRight = mRight; 10361 } else { 10362 maxRight = right; 10363 } 10364 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 10365 } 10366 } else { 10367 // Double-invalidation is necessary to capture view's old and new areas 10368 invalidate(true); 10369 } 10370 10371 int oldWidth = mRight - mLeft; 10372 int height = mBottom - mTop; 10373 10374 mRight = right; 10375 mRenderNode.setRight(mRight); 10376 10377 sizeChange(mRight - mLeft, height, oldWidth, height); 10378 10379 if (!matrixIsIdentity) { 10380 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 10381 invalidate(true); 10382 } 10383 mBackgroundSizeChanged = true; 10384 invalidateParentIfNeeded(); 10385 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 10386 // View was rejected last time it was drawn by its parent; this may have changed 10387 invalidateParentIfNeeded(); 10388 } 10389 } 10390 } 10391 10392 /** 10393 * The visual x position of this view, in pixels. This is equivalent to the 10394 * {@link #setTranslationX(float) translationX} property plus the current 10395 * {@link #getLeft() left} property. 10396 * 10397 * @return The visual x position of this view, in pixels. 10398 */ 10399 @ViewDebug.ExportedProperty(category = "drawing") 10400 public float getX() { 10401 return mLeft + getTranslationX(); 10402 } 10403 10404 /** 10405 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 10406 * {@link #setTranslationX(float) translationX} property to be the difference between 10407 * the x value passed in and the current {@link #getLeft() left} property. 10408 * 10409 * @param x The visual x position of this view, in pixels. 10410 */ 10411 public void setX(float x) { 10412 setTranslationX(x - mLeft); 10413 } 10414 10415 /** 10416 * The visual y position of this view, in pixels. This is equivalent to the 10417 * {@link #setTranslationY(float) translationY} property plus the current 10418 * {@link #getTop() top} property. 10419 * 10420 * @return The visual y position of this view, in pixels. 10421 */ 10422 @ViewDebug.ExportedProperty(category = "drawing") 10423 public float getY() { 10424 return mTop + getTranslationY(); 10425 } 10426 10427 /** 10428 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 10429 * {@link #setTranslationY(float) translationY} property to be the difference between 10430 * the y value passed in and the current {@link #getTop() top} property. 10431 * 10432 * @param y The visual y position of this view, in pixels. 10433 */ 10434 public void setY(float y) { 10435 setTranslationY(y - mTop); 10436 } 10437 10438 10439 /** 10440 * The horizontal location of this view relative to its {@link #getLeft() left} position. 10441 * This position is post-layout, in addition to wherever the object's 10442 * layout placed it. 10443 * 10444 * @return The horizontal position of this view relative to its left position, in pixels. 10445 */ 10446 @ViewDebug.ExportedProperty(category = "drawing") 10447 public float getTranslationX() { 10448 return mRenderNode.getTranslationX(); 10449 } 10450 10451 /** 10452 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 10453 * This effectively positions the object post-layout, in addition to wherever the object's 10454 * layout placed it. 10455 * 10456 * @param translationX The horizontal position of this view relative to its left position, 10457 * in pixels. 10458 * 10459 * @attr ref android.R.styleable#View_translationX 10460 */ 10461 public void setTranslationX(float translationX) { 10462 if (translationX != getTranslationX()) { 10463 invalidateViewProperty(true, false); 10464 mRenderNode.setTranslationX(translationX); 10465 invalidateViewProperty(false, true); 10466 10467 invalidateParentIfNeededAndWasQuickRejected(); 10468 } 10469 } 10470 10471 /** 10472 * The vertical location of this view relative to its {@link #getTop() top} position. 10473 * This position is post-layout, in addition to wherever the object's 10474 * layout placed it. 10475 * 10476 * @return The vertical position of this view relative to its top position, 10477 * in pixels. 10478 */ 10479 @ViewDebug.ExportedProperty(category = "drawing") 10480 public float getTranslationY() { 10481 return mRenderNode.getTranslationY(); 10482 } 10483 10484 /** 10485 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 10486 * This effectively positions the object post-layout, in addition to wherever the object's 10487 * layout placed it. 10488 * 10489 * @param translationY The vertical position of this view relative to its top position, 10490 * in pixels. 10491 * 10492 * @attr ref android.R.styleable#View_translationY 10493 */ 10494 public void setTranslationY(float translationY) { 10495 if (translationY != getTranslationY()) { 10496 invalidateViewProperty(true, false); 10497 mRenderNode.setTranslationY(translationY); 10498 invalidateViewProperty(false, true); 10499 10500 invalidateParentIfNeededAndWasQuickRejected(); 10501 } 10502 } 10503 10504 /** 10505 * The depth location of this view relative to its parent. 10506 * 10507 * @return The depth of this view relative to its parent. 10508 */ 10509 @ViewDebug.ExportedProperty(category = "drawing") 10510 public float getTranslationZ() { 10511 return mRenderNode.getTranslationZ(); 10512 } 10513 10514 /** 10515 * Sets the depth location of this view relative to its parent. 10516 * 10517 * @attr ref android.R.styleable#View_translationZ 10518 */ 10519 public void setTranslationZ(float translationZ) { 10520 if (translationZ != getTranslationZ()) { 10521 invalidateViewProperty(true, false); 10522 mRenderNode.setTranslationZ(translationZ); 10523 invalidateViewProperty(false, true); 10524 10525 invalidateParentIfNeededAndWasQuickRejected(); 10526 } 10527 } 10528 10529 /** 10530 * Returns a ValueAnimator which can animate a clipping circle. 10531 * <p> 10532 * The View will be clipped to the animating circle. 10533 * <p> 10534 * Any shadow cast by the View will respect the circular clip from this animator. 10535 * 10536 * @param centerX The x coordinate of the center of the animating circle. 10537 * @param centerY The y coordinate of the center of the animating circle. 10538 * @param startRadius The starting radius of the animating circle. 10539 * @param endRadius The ending radius of the animating circle. 10540 */ 10541 public final ValueAnimator createRevealAnimator(int centerX, int centerY, 10542 float startRadius, float endRadius) { 10543 return RevealAnimator.ofRevealCircle(this, centerX, centerY, 10544 startRadius, endRadius, false); 10545 } 10546 10547 /** 10548 * Returns a ValueAnimator which can animate a clearing circle. 10549 * <p> 10550 * The View is prevented from drawing within the circle, so the content 10551 * behind the View shows through. 10552 * 10553 * @param centerX The x coordinate of the center of the animating circle. 10554 * @param centerY The y coordinate of the center of the animating circle. 10555 * @param startRadius The starting radius of the animating circle. 10556 * @param endRadius The ending radius of the animating circle. 10557 * 10558 * @hide 10559 */ 10560 public final ValueAnimator createClearCircleAnimator(int centerX, int centerY, 10561 float startRadius, float endRadius) { 10562 return RevealAnimator.ofRevealCircle(this, centerX, centerY, 10563 startRadius, endRadius, true); 10564 } 10565 10566 /** 10567 * Sets the outline of the view, which defines the shape of the shadow it 10568 * casts. 10569 * <p> 10570 * If the outline is not set or is null, shadows will be cast from the 10571 * bounds of the View. 10572 * 10573 * @param outline The new outline of the view. 10574 * Must be {@link android.graphics.Outline#isValid() valid.} 10575 */ 10576 public void setOutline(@Nullable Outline outline) { 10577 if (outline != null && !outline.isValid()) { 10578 throw new IllegalArgumentException("Outline must not be invalid"); 10579 } 10580 10581 mPrivateFlags3 |= PFLAG3_OUTLINE_DEFINED; 10582 10583 if (outline == null) { 10584 mOutline = null; 10585 } else { 10586 // always copy the path since caller may reuse 10587 if (mOutline == null) { 10588 mOutline = new Outline(outline); 10589 } 10590 } 10591 mRenderNode.setOutline(mOutline); 10592 } 10593 10594 // TODO: remove 10595 public final boolean getClipToOutline() { return false; } 10596 public void setClipToOutline(boolean clipToOutline) {} 10597 10598 private void queryOutlineFromBackgroundIfUndefined() { 10599 if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) { 10600 // Outline not currently defined, query from background 10601 if (mOutline == null) { 10602 mOutline = new Outline(); 10603 } else { 10604 //invalidate outline, to ensure background calculates it 10605 mOutline.set(null); 10606 } 10607 if (mBackground.getOutline(mOutline)) { 10608 if (!mOutline.isValid()) { 10609 throw new IllegalStateException("Background drawable failed to build outline"); 10610 } 10611 mRenderNode.setOutline(mOutline); 10612 } else { 10613 mRenderNode.setOutline(null); 10614 } 10615 } 10616 } 10617 10618 /** 10619 * Private API to be used for reveal animation 10620 * 10621 * @hide 10622 */ 10623 public void setRevealClip(boolean shouldClip, boolean inverseClip, 10624 float x, float y, float radius) { 10625 mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius); 10626 // TODO: Handle this invalidate in a better way, or purely in native. 10627 invalidate(); 10628 } 10629 10630 /** 10631 * Hit rectangle in parent's coordinates 10632 * 10633 * @param outRect The hit rectangle of the view. 10634 */ 10635 public void getHitRect(Rect outRect) { 10636 if (hasIdentityMatrix() || mAttachInfo == null) { 10637 outRect.set(mLeft, mTop, mRight, mBottom); 10638 } else { 10639 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 10640 tmpRect.set(0, 0, getWidth(), getHeight()); 10641 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) 10642 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 10643 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 10644 } 10645 } 10646 10647 /** 10648 * Determines whether the given point, in local coordinates is inside the view. 10649 */ 10650 /*package*/ final boolean pointInView(float localX, float localY) { 10651 return localX >= 0 && localX < (mRight - mLeft) 10652 && localY >= 0 && localY < (mBottom - mTop); 10653 } 10654 10655 /** 10656 * Utility method to determine whether the given point, in local coordinates, 10657 * is inside the view, where the area of the view is expanded by the slop factor. 10658 * This method is called while processing touch-move events to determine if the event 10659 * is still within the view. 10660 * 10661 * @hide 10662 */ 10663 public boolean pointInView(float localX, float localY, float slop) { 10664 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 10665 localY < ((mBottom - mTop) + slop); 10666 } 10667 10668 /** 10669 * When a view has focus and the user navigates away from it, the next view is searched for 10670 * starting from the rectangle filled in by this method. 10671 * 10672 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 10673 * of the view. However, if your view maintains some idea of internal selection, 10674 * such as a cursor, or a selected row or column, you should override this method and 10675 * fill in a more specific rectangle. 10676 * 10677 * @param r The rectangle to fill in, in this view's coordinates. 10678 */ 10679 public void getFocusedRect(Rect r) { 10680 getDrawingRect(r); 10681 } 10682 10683 /** 10684 * If some part of this view is not clipped by any of its parents, then 10685 * return that area in r in global (root) coordinates. To convert r to local 10686 * coordinates (without taking possible View rotations into account), offset 10687 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 10688 * If the view is completely clipped or translated out, return false. 10689 * 10690 * @param r If true is returned, r holds the global coordinates of the 10691 * visible portion of this view. 10692 * @param globalOffset If true is returned, globalOffset holds the dx,dy 10693 * between this view and its root. globalOffet may be null. 10694 * @return true if r is non-empty (i.e. part of the view is visible at the 10695 * root level. 10696 */ 10697 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 10698 int width = mRight - mLeft; 10699 int height = mBottom - mTop; 10700 if (width > 0 && height > 0) { 10701 r.set(0, 0, width, height); 10702 if (globalOffset != null) { 10703 globalOffset.set(-mScrollX, -mScrollY); 10704 } 10705 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 10706 } 10707 return false; 10708 } 10709 10710 public final boolean getGlobalVisibleRect(Rect r) { 10711 return getGlobalVisibleRect(r, null); 10712 } 10713 10714 public final boolean getLocalVisibleRect(Rect r) { 10715 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 10716 if (getGlobalVisibleRect(r, offset)) { 10717 r.offset(-offset.x, -offset.y); // make r local 10718 return true; 10719 } 10720 return false; 10721 } 10722 10723 /** 10724 * Offset this view's vertical location by the specified number of pixels. 10725 * 10726 * @param offset the number of pixels to offset the view by 10727 */ 10728 public void offsetTopAndBottom(int offset) { 10729 if (offset != 0) { 10730 final boolean matrixIsIdentity = hasIdentityMatrix(); 10731 if (matrixIsIdentity) { 10732 if (isHardwareAccelerated()) { 10733 invalidateViewProperty(false, false); 10734 } else { 10735 final ViewParent p = mParent; 10736 if (p != null && mAttachInfo != null) { 10737 final Rect r = mAttachInfo.mTmpInvalRect; 10738 int minTop; 10739 int maxBottom; 10740 int yLoc; 10741 if (offset < 0) { 10742 minTop = mTop + offset; 10743 maxBottom = mBottom; 10744 yLoc = offset; 10745 } else { 10746 minTop = mTop; 10747 maxBottom = mBottom + offset; 10748 yLoc = 0; 10749 } 10750 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 10751 p.invalidateChild(this, r); 10752 } 10753 } 10754 } else { 10755 invalidateViewProperty(false, false); 10756 } 10757 10758 mTop += offset; 10759 mBottom += offset; 10760 mRenderNode.offsetTopAndBottom(offset); 10761 if (isHardwareAccelerated()) { 10762 invalidateViewProperty(false, false); 10763 } else { 10764 if (!matrixIsIdentity) { 10765 invalidateViewProperty(false, true); 10766 } 10767 invalidateParentIfNeeded(); 10768 } 10769 } 10770 } 10771 10772 /** 10773 * Offset this view's horizontal location by the specified amount of pixels. 10774 * 10775 * @param offset the number of pixels to offset the view by 10776 */ 10777 public void offsetLeftAndRight(int offset) { 10778 if (offset != 0) { 10779 final boolean matrixIsIdentity = hasIdentityMatrix(); 10780 if (matrixIsIdentity) { 10781 if (isHardwareAccelerated()) { 10782 invalidateViewProperty(false, false); 10783 } else { 10784 final ViewParent p = mParent; 10785 if (p != null && mAttachInfo != null) { 10786 final Rect r = mAttachInfo.mTmpInvalRect; 10787 int minLeft; 10788 int maxRight; 10789 if (offset < 0) { 10790 minLeft = mLeft + offset; 10791 maxRight = mRight; 10792 } else { 10793 minLeft = mLeft; 10794 maxRight = mRight + offset; 10795 } 10796 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 10797 p.invalidateChild(this, r); 10798 } 10799 } 10800 } else { 10801 invalidateViewProperty(false, false); 10802 } 10803 10804 mLeft += offset; 10805 mRight += offset; 10806 mRenderNode.offsetLeftAndRight(offset); 10807 if (isHardwareAccelerated()) { 10808 invalidateViewProperty(false, false); 10809 } else { 10810 if (!matrixIsIdentity) { 10811 invalidateViewProperty(false, true); 10812 } 10813 invalidateParentIfNeeded(); 10814 } 10815 } 10816 } 10817 10818 /** 10819 * Get the LayoutParams associated with this view. All views should have 10820 * layout parameters. These supply parameters to the <i>parent</i> of this 10821 * view specifying how it should be arranged. There are many subclasses of 10822 * ViewGroup.LayoutParams, and these correspond to the different subclasses 10823 * of ViewGroup that are responsible for arranging their children. 10824 * 10825 * This method may return null if this View is not attached to a parent 10826 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 10827 * was not invoked successfully. When a View is attached to a parent 10828 * ViewGroup, this method must not return null. 10829 * 10830 * @return The LayoutParams associated with this view, or null if no 10831 * parameters have been set yet 10832 */ 10833 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 10834 public ViewGroup.LayoutParams getLayoutParams() { 10835 return mLayoutParams; 10836 } 10837 10838 /** 10839 * Set the layout parameters associated with this view. These supply 10840 * parameters to the <i>parent</i> of this view specifying how it should be 10841 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 10842 * correspond to the different subclasses of ViewGroup that are responsible 10843 * for arranging their children. 10844 * 10845 * @param params The layout parameters for this view, cannot be null 10846 */ 10847 public void setLayoutParams(ViewGroup.LayoutParams params) { 10848 if (params == null) { 10849 throw new NullPointerException("Layout parameters cannot be null"); 10850 } 10851 mLayoutParams = params; 10852 resolveLayoutParams(); 10853 if (mParent instanceof ViewGroup) { 10854 ((ViewGroup) mParent).onSetLayoutParams(this, params); 10855 } 10856 requestLayout(); 10857 } 10858 10859 /** 10860 * Resolve the layout parameters depending on the resolved layout direction 10861 * 10862 * @hide 10863 */ 10864 public void resolveLayoutParams() { 10865 if (mLayoutParams != null) { 10866 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 10867 } 10868 } 10869 10870 /** 10871 * Set the scrolled position of your view. This will cause a call to 10872 * {@link #onScrollChanged(int, int, int, int)} and the view will be 10873 * invalidated. 10874 * @param x the x position to scroll to 10875 * @param y the y position to scroll to 10876 */ 10877 public void scrollTo(int x, int y) { 10878 if (mScrollX != x || mScrollY != y) { 10879 int oldX = mScrollX; 10880 int oldY = mScrollY; 10881 mScrollX = x; 10882 mScrollY = y; 10883 invalidateParentCaches(); 10884 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 10885 if (!awakenScrollBars()) { 10886 postInvalidateOnAnimation(); 10887 } 10888 } 10889 } 10890 10891 /** 10892 * Move the scrolled position of your view. This will cause a call to 10893 * {@link #onScrollChanged(int, int, int, int)} and the view will be 10894 * invalidated. 10895 * @param x the amount of pixels to scroll by horizontally 10896 * @param y the amount of pixels to scroll by vertically 10897 */ 10898 public void scrollBy(int x, int y) { 10899 scrollTo(mScrollX + x, mScrollY + y); 10900 } 10901 10902 /** 10903 * <p>Trigger the scrollbars to draw. When invoked this method starts an 10904 * animation to fade the scrollbars out after a default delay. If a subclass 10905 * provides animated scrolling, the start delay should equal the duration 10906 * of the scrolling animation.</p> 10907 * 10908 * <p>The animation starts only if at least one of the scrollbars is 10909 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 10910 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10911 * this method returns true, and false otherwise. If the animation is 10912 * started, this method calls {@link #invalidate()}; in that case the 10913 * caller should not call {@link #invalidate()}.</p> 10914 * 10915 * <p>This method should be invoked every time a subclass directly updates 10916 * the scroll parameters.</p> 10917 * 10918 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 10919 * and {@link #scrollTo(int, int)}.</p> 10920 * 10921 * @return true if the animation is played, false otherwise 10922 * 10923 * @see #awakenScrollBars(int) 10924 * @see #scrollBy(int, int) 10925 * @see #scrollTo(int, int) 10926 * @see #isHorizontalScrollBarEnabled() 10927 * @see #isVerticalScrollBarEnabled() 10928 * @see #setHorizontalScrollBarEnabled(boolean) 10929 * @see #setVerticalScrollBarEnabled(boolean) 10930 */ 10931 protected boolean awakenScrollBars() { 10932 return mScrollCache != null && 10933 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 10934 } 10935 10936 /** 10937 * Trigger the scrollbars to draw. 10938 * This method differs from awakenScrollBars() only in its default duration. 10939 * initialAwakenScrollBars() will show the scroll bars for longer than 10940 * usual to give the user more of a chance to notice them. 10941 * 10942 * @return true if the animation is played, false otherwise. 10943 */ 10944 private boolean initialAwakenScrollBars() { 10945 return mScrollCache != null && 10946 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 10947 } 10948 10949 /** 10950 * <p> 10951 * Trigger the scrollbars to draw. When invoked this method starts an 10952 * animation to fade the scrollbars out after a fixed delay. If a subclass 10953 * provides animated scrolling, the start delay should equal the duration of 10954 * the scrolling animation. 10955 * </p> 10956 * 10957 * <p> 10958 * The animation starts only if at least one of the scrollbars is enabled, 10959 * as specified by {@link #isHorizontalScrollBarEnabled()} and 10960 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10961 * this method returns true, and false otherwise. If the animation is 10962 * started, this method calls {@link #invalidate()}; in that case the caller 10963 * should not call {@link #invalidate()}. 10964 * </p> 10965 * 10966 * <p> 10967 * This method should be invoked everytime a subclass directly updates the 10968 * scroll parameters. 10969 * </p> 10970 * 10971 * @param startDelay the delay, in milliseconds, after which the animation 10972 * should start; when the delay is 0, the animation starts 10973 * immediately 10974 * @return true if the animation is played, false otherwise 10975 * 10976 * @see #scrollBy(int, int) 10977 * @see #scrollTo(int, int) 10978 * @see #isHorizontalScrollBarEnabled() 10979 * @see #isVerticalScrollBarEnabled() 10980 * @see #setHorizontalScrollBarEnabled(boolean) 10981 * @see #setVerticalScrollBarEnabled(boolean) 10982 */ 10983 protected boolean awakenScrollBars(int startDelay) { 10984 return awakenScrollBars(startDelay, true); 10985 } 10986 10987 /** 10988 * <p> 10989 * Trigger the scrollbars to draw. When invoked this method starts an 10990 * animation to fade the scrollbars out after a fixed delay. If a subclass 10991 * provides animated scrolling, the start delay should equal the duration of 10992 * the scrolling animation. 10993 * </p> 10994 * 10995 * <p> 10996 * The animation starts only if at least one of the scrollbars is enabled, 10997 * as specified by {@link #isHorizontalScrollBarEnabled()} and 10998 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 10999 * this method returns true, and false otherwise. If the animation is 11000 * started, this method calls {@link #invalidate()} if the invalidate parameter 11001 * is set to true; in that case the caller 11002 * should not call {@link #invalidate()}. 11003 * </p> 11004 * 11005 * <p> 11006 * This method should be invoked everytime a subclass directly updates the 11007 * scroll parameters. 11008 * </p> 11009 * 11010 * @param startDelay the delay, in milliseconds, after which the animation 11011 * should start; when the delay is 0, the animation starts 11012 * immediately 11013 * 11014 * @param invalidate Wheter this method should call invalidate 11015 * 11016 * @return true if the animation is played, false otherwise 11017 * 11018 * @see #scrollBy(int, int) 11019 * @see #scrollTo(int, int) 11020 * @see #isHorizontalScrollBarEnabled() 11021 * @see #isVerticalScrollBarEnabled() 11022 * @see #setHorizontalScrollBarEnabled(boolean) 11023 * @see #setVerticalScrollBarEnabled(boolean) 11024 */ 11025 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 11026 final ScrollabilityCache scrollCache = mScrollCache; 11027 11028 if (scrollCache == null || !scrollCache.fadeScrollBars) { 11029 return false; 11030 } 11031 11032 if (scrollCache.scrollBar == null) { 11033 scrollCache.scrollBar = new ScrollBarDrawable(); 11034 } 11035 11036 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 11037 11038 if (invalidate) { 11039 // Invalidate to show the scrollbars 11040 postInvalidateOnAnimation(); 11041 } 11042 11043 if (scrollCache.state == ScrollabilityCache.OFF) { 11044 // FIXME: this is copied from WindowManagerService. 11045 // We should get this value from the system when it 11046 // is possible to do so. 11047 final int KEY_REPEAT_FIRST_DELAY = 750; 11048 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 11049 } 11050 11051 // Tell mScrollCache when we should start fading. This may 11052 // extend the fade start time if one was already scheduled 11053 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 11054 scrollCache.fadeStartTime = fadeStartTime; 11055 scrollCache.state = ScrollabilityCache.ON; 11056 11057 // Schedule our fader to run, unscheduling any old ones first 11058 if (mAttachInfo != null) { 11059 mAttachInfo.mHandler.removeCallbacks(scrollCache); 11060 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 11061 } 11062 11063 return true; 11064 } 11065 11066 return false; 11067 } 11068 11069 /** 11070 * Do not invalidate views which are not visible and which are not running an animation. They 11071 * will not get drawn and they should not set dirty flags as if they will be drawn 11072 */ 11073 private boolean skipInvalidate() { 11074 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 11075 (!(mParent instanceof ViewGroup) || 11076 !((ViewGroup) mParent).isViewTransitioning(this)); 11077 } 11078 11079 /** 11080 * Mark the area defined by dirty as needing to be drawn. If the view is 11081 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 11082 * point in the future. 11083 * <p> 11084 * This must be called from a UI thread. To call from a non-UI thread, call 11085 * {@link #postInvalidate()}. 11086 * <p> 11087 * <b>WARNING:</b> In API 19 and below, this method may be destructive to 11088 * {@code dirty}. 11089 * 11090 * @param dirty the rectangle representing the bounds of the dirty region 11091 */ 11092 public void invalidate(Rect dirty) { 11093 final int scrollX = mScrollX; 11094 final int scrollY = mScrollY; 11095 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, 11096 dirty.right - scrollX, dirty.bottom - scrollY, true, false); 11097 } 11098 11099 /** 11100 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The 11101 * coordinates of the dirty rect are relative to the view. If the view is 11102 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 11103 * point in the future. 11104 * <p> 11105 * This must be called from a UI thread. To call from a non-UI thread, call 11106 * {@link #postInvalidate()}. 11107 * 11108 * @param l the left position of the dirty region 11109 * @param t the top position of the dirty region 11110 * @param r the right position of the dirty region 11111 * @param b the bottom position of the dirty region 11112 */ 11113 public void invalidate(int l, int t, int r, int b) { 11114 final int scrollX = mScrollX; 11115 final int scrollY = mScrollY; 11116 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false); 11117 } 11118 11119 /** 11120 * Invalidate the whole view. If the view is visible, 11121 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 11122 * the future. 11123 * <p> 11124 * This must be called from a UI thread. To call from a non-UI thread, call 11125 * {@link #postInvalidate()}. 11126 */ 11127 public void invalidate() { 11128 invalidate(true); 11129 } 11130 11131 /** 11132 * This is where the invalidate() work actually happens. A full invalidate() 11133 * causes the drawing cache to be invalidated, but this function can be 11134 * called with invalidateCache set to false to skip that invalidation step 11135 * for cases that do not need it (for example, a component that remains at 11136 * the same dimensions with the same content). 11137 * 11138 * @param invalidateCache Whether the drawing cache for this view should be 11139 * invalidated as well. This is usually true for a full 11140 * invalidate, but may be set to false if the View's contents or 11141 * dimensions have not changed. 11142 */ 11143 void invalidate(boolean invalidateCache) { 11144 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 11145 } 11146 11147 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, 11148 boolean fullInvalidate) { 11149 if (skipInvalidate()) { 11150 return; 11151 } 11152 11153 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) 11154 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) 11155 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED 11156 || (fullInvalidate && isOpaque() != mLastIsOpaque)) { 11157 if (fullInvalidate) { 11158 mLastIsOpaque = isOpaque(); 11159 mPrivateFlags &= ~PFLAG_DRAWN; 11160 } 11161 11162 mPrivateFlags |= PFLAG_DIRTY; 11163 11164 if (invalidateCache) { 11165 mPrivateFlags |= PFLAG_INVALIDATED; 11166 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 11167 } 11168 11169 // Propagate the damage rectangle to the parent view. 11170 final AttachInfo ai = mAttachInfo; 11171 final ViewParent p = mParent; 11172 if (p != null && ai != null && l < r && t < b) { 11173 final Rect damage = ai.mTmpInvalRect; 11174 damage.set(l, t, r, b); 11175 p.invalidateChild(this, damage); 11176 } 11177 11178 // Damage the entire projection receiver, if necessary. 11179 if (mBackground != null && mBackground.isProjected()) { 11180 final View receiver = getProjectionReceiver(); 11181 if (receiver != null) { 11182 receiver.damageInParent(); 11183 } 11184 } 11185 11186 // Damage the entire IsolatedZVolume recieving this view's shadow. 11187 if (isHardwareAccelerated() && getTranslationZ() != 0) { 11188 damageShadowReceiver(); 11189 } 11190 } 11191 } 11192 11193 /** 11194 * @return this view's projection receiver, or {@code null} if none exists 11195 */ 11196 private View getProjectionReceiver() { 11197 ViewParent p = getParent(); 11198 while (p != null && p instanceof View) { 11199 final View v = (View) p; 11200 if (v.isProjectionReceiver()) { 11201 return v; 11202 } 11203 p = p.getParent(); 11204 } 11205 11206 return null; 11207 } 11208 11209 /** 11210 * @return whether the view is a projection receiver 11211 */ 11212 private boolean isProjectionReceiver() { 11213 return mBackground != null; 11214 } 11215 11216 /** 11217 * Damage area of the screen that can be covered by this View's shadow. 11218 * 11219 * This method will guarantee that any changes to shadows cast by a View 11220 * are damaged on the screen for future redraw. 11221 */ 11222 private void damageShadowReceiver() { 11223 final AttachInfo ai = mAttachInfo; 11224 if (ai != null) { 11225 ViewParent p = getParent(); 11226 if (p != null && p instanceof ViewGroup) { 11227 final ViewGroup vg = (ViewGroup) p; 11228 vg.damageInParent(); 11229 } 11230 } 11231 } 11232 11233 /** 11234 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 11235 * set any flags or handle all of the cases handled by the default invalidation methods. 11236 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 11237 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 11238 * walk up the hierarchy, transforming the dirty rect as necessary. 11239 * 11240 * The method also handles normal invalidation logic if display list properties are not 11241 * being used in this view. The invalidateParent and forceRedraw flags are used by that 11242 * backup approach, to handle these cases used in the various property-setting methods. 11243 * 11244 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 11245 * are not being used in this view 11246 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 11247 * list properties are not being used in this view 11248 */ 11249 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 11250 if (!isHardwareAccelerated() 11251 || !mRenderNode.isValid() 11252 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { 11253 if (invalidateParent) { 11254 invalidateParentCaches(); 11255 } 11256 if (forceRedraw) { 11257 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 11258 } 11259 invalidate(false); 11260 } else { 11261 damageInParent(); 11262 } 11263 if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) { 11264 damageShadowReceiver(); 11265 } 11266 } 11267 11268 /** 11269 * Tells the parent view to damage this view's bounds. 11270 * 11271 * @hide 11272 */ 11273 protected void damageInParent() { 11274 final AttachInfo ai = mAttachInfo; 11275 final ViewParent p = mParent; 11276 if (p != null && ai != null) { 11277 final Rect r = ai.mTmpInvalRect; 11278 r.set(0, 0, mRight - mLeft, mBottom - mTop); 11279 if (mParent instanceof ViewGroup) { 11280 ((ViewGroup) mParent).damageChild(this, r); 11281 } else { 11282 mParent.invalidateChild(this, r); 11283 } 11284 } 11285 } 11286 11287 /** 11288 * Utility method to transform a given Rect by the current matrix of this view. 11289 */ 11290 void transformRect(final Rect rect) { 11291 if (!getMatrix().isIdentity()) { 11292 RectF boundingRect = mAttachInfo.mTmpTransformRect; 11293 boundingRect.set(rect); 11294 getMatrix().mapRect(boundingRect); 11295 rect.set((int) Math.floor(boundingRect.left), 11296 (int) Math.floor(boundingRect.top), 11297 (int) Math.ceil(boundingRect.right), 11298 (int) Math.ceil(boundingRect.bottom)); 11299 } 11300 } 11301 11302 /** 11303 * Used to indicate that the parent of this view should clear its caches. This functionality 11304 * is used to force the parent to rebuild its display list (when hardware-accelerated), 11305 * which is necessary when various parent-managed properties of the view change, such as 11306 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 11307 * clears the parent caches and does not causes an invalidate event. 11308 * 11309 * @hide 11310 */ 11311 protected void invalidateParentCaches() { 11312 if (mParent instanceof View) { 11313 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 11314 } 11315 } 11316 11317 /** 11318 * Used to indicate that the parent of this view should be invalidated. This functionality 11319 * is used to force the parent to rebuild its display list (when hardware-accelerated), 11320 * which is necessary when various parent-managed properties of the view change, such as 11321 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 11322 * an invalidation event to the parent. 11323 * 11324 * @hide 11325 */ 11326 protected void invalidateParentIfNeeded() { 11327 if (isHardwareAccelerated() && mParent instanceof View) { 11328 ((View) mParent).invalidate(true); 11329 } 11330 } 11331 11332 /** 11333 * @hide 11334 */ 11335 protected void invalidateParentIfNeededAndWasQuickRejected() { 11336 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { 11337 // View was rejected last time it was drawn by its parent; this may have changed 11338 invalidateParentIfNeeded(); 11339 } 11340 } 11341 11342 /** 11343 * Indicates whether this View is opaque. An opaque View guarantees that it will 11344 * draw all the pixels overlapping its bounds using a fully opaque color. 11345 * 11346 * Subclasses of View should override this method whenever possible to indicate 11347 * whether an instance is opaque. Opaque Views are treated in a special way by 11348 * the View hierarchy, possibly allowing it to perform optimizations during 11349 * invalidate/draw passes. 11350 * 11351 * @return True if this View is guaranteed to be fully opaque, false otherwise. 11352 */ 11353 @ViewDebug.ExportedProperty(category = "drawing") 11354 public boolean isOpaque() { 11355 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 11356 getFinalAlpha() >= 1.0f; 11357 } 11358 11359 /** 11360 * @hide 11361 */ 11362 protected void computeOpaqueFlags() { 11363 // Opaque if: 11364 // - Has a background 11365 // - Background is opaque 11366 // - Doesn't have scrollbars or scrollbars overlay 11367 11368 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 11369 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 11370 } else { 11371 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 11372 } 11373 11374 final int flags = mViewFlags; 11375 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 11376 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 11377 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 11378 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 11379 } else { 11380 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 11381 } 11382 } 11383 11384 /** 11385 * @hide 11386 */ 11387 protected boolean hasOpaqueScrollbars() { 11388 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 11389 } 11390 11391 /** 11392 * @return A handler associated with the thread running the View. This 11393 * handler can be used to pump events in the UI events queue. 11394 */ 11395 public Handler getHandler() { 11396 final AttachInfo attachInfo = mAttachInfo; 11397 if (attachInfo != null) { 11398 return attachInfo.mHandler; 11399 } 11400 return null; 11401 } 11402 11403 /** 11404 * Gets the view root associated with the View. 11405 * @return The view root, or null if none. 11406 * @hide 11407 */ 11408 public ViewRootImpl getViewRootImpl() { 11409 if (mAttachInfo != null) { 11410 return mAttachInfo.mViewRootImpl; 11411 } 11412 return null; 11413 } 11414 11415 /** 11416 * @hide 11417 */ 11418 public HardwareRenderer getHardwareRenderer() { 11419 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null; 11420 } 11421 11422 /** 11423 * <p>Causes the Runnable to be added to the message queue. 11424 * The runnable will be run on the user interface thread.</p> 11425 * 11426 * @param action The Runnable that will be executed. 11427 * 11428 * @return Returns true if the Runnable was successfully placed in to the 11429 * message queue. Returns false on failure, usually because the 11430 * looper processing the message queue is exiting. 11431 * 11432 * @see #postDelayed 11433 * @see #removeCallbacks 11434 */ 11435 public boolean post(Runnable action) { 11436 final AttachInfo attachInfo = mAttachInfo; 11437 if (attachInfo != null) { 11438 return attachInfo.mHandler.post(action); 11439 } 11440 // Assume that post will succeed later 11441 ViewRootImpl.getRunQueue().post(action); 11442 return true; 11443 } 11444 11445 /** 11446 * <p>Causes the Runnable to be added to the message queue, to be run 11447 * after the specified amount of time elapses. 11448 * The runnable will be run on the user interface thread.</p> 11449 * 11450 * @param action The Runnable that will be executed. 11451 * @param delayMillis The delay (in milliseconds) until the Runnable 11452 * will be executed. 11453 * 11454 * @return true if the Runnable was successfully placed in to the 11455 * message queue. Returns false on failure, usually because the 11456 * looper processing the message queue is exiting. Note that a 11457 * result of true does not mean the Runnable will be processed -- 11458 * if the looper is quit before the delivery time of the message 11459 * occurs then the message will be dropped. 11460 * 11461 * @see #post 11462 * @see #removeCallbacks 11463 */ 11464 public boolean postDelayed(Runnable action, long delayMillis) { 11465 final AttachInfo attachInfo = mAttachInfo; 11466 if (attachInfo != null) { 11467 return attachInfo.mHandler.postDelayed(action, delayMillis); 11468 } 11469 // Assume that post will succeed later 11470 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); 11471 return true; 11472 } 11473 11474 /** 11475 * <p>Causes the Runnable to execute on the next animation time step. 11476 * The runnable will be run on the user interface thread.</p> 11477 * 11478 * @param action The Runnable that will be executed. 11479 * 11480 * @see #postOnAnimationDelayed 11481 * @see #removeCallbacks 11482 */ 11483 public void postOnAnimation(Runnable action) { 11484 final AttachInfo attachInfo = mAttachInfo; 11485 if (attachInfo != null) { 11486 attachInfo.mViewRootImpl.mChoreographer.postCallback( 11487 Choreographer.CALLBACK_ANIMATION, action, null); 11488 } else { 11489 // Assume that post will succeed later 11490 ViewRootImpl.getRunQueue().post(action); 11491 } 11492 } 11493 11494 /** 11495 * <p>Causes the Runnable to execute on the next animation time step, 11496 * after the specified amount of time elapses. 11497 * The runnable will be run on the user interface thread.</p> 11498 * 11499 * @param action The Runnable that will be executed. 11500 * @param delayMillis The delay (in milliseconds) until the Runnable 11501 * will be executed. 11502 * 11503 * @see #postOnAnimation 11504 * @see #removeCallbacks 11505 */ 11506 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 11507 final AttachInfo attachInfo = mAttachInfo; 11508 if (attachInfo != null) { 11509 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 11510 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 11511 } else { 11512 // Assume that post will succeed later 11513 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); 11514 } 11515 } 11516 11517 /** 11518 * <p>Removes the specified Runnable from the message queue.</p> 11519 * 11520 * @param action The Runnable to remove from the message handling queue 11521 * 11522 * @return true if this view could ask the Handler to remove the Runnable, 11523 * false otherwise. When the returned value is true, the Runnable 11524 * may or may not have been actually removed from the message queue 11525 * (for instance, if the Runnable was not in the queue already.) 11526 * 11527 * @see #post 11528 * @see #postDelayed 11529 * @see #postOnAnimation 11530 * @see #postOnAnimationDelayed 11531 */ 11532 public boolean removeCallbacks(Runnable action) { 11533 if (action != null) { 11534 final AttachInfo attachInfo = mAttachInfo; 11535 if (attachInfo != null) { 11536 attachInfo.mHandler.removeCallbacks(action); 11537 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 11538 Choreographer.CALLBACK_ANIMATION, action, null); 11539 } 11540 // Assume that post will succeed later 11541 ViewRootImpl.getRunQueue().removeCallbacks(action); 11542 } 11543 return true; 11544 } 11545 11546 /** 11547 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 11548 * Use this to invalidate the View from a non-UI thread.</p> 11549 * 11550 * <p>This method can be invoked from outside of the UI thread 11551 * only when this View is attached to a window.</p> 11552 * 11553 * @see #invalidate() 11554 * @see #postInvalidateDelayed(long) 11555 */ 11556 public void postInvalidate() { 11557 postInvalidateDelayed(0); 11558 } 11559 11560 /** 11561 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 11562 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 11563 * 11564 * <p>This method can be invoked from outside of the UI thread 11565 * only when this View is attached to a window.</p> 11566 * 11567 * @param left The left coordinate of the rectangle to invalidate. 11568 * @param top The top coordinate of the rectangle to invalidate. 11569 * @param right The right coordinate of the rectangle to invalidate. 11570 * @param bottom The bottom coordinate of the rectangle to invalidate. 11571 * 11572 * @see #invalidate(int, int, int, int) 11573 * @see #invalidate(Rect) 11574 * @see #postInvalidateDelayed(long, int, int, int, int) 11575 */ 11576 public void postInvalidate(int left, int top, int right, int bottom) { 11577 postInvalidateDelayed(0, left, top, right, bottom); 11578 } 11579 11580 /** 11581 * <p>Cause an invalidate to happen on a subsequent cycle through the event 11582 * loop. Waits for the specified amount of time.</p> 11583 * 11584 * <p>This method can be invoked from outside of the UI thread 11585 * only when this View is attached to a window.</p> 11586 * 11587 * @param delayMilliseconds the duration in milliseconds to delay the 11588 * invalidation by 11589 * 11590 * @see #invalidate() 11591 * @see #postInvalidate() 11592 */ 11593 public void postInvalidateDelayed(long delayMilliseconds) { 11594 // We try only with the AttachInfo because there's no point in invalidating 11595 // if we are not attached to our window 11596 final AttachInfo attachInfo = mAttachInfo; 11597 if (attachInfo != null) { 11598 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 11599 } 11600 } 11601 11602 /** 11603 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 11604 * through the event loop. Waits for the specified amount of time.</p> 11605 * 11606 * <p>This method can be invoked from outside of the UI thread 11607 * only when this View is attached to a window.</p> 11608 * 11609 * @param delayMilliseconds the duration in milliseconds to delay the 11610 * invalidation by 11611 * @param left The left coordinate of the rectangle to invalidate. 11612 * @param top The top coordinate of the rectangle to invalidate. 11613 * @param right The right coordinate of the rectangle to invalidate. 11614 * @param bottom The bottom coordinate of the rectangle to invalidate. 11615 * 11616 * @see #invalidate(int, int, int, int) 11617 * @see #invalidate(Rect) 11618 * @see #postInvalidate(int, int, int, int) 11619 */ 11620 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 11621 int right, int bottom) { 11622 11623 // We try only with the AttachInfo because there's no point in invalidating 11624 // if we are not attached to our window 11625 final AttachInfo attachInfo = mAttachInfo; 11626 if (attachInfo != null) { 11627 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 11628 info.target = this; 11629 info.left = left; 11630 info.top = top; 11631 info.right = right; 11632 info.bottom = bottom; 11633 11634 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 11635 } 11636 } 11637 11638 /** 11639 * <p>Cause an invalidate to happen on the next animation time step, typically the 11640 * next display frame.</p> 11641 * 11642 * <p>This method can be invoked from outside of the UI thread 11643 * only when this View is attached to a window.</p> 11644 * 11645 * @see #invalidate() 11646 */ 11647 public void postInvalidateOnAnimation() { 11648 // We try only with the AttachInfo because there's no point in invalidating 11649 // if we are not attached to our window 11650 final AttachInfo attachInfo = mAttachInfo; 11651 if (attachInfo != null) { 11652 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 11653 } 11654 } 11655 11656 /** 11657 * <p>Cause an invalidate of the specified area to happen on the next animation 11658 * time step, typically the next display frame.</p> 11659 * 11660 * <p>This method can be invoked from outside of the UI thread 11661 * only when this View is attached to a window.</p> 11662 * 11663 * @param left The left coordinate of the rectangle to invalidate. 11664 * @param top The top coordinate of the rectangle to invalidate. 11665 * @param right The right coordinate of the rectangle to invalidate. 11666 * @param bottom The bottom coordinate of the rectangle to invalidate. 11667 * 11668 * @see #invalidate(int, int, int, int) 11669 * @see #invalidate(Rect) 11670 */ 11671 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 11672 // We try only with the AttachInfo because there's no point in invalidating 11673 // if we are not attached to our window 11674 final AttachInfo attachInfo = mAttachInfo; 11675 if (attachInfo != null) { 11676 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 11677 info.target = this; 11678 info.left = left; 11679 info.top = top; 11680 info.right = right; 11681 info.bottom = bottom; 11682 11683 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 11684 } 11685 } 11686 11687 /** 11688 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 11689 * This event is sent at most once every 11690 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 11691 */ 11692 private void postSendViewScrolledAccessibilityEventCallback() { 11693 if (mSendViewScrolledAccessibilityEvent == null) { 11694 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 11695 } 11696 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 11697 mSendViewScrolledAccessibilityEvent.mIsPending = true; 11698 postDelayed(mSendViewScrolledAccessibilityEvent, 11699 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 11700 } 11701 } 11702 11703 /** 11704 * Called by a parent to request that a child update its values for mScrollX 11705 * and mScrollY if necessary. This will typically be done if the child is 11706 * animating a scroll using a {@link android.widget.Scroller Scroller} 11707 * object. 11708 */ 11709 public void computeScroll() { 11710 } 11711 11712 /** 11713 * <p>Indicate whether the horizontal edges are faded when the view is 11714 * scrolled horizontally.</p> 11715 * 11716 * @return true if the horizontal edges should are faded on scroll, false 11717 * otherwise 11718 * 11719 * @see #setHorizontalFadingEdgeEnabled(boolean) 11720 * 11721 * @attr ref android.R.styleable#View_requiresFadingEdge 11722 */ 11723 public boolean isHorizontalFadingEdgeEnabled() { 11724 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 11725 } 11726 11727 /** 11728 * <p>Define whether the horizontal edges should be faded when this view 11729 * is scrolled horizontally.</p> 11730 * 11731 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 11732 * be faded when the view is scrolled 11733 * horizontally 11734 * 11735 * @see #isHorizontalFadingEdgeEnabled() 11736 * 11737 * @attr ref android.R.styleable#View_requiresFadingEdge 11738 */ 11739 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 11740 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 11741 if (horizontalFadingEdgeEnabled) { 11742 initScrollCache(); 11743 } 11744 11745 mViewFlags ^= FADING_EDGE_HORIZONTAL; 11746 } 11747 } 11748 11749 /** 11750 * <p>Indicate whether the vertical edges are faded when the view is 11751 * scrolled horizontally.</p> 11752 * 11753 * @return true if the vertical edges should are faded on scroll, false 11754 * otherwise 11755 * 11756 * @see #setVerticalFadingEdgeEnabled(boolean) 11757 * 11758 * @attr ref android.R.styleable#View_requiresFadingEdge 11759 */ 11760 public boolean isVerticalFadingEdgeEnabled() { 11761 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 11762 } 11763 11764 /** 11765 * <p>Define whether the vertical edges should be faded when this view 11766 * is scrolled vertically.</p> 11767 * 11768 * @param verticalFadingEdgeEnabled true if the vertical edges should 11769 * be faded when the view is scrolled 11770 * vertically 11771 * 11772 * @see #isVerticalFadingEdgeEnabled() 11773 * 11774 * @attr ref android.R.styleable#View_requiresFadingEdge 11775 */ 11776 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 11777 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 11778 if (verticalFadingEdgeEnabled) { 11779 initScrollCache(); 11780 } 11781 11782 mViewFlags ^= FADING_EDGE_VERTICAL; 11783 } 11784 } 11785 11786 /** 11787 * Returns the strength, or intensity, of the top faded edge. The strength is 11788 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11789 * returns 0.0 or 1.0 but no value in between. 11790 * 11791 * Subclasses should override this method to provide a smoother fade transition 11792 * when scrolling occurs. 11793 * 11794 * @return the intensity of the top fade as a float between 0.0f and 1.0f 11795 */ 11796 protected float getTopFadingEdgeStrength() { 11797 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 11798 } 11799 11800 /** 11801 * Returns the strength, or intensity, of the bottom faded edge. The strength is 11802 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11803 * returns 0.0 or 1.0 but no value in between. 11804 * 11805 * Subclasses should override this method to provide a smoother fade transition 11806 * when scrolling occurs. 11807 * 11808 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 11809 */ 11810 protected float getBottomFadingEdgeStrength() { 11811 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 11812 computeVerticalScrollRange() ? 1.0f : 0.0f; 11813 } 11814 11815 /** 11816 * Returns the strength, or intensity, of the left faded edge. The strength is 11817 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11818 * returns 0.0 or 1.0 but no value in between. 11819 * 11820 * Subclasses should override this method to provide a smoother fade transition 11821 * when scrolling occurs. 11822 * 11823 * @return the intensity of the left fade as a float between 0.0f and 1.0f 11824 */ 11825 protected float getLeftFadingEdgeStrength() { 11826 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 11827 } 11828 11829 /** 11830 * Returns the strength, or intensity, of the right faded edge. The strength is 11831 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 11832 * returns 0.0 or 1.0 but no value in between. 11833 * 11834 * Subclasses should override this method to provide a smoother fade transition 11835 * when scrolling occurs. 11836 * 11837 * @return the intensity of the right fade as a float between 0.0f and 1.0f 11838 */ 11839 protected float getRightFadingEdgeStrength() { 11840 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 11841 computeHorizontalScrollRange() ? 1.0f : 0.0f; 11842 } 11843 11844 /** 11845 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 11846 * scrollbar is not drawn by default.</p> 11847 * 11848 * @return true if the horizontal scrollbar should be painted, false 11849 * otherwise 11850 * 11851 * @see #setHorizontalScrollBarEnabled(boolean) 11852 */ 11853 public boolean isHorizontalScrollBarEnabled() { 11854 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 11855 } 11856 11857 /** 11858 * <p>Define whether the horizontal scrollbar should be drawn or not. The 11859 * scrollbar is not drawn by default.</p> 11860 * 11861 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 11862 * be painted 11863 * 11864 * @see #isHorizontalScrollBarEnabled() 11865 */ 11866 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 11867 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 11868 mViewFlags ^= SCROLLBARS_HORIZONTAL; 11869 computeOpaqueFlags(); 11870 resolvePadding(); 11871 } 11872 } 11873 11874 /** 11875 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 11876 * scrollbar is not drawn by default.</p> 11877 * 11878 * @return true if the vertical scrollbar should be painted, false 11879 * otherwise 11880 * 11881 * @see #setVerticalScrollBarEnabled(boolean) 11882 */ 11883 public boolean isVerticalScrollBarEnabled() { 11884 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 11885 } 11886 11887 /** 11888 * <p>Define whether the vertical scrollbar should be drawn or not. The 11889 * scrollbar is not drawn by default.</p> 11890 * 11891 * @param verticalScrollBarEnabled true if the vertical scrollbar should 11892 * be painted 11893 * 11894 * @see #isVerticalScrollBarEnabled() 11895 */ 11896 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 11897 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 11898 mViewFlags ^= SCROLLBARS_VERTICAL; 11899 computeOpaqueFlags(); 11900 resolvePadding(); 11901 } 11902 } 11903 11904 /** 11905 * @hide 11906 */ 11907 protected void recomputePadding() { 11908 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 11909 } 11910 11911 /** 11912 * Define whether scrollbars will fade when the view is not scrolling. 11913 * 11914 * @param fadeScrollbars wheter to enable fading 11915 * 11916 * @attr ref android.R.styleable#View_fadeScrollbars 11917 */ 11918 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 11919 initScrollCache(); 11920 final ScrollabilityCache scrollabilityCache = mScrollCache; 11921 scrollabilityCache.fadeScrollBars = fadeScrollbars; 11922 if (fadeScrollbars) { 11923 scrollabilityCache.state = ScrollabilityCache.OFF; 11924 } else { 11925 scrollabilityCache.state = ScrollabilityCache.ON; 11926 } 11927 } 11928 11929 /** 11930 * 11931 * Returns true if scrollbars will fade when this view is not scrolling 11932 * 11933 * @return true if scrollbar fading is enabled 11934 * 11935 * @attr ref android.R.styleable#View_fadeScrollbars 11936 */ 11937 public boolean isScrollbarFadingEnabled() { 11938 return mScrollCache != null && mScrollCache.fadeScrollBars; 11939 } 11940 11941 /** 11942 * 11943 * Returns the delay before scrollbars fade. 11944 * 11945 * @return the delay before scrollbars fade 11946 * 11947 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 11948 */ 11949 public int getScrollBarDefaultDelayBeforeFade() { 11950 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 11951 mScrollCache.scrollBarDefaultDelayBeforeFade; 11952 } 11953 11954 /** 11955 * Define the delay before scrollbars fade. 11956 * 11957 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 11958 * 11959 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 11960 */ 11961 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 11962 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 11963 } 11964 11965 /** 11966 * 11967 * Returns the scrollbar fade duration. 11968 * 11969 * @return the scrollbar fade duration 11970 * 11971 * @attr ref android.R.styleable#View_scrollbarFadeDuration 11972 */ 11973 public int getScrollBarFadeDuration() { 11974 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 11975 mScrollCache.scrollBarFadeDuration; 11976 } 11977 11978 /** 11979 * Define the scrollbar fade duration. 11980 * 11981 * @param scrollBarFadeDuration - the scrollbar fade duration 11982 * 11983 * @attr ref android.R.styleable#View_scrollbarFadeDuration 11984 */ 11985 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 11986 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 11987 } 11988 11989 /** 11990 * 11991 * Returns the scrollbar size. 11992 * 11993 * @return the scrollbar size 11994 * 11995 * @attr ref android.R.styleable#View_scrollbarSize 11996 */ 11997 public int getScrollBarSize() { 11998 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 11999 mScrollCache.scrollBarSize; 12000 } 12001 12002 /** 12003 * Define the scrollbar size. 12004 * 12005 * @param scrollBarSize - the scrollbar size 12006 * 12007 * @attr ref android.R.styleable#View_scrollbarSize 12008 */ 12009 public void setScrollBarSize(int scrollBarSize) { 12010 getScrollCache().scrollBarSize = scrollBarSize; 12011 } 12012 12013 /** 12014 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 12015 * inset. When inset, they add to the padding of the view. And the scrollbars 12016 * can be drawn inside the padding area or on the edge of the view. For example, 12017 * if a view has a background drawable and you want to draw the scrollbars 12018 * inside the padding specified by the drawable, you can use 12019 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 12020 * appear at the edge of the view, ignoring the padding, then you can use 12021 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 12022 * @param style the style of the scrollbars. Should be one of 12023 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 12024 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 12025 * @see #SCROLLBARS_INSIDE_OVERLAY 12026 * @see #SCROLLBARS_INSIDE_INSET 12027 * @see #SCROLLBARS_OUTSIDE_OVERLAY 12028 * @see #SCROLLBARS_OUTSIDE_INSET 12029 * 12030 * @attr ref android.R.styleable#View_scrollbarStyle 12031 */ 12032 public void setScrollBarStyle(@ScrollBarStyle int style) { 12033 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 12034 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 12035 computeOpaqueFlags(); 12036 resolvePadding(); 12037 } 12038 } 12039 12040 /** 12041 * <p>Returns the current scrollbar style.</p> 12042 * @return the current scrollbar style 12043 * @see #SCROLLBARS_INSIDE_OVERLAY 12044 * @see #SCROLLBARS_INSIDE_INSET 12045 * @see #SCROLLBARS_OUTSIDE_OVERLAY 12046 * @see #SCROLLBARS_OUTSIDE_INSET 12047 * 12048 * @attr ref android.R.styleable#View_scrollbarStyle 12049 */ 12050 @ViewDebug.ExportedProperty(mapping = { 12051 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 12052 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 12053 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 12054 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 12055 }) 12056 @ScrollBarStyle 12057 public int getScrollBarStyle() { 12058 return mViewFlags & SCROLLBARS_STYLE_MASK; 12059 } 12060 12061 /** 12062 * <p>Compute the horizontal range that the horizontal scrollbar 12063 * represents.</p> 12064 * 12065 * <p>The range is expressed in arbitrary units that must be the same as the 12066 * units used by {@link #computeHorizontalScrollExtent()} and 12067 * {@link #computeHorizontalScrollOffset()}.</p> 12068 * 12069 * <p>The default range is the drawing width of this view.</p> 12070 * 12071 * @return the total horizontal range represented by the horizontal 12072 * scrollbar 12073 * 12074 * @see #computeHorizontalScrollExtent() 12075 * @see #computeHorizontalScrollOffset() 12076 * @see android.widget.ScrollBarDrawable 12077 */ 12078 protected int computeHorizontalScrollRange() { 12079 return getWidth(); 12080 } 12081 12082 /** 12083 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 12084 * within the horizontal range. This value is used to compute the position 12085 * of the thumb within the scrollbar's track.</p> 12086 * 12087 * <p>The range is expressed in arbitrary units that must be the same as the 12088 * units used by {@link #computeHorizontalScrollRange()} and 12089 * {@link #computeHorizontalScrollExtent()}.</p> 12090 * 12091 * <p>The default offset is the scroll offset of this view.</p> 12092 * 12093 * @return the horizontal offset of the scrollbar's thumb 12094 * 12095 * @see #computeHorizontalScrollRange() 12096 * @see #computeHorizontalScrollExtent() 12097 * @see android.widget.ScrollBarDrawable 12098 */ 12099 protected int computeHorizontalScrollOffset() { 12100 return mScrollX; 12101 } 12102 12103 /** 12104 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 12105 * within the horizontal range. This value is used to compute the length 12106 * of the thumb within the scrollbar's track.</p> 12107 * 12108 * <p>The range is expressed in arbitrary units that must be the same as the 12109 * units used by {@link #computeHorizontalScrollRange()} and 12110 * {@link #computeHorizontalScrollOffset()}.</p> 12111 * 12112 * <p>The default extent is the drawing width of this view.</p> 12113 * 12114 * @return the horizontal extent of the scrollbar's thumb 12115 * 12116 * @see #computeHorizontalScrollRange() 12117 * @see #computeHorizontalScrollOffset() 12118 * @see android.widget.ScrollBarDrawable 12119 */ 12120 protected int computeHorizontalScrollExtent() { 12121 return getWidth(); 12122 } 12123 12124 /** 12125 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 12126 * 12127 * <p>The range is expressed in arbitrary units that must be the same as the 12128 * units used by {@link #computeVerticalScrollExtent()} and 12129 * {@link #computeVerticalScrollOffset()}.</p> 12130 * 12131 * @return the total vertical range represented by the vertical scrollbar 12132 * 12133 * <p>The default range is the drawing height of this view.</p> 12134 * 12135 * @see #computeVerticalScrollExtent() 12136 * @see #computeVerticalScrollOffset() 12137 * @see android.widget.ScrollBarDrawable 12138 */ 12139 protected int computeVerticalScrollRange() { 12140 return getHeight(); 12141 } 12142 12143 /** 12144 * <p>Compute the vertical offset of the vertical scrollbar's thumb 12145 * within the horizontal range. This value is used to compute the position 12146 * of the thumb within the scrollbar's track.</p> 12147 * 12148 * <p>The range is expressed in arbitrary units that must be the same as the 12149 * units used by {@link #computeVerticalScrollRange()} and 12150 * {@link #computeVerticalScrollExtent()}.</p> 12151 * 12152 * <p>The default offset is the scroll offset of this view.</p> 12153 * 12154 * @return the vertical offset of the scrollbar's thumb 12155 * 12156 * @see #computeVerticalScrollRange() 12157 * @see #computeVerticalScrollExtent() 12158 * @see android.widget.ScrollBarDrawable 12159 */ 12160 protected int computeVerticalScrollOffset() { 12161 return mScrollY; 12162 } 12163 12164 /** 12165 * <p>Compute the vertical extent of the vertical scrollbar's thumb 12166 * within the vertical range. This value is used to compute the length 12167 * of the thumb within the scrollbar's track.</p> 12168 * 12169 * <p>The range is expressed in arbitrary units that must be the same as the 12170 * units used by {@link #computeVerticalScrollRange()} and 12171 * {@link #computeVerticalScrollOffset()}.</p> 12172 * 12173 * <p>The default extent is the drawing height of this view.</p> 12174 * 12175 * @return the vertical extent of the scrollbar's thumb 12176 * 12177 * @see #computeVerticalScrollRange() 12178 * @see #computeVerticalScrollOffset() 12179 * @see android.widget.ScrollBarDrawable 12180 */ 12181 protected int computeVerticalScrollExtent() { 12182 return getHeight(); 12183 } 12184 12185 /** 12186 * Check if this view can be scrolled horizontally in a certain direction. 12187 * 12188 * @param direction Negative to check scrolling left, positive to check scrolling right. 12189 * @return true if this view can be scrolled in the specified direction, false otherwise. 12190 */ 12191 public boolean canScrollHorizontally(int direction) { 12192 final int offset = computeHorizontalScrollOffset(); 12193 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 12194 if (range == 0) return false; 12195 if (direction < 0) { 12196 return offset > 0; 12197 } else { 12198 return offset < range - 1; 12199 } 12200 } 12201 12202 /** 12203 * Check if this view can be scrolled vertically in a certain direction. 12204 * 12205 * @param direction Negative to check scrolling up, positive to check scrolling down. 12206 * @return true if this view can be scrolled in the specified direction, false otherwise. 12207 */ 12208 public boolean canScrollVertically(int direction) { 12209 final int offset = computeVerticalScrollOffset(); 12210 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 12211 if (range == 0) return false; 12212 if (direction < 0) { 12213 return offset > 0; 12214 } else { 12215 return offset < range - 1; 12216 } 12217 } 12218 12219 /** 12220 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 12221 * scrollbars are painted only if they have been awakened first.</p> 12222 * 12223 * @param canvas the canvas on which to draw the scrollbars 12224 * 12225 * @see #awakenScrollBars(int) 12226 */ 12227 protected final void onDrawScrollBars(Canvas canvas) { 12228 // scrollbars are drawn only when the animation is running 12229 final ScrollabilityCache cache = mScrollCache; 12230 if (cache != null) { 12231 12232 int state = cache.state; 12233 12234 if (state == ScrollabilityCache.OFF) { 12235 return; 12236 } 12237 12238 boolean invalidate = false; 12239 12240 if (state == ScrollabilityCache.FADING) { 12241 // We're fading -- get our fade interpolation 12242 if (cache.interpolatorValues == null) { 12243 cache.interpolatorValues = new float[1]; 12244 } 12245 12246 float[] values = cache.interpolatorValues; 12247 12248 // Stops the animation if we're done 12249 if (cache.scrollBarInterpolator.timeToValues(values) == 12250 Interpolator.Result.FREEZE_END) { 12251 cache.state = ScrollabilityCache.OFF; 12252 } else { 12253 cache.scrollBar.setAlpha(Math.round(values[0])); 12254 } 12255 12256 // This will make the scroll bars inval themselves after 12257 // drawing. We only want this when we're fading so that 12258 // we prevent excessive redraws 12259 invalidate = true; 12260 } else { 12261 // We're just on -- but we may have been fading before so 12262 // reset alpha 12263 cache.scrollBar.setAlpha(255); 12264 } 12265 12266 12267 final int viewFlags = mViewFlags; 12268 12269 final boolean drawHorizontalScrollBar = 12270 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 12271 final boolean drawVerticalScrollBar = 12272 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 12273 && !isVerticalScrollBarHidden(); 12274 12275 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 12276 final int width = mRight - mLeft; 12277 final int height = mBottom - mTop; 12278 12279 final ScrollBarDrawable scrollBar = cache.scrollBar; 12280 12281 final int scrollX = mScrollX; 12282 final int scrollY = mScrollY; 12283 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 12284 12285 int left; 12286 int top; 12287 int right; 12288 int bottom; 12289 12290 if (drawHorizontalScrollBar) { 12291 int size = scrollBar.getSize(false); 12292 if (size <= 0) { 12293 size = cache.scrollBarSize; 12294 } 12295 12296 scrollBar.setParameters(computeHorizontalScrollRange(), 12297 computeHorizontalScrollOffset(), 12298 computeHorizontalScrollExtent(), false); 12299 final int verticalScrollBarGap = drawVerticalScrollBar ? 12300 getVerticalScrollbarWidth() : 0; 12301 top = scrollY + height - size - (mUserPaddingBottom & inside); 12302 left = scrollX + (mPaddingLeft & inside); 12303 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 12304 bottom = top + size; 12305 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); 12306 if (invalidate) { 12307 invalidate(left, top, right, bottom); 12308 } 12309 } 12310 12311 if (drawVerticalScrollBar) { 12312 int size = scrollBar.getSize(true); 12313 if (size <= 0) { 12314 size = cache.scrollBarSize; 12315 } 12316 12317 scrollBar.setParameters(computeVerticalScrollRange(), 12318 computeVerticalScrollOffset(), 12319 computeVerticalScrollExtent(), true); 12320 int verticalScrollbarPosition = mVerticalScrollbarPosition; 12321 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 12322 verticalScrollbarPosition = isLayoutRtl() ? 12323 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 12324 } 12325 switch (verticalScrollbarPosition) { 12326 default: 12327 case SCROLLBAR_POSITION_RIGHT: 12328 left = scrollX + width - size - (mUserPaddingRight & inside); 12329 break; 12330 case SCROLLBAR_POSITION_LEFT: 12331 left = scrollX + (mUserPaddingLeft & inside); 12332 break; 12333 } 12334 top = scrollY + (mPaddingTop & inside); 12335 right = left + size; 12336 bottom = scrollY + height - (mUserPaddingBottom & inside); 12337 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); 12338 if (invalidate) { 12339 invalidate(left, top, right, bottom); 12340 } 12341 } 12342 } 12343 } 12344 } 12345 12346 /** 12347 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 12348 * FastScroller is visible. 12349 * @return whether to temporarily hide the vertical scrollbar 12350 * @hide 12351 */ 12352 protected boolean isVerticalScrollBarHidden() { 12353 return false; 12354 } 12355 12356 /** 12357 * <p>Draw the horizontal scrollbar if 12358 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 12359 * 12360 * @param canvas the canvas on which to draw the scrollbar 12361 * @param scrollBar the scrollbar's drawable 12362 * 12363 * @see #isHorizontalScrollBarEnabled() 12364 * @see #computeHorizontalScrollRange() 12365 * @see #computeHorizontalScrollExtent() 12366 * @see #computeHorizontalScrollOffset() 12367 * @see android.widget.ScrollBarDrawable 12368 * @hide 12369 */ 12370 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 12371 int l, int t, int r, int b) { 12372 scrollBar.setBounds(l, t, r, b); 12373 scrollBar.draw(canvas); 12374 } 12375 12376 /** 12377 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 12378 * returns true.</p> 12379 * 12380 * @param canvas the canvas on which to draw the scrollbar 12381 * @param scrollBar the scrollbar's drawable 12382 * 12383 * @see #isVerticalScrollBarEnabled() 12384 * @see #computeVerticalScrollRange() 12385 * @see #computeVerticalScrollExtent() 12386 * @see #computeVerticalScrollOffset() 12387 * @see android.widget.ScrollBarDrawable 12388 * @hide 12389 */ 12390 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 12391 int l, int t, int r, int b) { 12392 scrollBar.setBounds(l, t, r, b); 12393 scrollBar.draw(canvas); 12394 } 12395 12396 /** 12397 * Implement this to do your drawing. 12398 * 12399 * @param canvas the canvas on which the background will be drawn 12400 */ 12401 protected void onDraw(Canvas canvas) { 12402 } 12403 12404 /* 12405 * Caller is responsible for calling requestLayout if necessary. 12406 * (This allows addViewInLayout to not request a new layout.) 12407 */ 12408 void assignParent(ViewParent parent) { 12409 if (mParent == null) { 12410 mParent = parent; 12411 } else if (parent == null) { 12412 mParent = null; 12413 } else { 12414 throw new RuntimeException("view " + this + " being added, but" 12415 + " it already has a parent"); 12416 } 12417 } 12418 12419 /** 12420 * This is called when the view is attached to a window. At this point it 12421 * has a Surface and will start drawing. Note that this function is 12422 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 12423 * however it may be called any time before the first onDraw -- including 12424 * before or after {@link #onMeasure(int, int)}. 12425 * 12426 * @see #onDetachedFromWindow() 12427 */ 12428 protected void onAttachedToWindow() { 12429 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 12430 mParent.requestTransparentRegion(this); 12431 } 12432 12433 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) { 12434 initialAwakenScrollBars(); 12435 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH; 12436 } 12437 12438 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 12439 12440 jumpDrawablesToCurrentState(); 12441 12442 resetSubtreeAccessibilityStateChanged(); 12443 12444 if (isFocused()) { 12445 InputMethodManager imm = InputMethodManager.peekInstance(); 12446 imm.focusIn(this); 12447 } 12448 } 12449 12450 /** 12451 * Resolve all RTL related properties. 12452 * 12453 * @return true if resolution of RTL properties has been done 12454 * 12455 * @hide 12456 */ 12457 public boolean resolveRtlPropertiesIfNeeded() { 12458 if (!needRtlPropertiesResolution()) return false; 12459 12460 // Order is important here: LayoutDirection MUST be resolved first 12461 if (!isLayoutDirectionResolved()) { 12462 resolveLayoutDirection(); 12463 resolveLayoutParams(); 12464 } 12465 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 12466 if (!isTextDirectionResolved()) { 12467 resolveTextDirection(); 12468 } 12469 if (!isTextAlignmentResolved()) { 12470 resolveTextAlignment(); 12471 } 12472 // Should resolve Drawables before Padding because we need the layout direction of the 12473 // Drawable to correctly resolve Padding. 12474 if (!isDrawablesResolved()) { 12475 resolveDrawables(); 12476 } 12477 if (!isPaddingResolved()) { 12478 resolvePadding(); 12479 } 12480 onRtlPropertiesChanged(getLayoutDirection()); 12481 return true; 12482 } 12483 12484 /** 12485 * Reset resolution of all RTL related properties. 12486 * 12487 * @hide 12488 */ 12489 public void resetRtlProperties() { 12490 resetResolvedLayoutDirection(); 12491 resetResolvedTextDirection(); 12492 resetResolvedTextAlignment(); 12493 resetResolvedPadding(); 12494 resetResolvedDrawables(); 12495 } 12496 12497 /** 12498 * @see #onScreenStateChanged(int) 12499 */ 12500 void dispatchScreenStateChanged(int screenState) { 12501 onScreenStateChanged(screenState); 12502 } 12503 12504 /** 12505 * This method is called whenever the state of the screen this view is 12506 * attached to changes. A state change will usually occurs when the screen 12507 * turns on or off (whether it happens automatically or the user does it 12508 * manually.) 12509 * 12510 * @param screenState The new state of the screen. Can be either 12511 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 12512 */ 12513 public void onScreenStateChanged(int screenState) { 12514 } 12515 12516 /** 12517 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 12518 */ 12519 private boolean hasRtlSupport() { 12520 return mContext.getApplicationInfo().hasRtlSupport(); 12521 } 12522 12523 /** 12524 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 12525 * RTL not supported) 12526 */ 12527 private boolean isRtlCompatibilityMode() { 12528 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 12529 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 12530 } 12531 12532 /** 12533 * @return true if RTL properties need resolution. 12534 * 12535 */ 12536 private boolean needRtlPropertiesResolution() { 12537 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 12538 } 12539 12540 /** 12541 * Called when any RTL property (layout direction or text direction or text alignment) has 12542 * been changed. 12543 * 12544 * Subclasses need to override this method to take care of cached information that depends on the 12545 * resolved layout direction, or to inform child views that inherit their layout direction. 12546 * 12547 * The default implementation does nothing. 12548 * 12549 * @param layoutDirection the direction of the layout 12550 * 12551 * @see #LAYOUT_DIRECTION_LTR 12552 * @see #LAYOUT_DIRECTION_RTL 12553 */ 12554 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { 12555 } 12556 12557 /** 12558 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 12559 * that the parent directionality can and will be resolved before its children. 12560 * 12561 * @return true if resolution has been done, false otherwise. 12562 * 12563 * @hide 12564 */ 12565 public boolean resolveLayoutDirection() { 12566 // Clear any previous layout direction resolution 12567 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 12568 12569 if (hasRtlSupport()) { 12570 // Set resolved depending on layout direction 12571 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 12572 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 12573 case LAYOUT_DIRECTION_INHERIT: 12574 // We cannot resolve yet. LTR is by default and let the resolution happen again 12575 // later to get the correct resolved value 12576 if (!canResolveLayoutDirection()) return false; 12577 12578 // Parent has not yet resolved, LTR is still the default 12579 try { 12580 if (!mParent.isLayoutDirectionResolved()) return false; 12581 12582 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 12583 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12584 } 12585 } catch (AbstractMethodError e) { 12586 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 12587 " does not fully implement ViewParent", e); 12588 } 12589 break; 12590 case LAYOUT_DIRECTION_RTL: 12591 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12592 break; 12593 case LAYOUT_DIRECTION_LOCALE: 12594 if((LAYOUT_DIRECTION_RTL == 12595 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 12596 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 12597 } 12598 break; 12599 default: 12600 // Nothing to do, LTR by default 12601 } 12602 } 12603 12604 // Set to resolved 12605 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 12606 return true; 12607 } 12608 12609 /** 12610 * Check if layout direction resolution can be done. 12611 * 12612 * @return true if layout direction resolution can be done otherwise return false. 12613 */ 12614 public boolean canResolveLayoutDirection() { 12615 switch (getRawLayoutDirection()) { 12616 case LAYOUT_DIRECTION_INHERIT: 12617 if (mParent != null) { 12618 try { 12619 return mParent.canResolveLayoutDirection(); 12620 } catch (AbstractMethodError e) { 12621 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 12622 " does not fully implement ViewParent", e); 12623 } 12624 } 12625 return false; 12626 12627 default: 12628 return true; 12629 } 12630 } 12631 12632 /** 12633 * Reset the resolved layout direction. Layout direction will be resolved during a call to 12634 * {@link #onMeasure(int, int)}. 12635 * 12636 * @hide 12637 */ 12638 public void resetResolvedLayoutDirection() { 12639 // Reset the current resolved bits 12640 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 12641 } 12642 12643 /** 12644 * @return true if the layout direction is inherited. 12645 * 12646 * @hide 12647 */ 12648 public boolean isLayoutDirectionInherited() { 12649 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 12650 } 12651 12652 /** 12653 * @return true if layout direction has been resolved. 12654 */ 12655 public boolean isLayoutDirectionResolved() { 12656 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 12657 } 12658 12659 /** 12660 * Return if padding has been resolved 12661 * 12662 * @hide 12663 */ 12664 boolean isPaddingResolved() { 12665 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 12666 } 12667 12668 /** 12669 * Resolves padding depending on layout direction, if applicable, and 12670 * recomputes internal padding values to adjust for scroll bars. 12671 * 12672 * @hide 12673 */ 12674 public void resolvePadding() { 12675 final int resolvedLayoutDirection = getLayoutDirection(); 12676 12677 if (!isRtlCompatibilityMode()) { 12678 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 12679 // If start / end padding are defined, they will be resolved (hence overriding) to 12680 // left / right or right / left depending on the resolved layout direction. 12681 // If start / end padding are not defined, use the left / right ones. 12682 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 12683 Rect padding = sThreadLocal.get(); 12684 if (padding == null) { 12685 padding = new Rect(); 12686 sThreadLocal.set(padding); 12687 } 12688 mBackground.getPadding(padding); 12689 if (!mLeftPaddingDefined) { 12690 mUserPaddingLeftInitial = padding.left; 12691 } 12692 if (!mRightPaddingDefined) { 12693 mUserPaddingRightInitial = padding.right; 12694 } 12695 } 12696 switch (resolvedLayoutDirection) { 12697 case LAYOUT_DIRECTION_RTL: 12698 if (mUserPaddingStart != UNDEFINED_PADDING) { 12699 mUserPaddingRight = mUserPaddingStart; 12700 } else { 12701 mUserPaddingRight = mUserPaddingRightInitial; 12702 } 12703 if (mUserPaddingEnd != UNDEFINED_PADDING) { 12704 mUserPaddingLeft = mUserPaddingEnd; 12705 } else { 12706 mUserPaddingLeft = mUserPaddingLeftInitial; 12707 } 12708 break; 12709 case LAYOUT_DIRECTION_LTR: 12710 default: 12711 if (mUserPaddingStart != UNDEFINED_PADDING) { 12712 mUserPaddingLeft = mUserPaddingStart; 12713 } else { 12714 mUserPaddingLeft = mUserPaddingLeftInitial; 12715 } 12716 if (mUserPaddingEnd != UNDEFINED_PADDING) { 12717 mUserPaddingRight = mUserPaddingEnd; 12718 } else { 12719 mUserPaddingRight = mUserPaddingRightInitial; 12720 } 12721 } 12722 12723 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 12724 } 12725 12726 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 12727 onRtlPropertiesChanged(resolvedLayoutDirection); 12728 12729 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 12730 } 12731 12732 /** 12733 * Reset the resolved layout direction. 12734 * 12735 * @hide 12736 */ 12737 public void resetResolvedPadding() { 12738 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 12739 } 12740 12741 /** 12742 * This is called when the view is detached from a window. At this point it 12743 * no longer has a surface for drawing. 12744 * 12745 * @see #onAttachedToWindow() 12746 */ 12747 protected void onDetachedFromWindow() { 12748 } 12749 12750 /** 12751 * This is a framework-internal mirror of onDetachedFromWindow() that's called 12752 * after onDetachedFromWindow(). 12753 * 12754 * If you override this you *MUST* call super.onDetachedFromWindowInternal()! 12755 * The super method should be called at the end of the overriden method to ensure 12756 * subclasses are destroyed first 12757 * 12758 * @hide 12759 */ 12760 protected void onDetachedFromWindowInternal() { 12761 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 12762 mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; 12763 12764 if (mBackground != null) { 12765 mBackground.clearHotspots(); 12766 } 12767 12768 removeUnsetPressCallback(); 12769 removeLongPressCallback(); 12770 removePerformClickCallback(); 12771 removeSendViewScrolledAccessibilityEventCallback(); 12772 stopNestedScroll(); 12773 12774 destroyDrawingCache(); 12775 destroyLayer(false); 12776 12777 cleanupDraw(); 12778 12779 mCurrentAnimation = null; 12780 } 12781 12782 private void cleanupDraw() { 12783 resetDisplayList(); 12784 if (mAttachInfo != null) { 12785 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 12786 } 12787 } 12788 12789 /** 12790 * This method ensures the hardware renderer is in a valid state 12791 * before executing the specified action. 12792 * 12793 * This method will attempt to set a valid state even if the window 12794 * the renderer is attached to was destroyed. 12795 * 12796 * This method is not guaranteed to work. If the hardware renderer 12797 * does not exist or cannot be put in a valid state, this method 12798 * will not executed the specified action. 12799 * 12800 * The specified action is executed synchronously. 12801 * 12802 * @param action The action to execute after the renderer is in a valid state 12803 * 12804 * @return True if the specified Runnable was executed, false otherwise 12805 * 12806 * @hide 12807 */ 12808 public boolean executeHardwareAction(Runnable action) { 12809 //noinspection SimplifiableIfStatement 12810 if (mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { 12811 return mAttachInfo.mHardwareRenderer.safelyRun(action); 12812 } 12813 return false; 12814 } 12815 12816 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 12817 } 12818 12819 /** 12820 * @return The number of times this view has been attached to a window 12821 */ 12822 protected int getWindowAttachCount() { 12823 return mWindowAttachCount; 12824 } 12825 12826 /** 12827 * Retrieve a unique token identifying the window this view is attached to. 12828 * @return Return the window's token for use in 12829 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 12830 */ 12831 public IBinder getWindowToken() { 12832 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 12833 } 12834 12835 /** 12836 * Retrieve the {@link WindowId} for the window this view is 12837 * currently attached to. 12838 */ 12839 public WindowId getWindowId() { 12840 if (mAttachInfo == null) { 12841 return null; 12842 } 12843 if (mAttachInfo.mWindowId == null) { 12844 try { 12845 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId( 12846 mAttachInfo.mWindowToken); 12847 mAttachInfo.mWindowId = new WindowId( 12848 mAttachInfo.mIWindowId); 12849 } catch (RemoteException e) { 12850 } 12851 } 12852 return mAttachInfo.mWindowId; 12853 } 12854 12855 /** 12856 * Retrieve a unique token identifying the top-level "real" window of 12857 * the window that this view is attached to. That is, this is like 12858 * {@link #getWindowToken}, except if the window this view in is a panel 12859 * window (attached to another containing window), then the token of 12860 * the containing window is returned instead. 12861 * 12862 * @return Returns the associated window token, either 12863 * {@link #getWindowToken()} or the containing window's token. 12864 */ 12865 public IBinder getApplicationWindowToken() { 12866 AttachInfo ai = mAttachInfo; 12867 if (ai != null) { 12868 IBinder appWindowToken = ai.mPanelParentWindowToken; 12869 if (appWindowToken == null) { 12870 appWindowToken = ai.mWindowToken; 12871 } 12872 return appWindowToken; 12873 } 12874 return null; 12875 } 12876 12877 /** 12878 * Gets the logical display to which the view's window has been attached. 12879 * 12880 * @return The logical display, or null if the view is not currently attached to a window. 12881 */ 12882 public Display getDisplay() { 12883 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 12884 } 12885 12886 /** 12887 * Retrieve private session object this view hierarchy is using to 12888 * communicate with the window manager. 12889 * @return the session object to communicate with the window manager 12890 */ 12891 /*package*/ IWindowSession getWindowSession() { 12892 return mAttachInfo != null ? mAttachInfo.mSession : null; 12893 } 12894 12895 /** 12896 * @param info the {@link android.view.View.AttachInfo} to associated with 12897 * this view 12898 */ 12899 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 12900 //System.out.println("Attached! " + this); 12901 mAttachInfo = info; 12902 if (mOverlay != null) { 12903 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 12904 } 12905 mWindowAttachCount++; 12906 // We will need to evaluate the drawable state at least once. 12907 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 12908 if (mFloatingTreeObserver != null) { 12909 info.mTreeObserver.merge(mFloatingTreeObserver); 12910 mFloatingTreeObserver = null; 12911 } 12912 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 12913 mAttachInfo.mScrollContainers.add(this); 12914 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 12915 } 12916 performCollectViewAttributes(mAttachInfo, visibility); 12917 onAttachedToWindow(); 12918 12919 ListenerInfo li = mListenerInfo; 12920 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 12921 li != null ? li.mOnAttachStateChangeListeners : null; 12922 if (listeners != null && listeners.size() > 0) { 12923 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 12924 // perform the dispatching. The iterator is a safe guard against listeners that 12925 // could mutate the list by calling the various add/remove methods. This prevents 12926 // the array from being modified while we iterate it. 12927 for (OnAttachStateChangeListener listener : listeners) { 12928 listener.onViewAttachedToWindow(this); 12929 } 12930 } 12931 12932 int vis = info.mWindowVisibility; 12933 if (vis != GONE) { 12934 onWindowVisibilityChanged(vis); 12935 } 12936 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 12937 // If nobody has evaluated the drawable state yet, then do it now. 12938 refreshDrawableState(); 12939 } 12940 needGlobalAttributesUpdate(false); 12941 } 12942 12943 void dispatchDetachedFromWindow() { 12944 AttachInfo info = mAttachInfo; 12945 if (info != null) { 12946 int vis = info.mWindowVisibility; 12947 if (vis != GONE) { 12948 onWindowVisibilityChanged(GONE); 12949 } 12950 } 12951 12952 onDetachedFromWindow(); 12953 onDetachedFromWindowInternal(); 12954 12955 ListenerInfo li = mListenerInfo; 12956 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 12957 li != null ? li.mOnAttachStateChangeListeners : null; 12958 if (listeners != null && listeners.size() > 0) { 12959 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 12960 // perform the dispatching. The iterator is a safe guard against listeners that 12961 // could mutate the list by calling the various add/remove methods. This prevents 12962 // the array from being modified while we iterate it. 12963 for (OnAttachStateChangeListener listener : listeners) { 12964 listener.onViewDetachedFromWindow(this); 12965 } 12966 } 12967 12968 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 12969 mAttachInfo.mScrollContainers.remove(this); 12970 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 12971 } 12972 12973 mAttachInfo = null; 12974 if (mOverlay != null) { 12975 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 12976 } 12977 } 12978 12979 /** 12980 * Cancel any deferred high-level input events that were previously posted to the event queue. 12981 * 12982 * <p>Many views post high-level events such as click handlers to the event queue 12983 * to run deferred in order to preserve a desired user experience - clearing visible 12984 * pressed states before executing, etc. This method will abort any events of this nature 12985 * that are currently in flight.</p> 12986 * 12987 * <p>Custom views that generate their own high-level deferred input events should override 12988 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 12989 * 12990 * <p>This will also cancel pending input events for any child views.</p> 12991 * 12992 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 12993 * This will not impact newer events posted after this call that may occur as a result of 12994 * lower-level input events still waiting in the queue. If you are trying to prevent 12995 * double-submitted events for the duration of some sort of asynchronous transaction 12996 * you should also take other steps to protect against unexpected double inputs e.g. calling 12997 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 12998 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 12999 */ 13000 public final void cancelPendingInputEvents() { 13001 dispatchCancelPendingInputEvents(); 13002 } 13003 13004 /** 13005 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 13006 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 13007 */ 13008 void dispatchCancelPendingInputEvents() { 13009 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 13010 onCancelPendingInputEvents(); 13011 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 13012 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 13013 " did not call through to super.onCancelPendingInputEvents()"); 13014 } 13015 } 13016 13017 /** 13018 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 13019 * a parent view. 13020 * 13021 * <p>This method is responsible for removing any pending high-level input events that were 13022 * posted to the event queue to run later. Custom view classes that post their own deferred 13023 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 13024 * {@link android.os.Handler} should override this method, call 13025 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 13026 * </p> 13027 */ 13028 public void onCancelPendingInputEvents() { 13029 removePerformClickCallback(); 13030 cancelLongPress(); 13031 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 13032 } 13033 13034 /** 13035 * Store this view hierarchy's frozen state into the given container. 13036 * 13037 * @param container The SparseArray in which to save the view's state. 13038 * 13039 * @see #restoreHierarchyState(android.util.SparseArray) 13040 * @see #dispatchSaveInstanceState(android.util.SparseArray) 13041 * @see #onSaveInstanceState() 13042 */ 13043 public void saveHierarchyState(SparseArray<Parcelable> container) { 13044 dispatchSaveInstanceState(container); 13045 } 13046 13047 /** 13048 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 13049 * this view and its children. May be overridden to modify how freezing happens to a 13050 * view's children; for example, some views may want to not store state for their children. 13051 * 13052 * @param container The SparseArray in which to save the view's state. 13053 * 13054 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 13055 * @see #saveHierarchyState(android.util.SparseArray) 13056 * @see #onSaveInstanceState() 13057 */ 13058 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 13059 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 13060 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 13061 Parcelable state = onSaveInstanceState(); 13062 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 13063 throw new IllegalStateException( 13064 "Derived class did not call super.onSaveInstanceState()"); 13065 } 13066 if (state != null) { 13067 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 13068 // + ": " + state); 13069 container.put(mID, state); 13070 } 13071 } 13072 } 13073 13074 /** 13075 * Hook allowing a view to generate a representation of its internal state 13076 * that can later be used to create a new instance with that same state. 13077 * This state should only contain information that is not persistent or can 13078 * not be reconstructed later. For example, you will never store your 13079 * current position on screen because that will be computed again when a 13080 * new instance of the view is placed in its view hierarchy. 13081 * <p> 13082 * Some examples of things you may store here: the current cursor position 13083 * in a text view (but usually not the text itself since that is stored in a 13084 * content provider or other persistent storage), the currently selected 13085 * item in a list view. 13086 * 13087 * @return Returns a Parcelable object containing the view's current dynamic 13088 * state, or null if there is nothing interesting to save. The 13089 * default implementation returns null. 13090 * @see #onRestoreInstanceState(android.os.Parcelable) 13091 * @see #saveHierarchyState(android.util.SparseArray) 13092 * @see #dispatchSaveInstanceState(android.util.SparseArray) 13093 * @see #setSaveEnabled(boolean) 13094 */ 13095 protected Parcelable onSaveInstanceState() { 13096 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 13097 return BaseSavedState.EMPTY_STATE; 13098 } 13099 13100 /** 13101 * Restore this view hierarchy's frozen state from the given container. 13102 * 13103 * @param container The SparseArray which holds previously frozen states. 13104 * 13105 * @see #saveHierarchyState(android.util.SparseArray) 13106 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 13107 * @see #onRestoreInstanceState(android.os.Parcelable) 13108 */ 13109 public void restoreHierarchyState(SparseArray<Parcelable> container) { 13110 dispatchRestoreInstanceState(container); 13111 } 13112 13113 /** 13114 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 13115 * state for this view and its children. May be overridden to modify how restoring 13116 * happens to a view's children; for example, some views may want to not store state 13117 * for their children. 13118 * 13119 * @param container The SparseArray which holds previously saved state. 13120 * 13121 * @see #dispatchSaveInstanceState(android.util.SparseArray) 13122 * @see #restoreHierarchyState(android.util.SparseArray) 13123 * @see #onRestoreInstanceState(android.os.Parcelable) 13124 */ 13125 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 13126 if (mID != NO_ID) { 13127 Parcelable state = container.get(mID); 13128 if (state != null) { 13129 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 13130 // + ": " + state); 13131 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 13132 onRestoreInstanceState(state); 13133 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 13134 throw new IllegalStateException( 13135 "Derived class did not call super.onRestoreInstanceState()"); 13136 } 13137 } 13138 } 13139 } 13140 13141 /** 13142 * Hook allowing a view to re-apply a representation of its internal state that had previously 13143 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 13144 * null state. 13145 * 13146 * @param state The frozen state that had previously been returned by 13147 * {@link #onSaveInstanceState}. 13148 * 13149 * @see #onSaveInstanceState() 13150 * @see #restoreHierarchyState(android.util.SparseArray) 13151 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 13152 */ 13153 protected void onRestoreInstanceState(Parcelable state) { 13154 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 13155 if (state != BaseSavedState.EMPTY_STATE && state != null) { 13156 throw new IllegalArgumentException("Wrong state class, expecting View State but " 13157 + "received " + state.getClass().toString() + " instead. This usually happens " 13158 + "when two views of different type have the same id in the same hierarchy. " 13159 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 13160 + "other views do not use the same id."); 13161 } 13162 } 13163 13164 /** 13165 * <p>Return the time at which the drawing of the view hierarchy started.</p> 13166 * 13167 * @return the drawing start time in milliseconds 13168 */ 13169 public long getDrawingTime() { 13170 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 13171 } 13172 13173 /** 13174 * <p>Enables or disables the duplication of the parent's state into this view. When 13175 * duplication is enabled, this view gets its drawable state from its parent rather 13176 * than from its own internal properties.</p> 13177 * 13178 * <p>Note: in the current implementation, setting this property to true after the 13179 * view was added to a ViewGroup might have no effect at all. This property should 13180 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 13181 * 13182 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 13183 * property is enabled, an exception will be thrown.</p> 13184 * 13185 * <p>Note: if the child view uses and updates additionnal states which are unknown to the 13186 * parent, these states should not be affected by this method.</p> 13187 * 13188 * @param enabled True to enable duplication of the parent's drawable state, false 13189 * to disable it. 13190 * 13191 * @see #getDrawableState() 13192 * @see #isDuplicateParentStateEnabled() 13193 */ 13194 public void setDuplicateParentStateEnabled(boolean enabled) { 13195 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 13196 } 13197 13198 /** 13199 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 13200 * 13201 * @return True if this view's drawable state is duplicated from the parent, 13202 * false otherwise 13203 * 13204 * @see #getDrawableState() 13205 * @see #setDuplicateParentStateEnabled(boolean) 13206 */ 13207 public boolean isDuplicateParentStateEnabled() { 13208 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 13209 } 13210 13211 /** 13212 * <p>Specifies the type of layer backing this view. The layer can be 13213 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 13214 * {@link #LAYER_TYPE_HARDWARE}.</p> 13215 * 13216 * <p>A layer is associated with an optional {@link android.graphics.Paint} 13217 * instance that controls how the layer is composed on screen. The following 13218 * properties of the paint are taken into account when composing the layer:</p> 13219 * <ul> 13220 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 13221 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 13222 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 13223 * </ul> 13224 * 13225 * <p>If this view has an alpha value set to < 1.0 by calling 13226 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded 13227 * by this view's alpha value.</p> 13228 * 13229 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 13230 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 13231 * for more information on when and how to use layers.</p> 13232 * 13233 * @param layerType The type of layer to use with this view, must be one of 13234 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 13235 * {@link #LAYER_TYPE_HARDWARE} 13236 * @param paint The paint used to compose the layer. This argument is optional 13237 * and can be null. It is ignored when the layer type is 13238 * {@link #LAYER_TYPE_NONE} 13239 * 13240 * @see #getLayerType() 13241 * @see #LAYER_TYPE_NONE 13242 * @see #LAYER_TYPE_SOFTWARE 13243 * @see #LAYER_TYPE_HARDWARE 13244 * @see #setAlpha(float) 13245 * 13246 * @attr ref android.R.styleable#View_layerType 13247 */ 13248 public void setLayerType(int layerType, Paint paint) { 13249 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 13250 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 13251 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 13252 } 13253 13254 if (layerType == mLayerType) { 13255 setLayerPaint(paint); 13256 return; 13257 } 13258 13259 // Destroy any previous software drawing cache if needed 13260 switch (mLayerType) { 13261 case LAYER_TYPE_HARDWARE: 13262 destroyLayer(false); 13263 // fall through - non-accelerated views may use software layer mechanism instead 13264 case LAYER_TYPE_SOFTWARE: 13265 destroyDrawingCache(); 13266 break; 13267 default: 13268 break; 13269 } 13270 13271 mLayerType = layerType; 13272 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE; 13273 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint); 13274 mLocalDirtyRect = layerDisabled ? null : new Rect(); 13275 13276 invalidateParentCaches(); 13277 invalidate(true); 13278 } 13279 13280 /** 13281 * Updates the {@link Paint} object used with the current layer (used only if the current 13282 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 13283 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 13284 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 13285 * ensure that the view gets redrawn immediately. 13286 * 13287 * <p>A layer is associated with an optional {@link android.graphics.Paint} 13288 * instance that controls how the layer is composed on screen. The following 13289 * properties of the paint are taken into account when composing the layer:</p> 13290 * <ul> 13291 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 13292 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 13293 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 13294 * </ul> 13295 * 13296 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 13297 * alpha value of the layer's paint is superceded by this view's alpha value.</p> 13298 * 13299 * @param paint The paint used to compose the layer. This argument is optional 13300 * and can be null. It is ignored when the layer type is 13301 * {@link #LAYER_TYPE_NONE} 13302 * 13303 * @see #setLayerType(int, android.graphics.Paint) 13304 */ 13305 public void setLayerPaint(Paint paint) { 13306 int layerType = getLayerType(); 13307 if (layerType != LAYER_TYPE_NONE) { 13308 mLayerPaint = paint == null ? new Paint() : paint; 13309 if (layerType == LAYER_TYPE_HARDWARE) { 13310 HardwareLayer layer = getHardwareLayer(); 13311 if (layer != null) { 13312 layer.setLayerPaint(mLayerPaint); 13313 } 13314 invalidateViewProperty(false, false); 13315 } else { 13316 invalidate(); 13317 } 13318 } 13319 } 13320 13321 /** 13322 * Indicates whether this view has a static layer. A view with layer type 13323 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are 13324 * dynamic. 13325 */ 13326 boolean hasStaticLayer() { 13327 return true; 13328 } 13329 13330 /** 13331 * Indicates what type of layer is currently associated with this view. By default 13332 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 13333 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 13334 * for more information on the different types of layers. 13335 * 13336 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 13337 * {@link #LAYER_TYPE_HARDWARE} 13338 * 13339 * @see #setLayerType(int, android.graphics.Paint) 13340 * @see #buildLayer() 13341 * @see #LAYER_TYPE_NONE 13342 * @see #LAYER_TYPE_SOFTWARE 13343 * @see #LAYER_TYPE_HARDWARE 13344 */ 13345 public int getLayerType() { 13346 return mLayerType; 13347 } 13348 13349 /** 13350 * Forces this view's layer to be created and this view to be rendered 13351 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 13352 * invoking this method will have no effect. 13353 * 13354 * This method can for instance be used to render a view into its layer before 13355 * starting an animation. If this view is complex, rendering into the layer 13356 * before starting the animation will avoid skipping frames. 13357 * 13358 * @throws IllegalStateException If this view is not attached to a window 13359 * 13360 * @see #setLayerType(int, android.graphics.Paint) 13361 */ 13362 public void buildLayer() { 13363 if (mLayerType == LAYER_TYPE_NONE) return; 13364 13365 final AttachInfo attachInfo = mAttachInfo; 13366 if (attachInfo == null) { 13367 throw new IllegalStateException("This view must be attached to a window first"); 13368 } 13369 13370 switch (mLayerType) { 13371 case LAYER_TYPE_HARDWARE: 13372 getHardwareLayer(); 13373 // TODO: We need a better way to handle this case 13374 // If views have registered pre-draw listeners they need 13375 // to be notified before we build the layer. Those listeners 13376 // may however rely on other events to happen first so we 13377 // cannot just invoke them here until they don't cancel the 13378 // current frame 13379 if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) { 13380 attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates(); 13381 } 13382 break; 13383 case LAYER_TYPE_SOFTWARE: 13384 buildDrawingCache(true); 13385 break; 13386 } 13387 } 13388 13389 /** 13390 * <p>Returns a hardware layer that can be used to draw this view again 13391 * without executing its draw method.</p> 13392 * 13393 * @return A HardwareLayer ready to render, or null if an error occurred. 13394 */ 13395 HardwareLayer getHardwareLayer() { 13396 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null || 13397 !mAttachInfo.mHardwareRenderer.isEnabled()) { 13398 return null; 13399 } 13400 13401 final int width = mRight - mLeft; 13402 final int height = mBottom - mTop; 13403 13404 if (width == 0 || height == 0) { 13405 return null; 13406 } 13407 13408 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) { 13409 if (mHardwareLayer == null) { 13410 mHardwareLayer = mAttachInfo.mHardwareRenderer.createDisplayListLayer( 13411 width, height); 13412 mLocalDirtyRect.set(0, 0, width, height); 13413 } else if (mHardwareLayer.isValid()) { 13414 // This should not be necessary but applications that change 13415 // the parameters of their background drawable without calling 13416 // this.setBackground(Drawable) can leave the view in a bad state 13417 // (for instance isOpaque() returns true, but the background is 13418 // not opaque.) 13419 computeOpaqueFlags(); 13420 13421 if (mHardwareLayer.prepare(width, height, isOpaque())) { 13422 mLocalDirtyRect.set(0, 0, width, height); 13423 } 13424 } 13425 13426 // The layer is not valid if the underlying GPU resources cannot be allocated 13427 mHardwareLayer.flushChanges(); 13428 if (!mHardwareLayer.isValid()) { 13429 return null; 13430 } 13431 13432 mHardwareLayer.setLayerPaint(mLayerPaint); 13433 RenderNode displayList = mHardwareLayer.startRecording(); 13434 updateDisplayListIfDirty(displayList, true); 13435 mHardwareLayer.endRecording(mLocalDirtyRect); 13436 mLocalDirtyRect.setEmpty(); 13437 } 13438 13439 return mHardwareLayer; 13440 } 13441 13442 /** 13443 * Destroys this View's hardware layer if possible. 13444 * 13445 * @return True if the layer was destroyed, false otherwise. 13446 * 13447 * @see #setLayerType(int, android.graphics.Paint) 13448 * @see #LAYER_TYPE_HARDWARE 13449 */ 13450 boolean destroyLayer(boolean valid) { 13451 if (mHardwareLayer != null) { 13452 mHardwareLayer.destroy(); 13453 mHardwareLayer = null; 13454 13455 invalidate(true); 13456 invalidateParentCaches(); 13457 return true; 13458 } 13459 return false; 13460 } 13461 13462 /** 13463 * Destroys all hardware rendering resources. This method is invoked 13464 * when the system needs to reclaim resources. Upon execution of this 13465 * method, you should free any OpenGL resources created by the view. 13466 * 13467 * Note: you <strong>must</strong> call 13468 * <code>super.destroyHardwareResources()</code> when overriding 13469 * this method. 13470 * 13471 * @hide 13472 */ 13473 protected void destroyHardwareResources() { 13474 resetDisplayList(); 13475 destroyLayer(true); 13476 } 13477 13478 /** 13479 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 13480 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 13481 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 13482 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 13483 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 13484 * null.</p> 13485 * 13486 * <p>Enabling the drawing cache is similar to 13487 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 13488 * acceleration is turned off. When hardware acceleration is turned on, enabling the 13489 * drawing cache has no effect on rendering because the system uses a different mechanism 13490 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 13491 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 13492 * for information on how to enable software and hardware layers.</p> 13493 * 13494 * <p>This API can be used to manually generate 13495 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 13496 * {@link #getDrawingCache()}.</p> 13497 * 13498 * @param enabled true to enable the drawing cache, false otherwise 13499 * 13500 * @see #isDrawingCacheEnabled() 13501 * @see #getDrawingCache() 13502 * @see #buildDrawingCache() 13503 * @see #setLayerType(int, android.graphics.Paint) 13504 */ 13505 public void setDrawingCacheEnabled(boolean enabled) { 13506 mCachingFailed = false; 13507 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 13508 } 13509 13510 /** 13511 * <p>Indicates whether the drawing cache is enabled for this view.</p> 13512 * 13513 * @return true if the drawing cache is enabled 13514 * 13515 * @see #setDrawingCacheEnabled(boolean) 13516 * @see #getDrawingCache() 13517 */ 13518 @ViewDebug.ExportedProperty(category = "drawing") 13519 public boolean isDrawingCacheEnabled() { 13520 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 13521 } 13522 13523 /** 13524 * Debugging utility which recursively outputs the dirty state of a view and its 13525 * descendants. 13526 * 13527 * @hide 13528 */ 13529 @SuppressWarnings({"UnusedDeclaration"}) 13530 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 13531 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) + 13532 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" + 13533 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) + 13534 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 13535 if (clear) { 13536 mPrivateFlags &= clearMask; 13537 } 13538 if (this instanceof ViewGroup) { 13539 ViewGroup parent = (ViewGroup) this; 13540 final int count = parent.getChildCount(); 13541 for (int i = 0; i < count; i++) { 13542 final View child = parent.getChildAt(i); 13543 child.outputDirtyFlags(indent + " ", clear, clearMask); 13544 } 13545 } 13546 } 13547 13548 /** 13549 * This method is used by ViewGroup to cause its children to restore or recreate their 13550 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 13551 * to recreate its own display list, which would happen if it went through the normal 13552 * draw/dispatchDraw mechanisms. 13553 * 13554 * @hide 13555 */ 13556 protected void dispatchGetDisplayList() {} 13557 13558 /** 13559 * A view that is not attached or hardware accelerated cannot create a display list. 13560 * This method checks these conditions and returns the appropriate result. 13561 * 13562 * @return true if view has the ability to create a display list, false otherwise. 13563 * 13564 * @hide 13565 */ 13566 public boolean canHaveDisplayList() { 13567 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 13568 } 13569 13570 /** 13571 * Returns a DisplayList. If the incoming displayList is null, one will be created. 13572 * Otherwise, the same display list will be returned (after having been rendered into 13573 * along the way, depending on the invalidation state of the view). 13574 * 13575 * @param renderNode The previous version of this displayList, could be null. 13576 * @param isLayer Whether the requester of the display list is a layer. If so, 13577 * the view will avoid creating a layer inside the resulting display list. 13578 * @return A new or reused DisplayList object. 13579 */ 13580 private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) { 13581 if (renderNode == null) { 13582 throw new IllegalArgumentException("RenderNode must not be null"); 13583 } 13584 if (!canHaveDisplayList()) { 13585 // can't populate RenderNode, don't try 13586 return; 13587 } 13588 13589 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 13590 || !renderNode.isValid() 13591 || (!isLayer && mRecreateDisplayList)) { 13592 // Don't need to recreate the display list, just need to tell our 13593 // children to restore/recreate theirs 13594 if (renderNode.isValid() 13595 && !isLayer 13596 && !mRecreateDisplayList) { 13597 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13598 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13599 dispatchGetDisplayList(); 13600 13601 return; // no work needed 13602 } 13603 13604 if (!isLayer) { 13605 // If we got here, we're recreating it. Mark it as such to ensure that 13606 // we copy in child display lists into ours in drawChild() 13607 mRecreateDisplayList = true; 13608 } 13609 13610 boolean caching = false; 13611 int width = mRight - mLeft; 13612 int height = mBottom - mTop; 13613 int layerType = getLayerType(); 13614 13615 final HardwareCanvas canvas = renderNode.start(width, height); 13616 13617 try { 13618 if (!isLayer && layerType != LAYER_TYPE_NONE) { 13619 if (layerType == LAYER_TYPE_HARDWARE) { 13620 final HardwareLayer layer = getHardwareLayer(); 13621 if (layer != null && layer.isValid()) { 13622 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint); 13623 } else { 13624 canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint, 13625 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | 13626 Canvas.CLIP_TO_LAYER_SAVE_FLAG); 13627 } 13628 caching = true; 13629 } else { 13630 buildDrawingCache(true); 13631 Bitmap cache = getDrawingCache(true); 13632 if (cache != null) { 13633 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 13634 caching = true; 13635 } 13636 } 13637 } else { 13638 13639 computeScroll(); 13640 13641 canvas.translate(-mScrollX, -mScrollY); 13642 if (!isLayer) { 13643 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13644 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13645 } 13646 13647 // Fast path for layouts with no backgrounds 13648 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 13649 dispatchDraw(canvas); 13650 if (mOverlay != null && !mOverlay.isEmpty()) { 13651 mOverlay.getOverlayView().draw(canvas); 13652 } 13653 } else { 13654 draw(canvas); 13655 } 13656 } 13657 } finally { 13658 renderNode.end(canvas); 13659 renderNode.setCaching(caching); 13660 if (isLayer) { 13661 renderNode.setLeftTopRightBottom(0, 0, width, height); 13662 } else { 13663 setDisplayListProperties(renderNode); 13664 } 13665 } 13666 } else if (!isLayer) { 13667 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 13668 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13669 } 13670 } 13671 13672 /** 13673 * Returns a RenderNode with View draw content recorded, which can be 13674 * used to draw this view again without executing its draw method. 13675 * 13676 * @return A RenderNode ready to replay, or null if caching is not enabled. 13677 * 13678 * @hide 13679 */ 13680 public RenderNode getDisplayList() { 13681 updateDisplayListIfDirty(mRenderNode, false); 13682 return mRenderNode; 13683 } 13684 13685 private void resetDisplayList() { 13686 if (mRenderNode.isValid()) { 13687 mRenderNode.destroyDisplayListData(); 13688 } 13689 13690 if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) { 13691 mBackgroundDisplayList.destroyDisplayListData(); 13692 } 13693 } 13694 13695 /** 13696 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 13697 * 13698 * @return A non-scaled bitmap representing this view or null if cache is disabled. 13699 * 13700 * @see #getDrawingCache(boolean) 13701 */ 13702 public Bitmap getDrawingCache() { 13703 return getDrawingCache(false); 13704 } 13705 13706 /** 13707 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 13708 * is null when caching is disabled. If caching is enabled and the cache is not ready, 13709 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 13710 * draw from the cache when the cache is enabled. To benefit from the cache, you must 13711 * request the drawing cache by calling this method and draw it on screen if the 13712 * returned bitmap is not null.</p> 13713 * 13714 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 13715 * this method will create a bitmap of the same size as this view. Because this bitmap 13716 * will be drawn scaled by the parent ViewGroup, the result on screen might show 13717 * scaling artifacts. To avoid such artifacts, you should call this method by setting 13718 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 13719 * size than the view. This implies that your application must be able to handle this 13720 * size.</p> 13721 * 13722 * @param autoScale Indicates whether the generated bitmap should be scaled based on 13723 * the current density of the screen when the application is in compatibility 13724 * mode. 13725 * 13726 * @return A bitmap representing this view or null if cache is disabled. 13727 * 13728 * @see #setDrawingCacheEnabled(boolean) 13729 * @see #isDrawingCacheEnabled() 13730 * @see #buildDrawingCache(boolean) 13731 * @see #destroyDrawingCache() 13732 */ 13733 public Bitmap getDrawingCache(boolean autoScale) { 13734 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 13735 return null; 13736 } 13737 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 13738 buildDrawingCache(autoScale); 13739 } 13740 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 13741 } 13742 13743 /** 13744 * <p>Frees the resources used by the drawing cache. If you call 13745 * {@link #buildDrawingCache()} manually without calling 13746 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 13747 * should cleanup the cache with this method afterwards.</p> 13748 * 13749 * @see #setDrawingCacheEnabled(boolean) 13750 * @see #buildDrawingCache() 13751 * @see #getDrawingCache() 13752 */ 13753 public void destroyDrawingCache() { 13754 if (mDrawingCache != null) { 13755 mDrawingCache.recycle(); 13756 mDrawingCache = null; 13757 } 13758 if (mUnscaledDrawingCache != null) { 13759 mUnscaledDrawingCache.recycle(); 13760 mUnscaledDrawingCache = null; 13761 } 13762 } 13763 13764 /** 13765 * Setting a solid background color for the drawing cache's bitmaps will improve 13766 * performance and memory usage. Note, though that this should only be used if this 13767 * view will always be drawn on top of a solid color. 13768 * 13769 * @param color The background color to use for the drawing cache's bitmap 13770 * 13771 * @see #setDrawingCacheEnabled(boolean) 13772 * @see #buildDrawingCache() 13773 * @see #getDrawingCache() 13774 */ 13775 public void setDrawingCacheBackgroundColor(int color) { 13776 if (color != mDrawingCacheBackgroundColor) { 13777 mDrawingCacheBackgroundColor = color; 13778 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 13779 } 13780 } 13781 13782 /** 13783 * @see #setDrawingCacheBackgroundColor(int) 13784 * 13785 * @return The background color to used for the drawing cache's bitmap 13786 */ 13787 public int getDrawingCacheBackgroundColor() { 13788 return mDrawingCacheBackgroundColor; 13789 } 13790 13791 /** 13792 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 13793 * 13794 * @see #buildDrawingCache(boolean) 13795 */ 13796 public void buildDrawingCache() { 13797 buildDrawingCache(false); 13798 } 13799 13800 /** 13801 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 13802 * 13803 * <p>If you call {@link #buildDrawingCache()} manually without calling 13804 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 13805 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 13806 * 13807 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 13808 * this method will create a bitmap of the same size as this view. Because this bitmap 13809 * will be drawn scaled by the parent ViewGroup, the result on screen might show 13810 * scaling artifacts. To avoid such artifacts, you should call this method by setting 13811 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 13812 * size than the view. This implies that your application must be able to handle this 13813 * size.</p> 13814 * 13815 * <p>You should avoid calling this method when hardware acceleration is enabled. If 13816 * you do not need the drawing cache bitmap, calling this method will increase memory 13817 * usage and cause the view to be rendered in software once, thus negatively impacting 13818 * performance.</p> 13819 * 13820 * @see #getDrawingCache() 13821 * @see #destroyDrawingCache() 13822 */ 13823 public void buildDrawingCache(boolean autoScale) { 13824 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 13825 mDrawingCache == null : mUnscaledDrawingCache == null)) { 13826 mCachingFailed = false; 13827 13828 int width = mRight - mLeft; 13829 int height = mBottom - mTop; 13830 13831 final AttachInfo attachInfo = mAttachInfo; 13832 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 13833 13834 if (autoScale && scalingRequired) { 13835 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 13836 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 13837 } 13838 13839 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 13840 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 13841 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 13842 13843 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 13844 final long drawingCacheSize = 13845 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 13846 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 13847 if (width > 0 && height > 0) { 13848 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs " 13849 + projectedBitmapSize + " bytes, only " 13850 + drawingCacheSize + " available"); 13851 } 13852 destroyDrawingCache(); 13853 mCachingFailed = true; 13854 return; 13855 } 13856 13857 boolean clear = true; 13858 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 13859 13860 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 13861 Bitmap.Config quality; 13862 if (!opaque) { 13863 // Never pick ARGB_4444 because it looks awful 13864 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 13865 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 13866 case DRAWING_CACHE_QUALITY_AUTO: 13867 case DRAWING_CACHE_QUALITY_LOW: 13868 case DRAWING_CACHE_QUALITY_HIGH: 13869 default: 13870 quality = Bitmap.Config.ARGB_8888; 13871 break; 13872 } 13873 } else { 13874 // Optimization for translucent windows 13875 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 13876 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 13877 } 13878 13879 // Try to cleanup memory 13880 if (bitmap != null) bitmap.recycle(); 13881 13882 try { 13883 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 13884 width, height, quality); 13885 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 13886 if (autoScale) { 13887 mDrawingCache = bitmap; 13888 } else { 13889 mUnscaledDrawingCache = bitmap; 13890 } 13891 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 13892 } catch (OutOfMemoryError e) { 13893 // If there is not enough memory to create the bitmap cache, just 13894 // ignore the issue as bitmap caches are not required to draw the 13895 // view hierarchy 13896 if (autoScale) { 13897 mDrawingCache = null; 13898 } else { 13899 mUnscaledDrawingCache = null; 13900 } 13901 mCachingFailed = true; 13902 return; 13903 } 13904 13905 clear = drawingCacheBackgroundColor != 0; 13906 } 13907 13908 Canvas canvas; 13909 if (attachInfo != null) { 13910 canvas = attachInfo.mCanvas; 13911 if (canvas == null) { 13912 canvas = new Canvas(); 13913 } 13914 canvas.setBitmap(bitmap); 13915 // Temporarily clobber the cached Canvas in case one of our children 13916 // is also using a drawing cache. Without this, the children would 13917 // steal the canvas by attaching their own bitmap to it and bad, bad 13918 // thing would happen (invisible views, corrupted drawings, etc.) 13919 attachInfo.mCanvas = null; 13920 } else { 13921 // This case should hopefully never or seldom happen 13922 canvas = new Canvas(bitmap); 13923 } 13924 13925 if (clear) { 13926 bitmap.eraseColor(drawingCacheBackgroundColor); 13927 } 13928 13929 computeScroll(); 13930 final int restoreCount = canvas.save(); 13931 13932 if (autoScale && scalingRequired) { 13933 final float scale = attachInfo.mApplicationScale; 13934 canvas.scale(scale, scale); 13935 } 13936 13937 canvas.translate(-mScrollX, -mScrollY); 13938 13939 mPrivateFlags |= PFLAG_DRAWN; 13940 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 13941 mLayerType != LAYER_TYPE_NONE) { 13942 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 13943 } 13944 13945 // Fast path for layouts with no backgrounds 13946 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 13947 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 13948 dispatchDraw(canvas); 13949 if (mOverlay != null && !mOverlay.isEmpty()) { 13950 mOverlay.getOverlayView().draw(canvas); 13951 } 13952 } else { 13953 draw(canvas); 13954 } 13955 13956 canvas.restoreToCount(restoreCount); 13957 canvas.setBitmap(null); 13958 13959 if (attachInfo != null) { 13960 // Restore the cached Canvas for our siblings 13961 attachInfo.mCanvas = canvas; 13962 } 13963 } 13964 } 13965 13966 /** 13967 * Create a snapshot of the view into a bitmap. We should probably make 13968 * some form of this public, but should think about the API. 13969 */ 13970 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 13971 int width = mRight - mLeft; 13972 int height = mBottom - mTop; 13973 13974 final AttachInfo attachInfo = mAttachInfo; 13975 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 13976 width = (int) ((width * scale) + 0.5f); 13977 height = (int) ((height * scale) + 0.5f); 13978 13979 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 13980 width > 0 ? width : 1, height > 0 ? height : 1, quality); 13981 if (bitmap == null) { 13982 throw new OutOfMemoryError(); 13983 } 13984 13985 Resources resources = getResources(); 13986 if (resources != null) { 13987 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 13988 } 13989 13990 Canvas canvas; 13991 if (attachInfo != null) { 13992 canvas = attachInfo.mCanvas; 13993 if (canvas == null) { 13994 canvas = new Canvas(); 13995 } 13996 canvas.setBitmap(bitmap); 13997 // Temporarily clobber the cached Canvas in case one of our children 13998 // is also using a drawing cache. Without this, the children would 13999 // steal the canvas by attaching their own bitmap to it and bad, bad 14000 // things would happen (invisible views, corrupted drawings, etc.) 14001 attachInfo.mCanvas = null; 14002 } else { 14003 // This case should hopefully never or seldom happen 14004 canvas = new Canvas(bitmap); 14005 } 14006 14007 if ((backgroundColor & 0xff000000) != 0) { 14008 bitmap.eraseColor(backgroundColor); 14009 } 14010 14011 computeScroll(); 14012 final int restoreCount = canvas.save(); 14013 canvas.scale(scale, scale); 14014 canvas.translate(-mScrollX, -mScrollY); 14015 14016 // Temporarily remove the dirty mask 14017 int flags = mPrivateFlags; 14018 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14019 14020 // Fast path for layouts with no backgrounds 14021 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 14022 dispatchDraw(canvas); 14023 if (mOverlay != null && !mOverlay.isEmpty()) { 14024 mOverlay.getOverlayView().draw(canvas); 14025 } 14026 } else { 14027 draw(canvas); 14028 } 14029 14030 mPrivateFlags = flags; 14031 14032 canvas.restoreToCount(restoreCount); 14033 canvas.setBitmap(null); 14034 14035 if (attachInfo != null) { 14036 // Restore the cached Canvas for our siblings 14037 attachInfo.mCanvas = canvas; 14038 } 14039 14040 return bitmap; 14041 } 14042 14043 /** 14044 * Indicates whether this View is currently in edit mode. A View is usually 14045 * in edit mode when displayed within a developer tool. For instance, if 14046 * this View is being drawn by a visual user interface builder, this method 14047 * should return true. 14048 * 14049 * Subclasses should check the return value of this method to provide 14050 * different behaviors if their normal behavior might interfere with the 14051 * host environment. For instance: the class spawns a thread in its 14052 * constructor, the drawing code relies on device-specific features, etc. 14053 * 14054 * This method is usually checked in the drawing code of custom widgets. 14055 * 14056 * @return True if this View is in edit mode, false otherwise. 14057 */ 14058 public boolean isInEditMode() { 14059 return false; 14060 } 14061 14062 /** 14063 * If the View draws content inside its padding and enables fading edges, 14064 * it needs to support padding offsets. Padding offsets are added to the 14065 * fading edges to extend the length of the fade so that it covers pixels 14066 * drawn inside the padding. 14067 * 14068 * Subclasses of this class should override this method if they need 14069 * to draw content inside the padding. 14070 * 14071 * @return True if padding offset must be applied, false otherwise. 14072 * 14073 * @see #getLeftPaddingOffset() 14074 * @see #getRightPaddingOffset() 14075 * @see #getTopPaddingOffset() 14076 * @see #getBottomPaddingOffset() 14077 * 14078 * @since CURRENT 14079 */ 14080 protected boolean isPaddingOffsetRequired() { 14081 return false; 14082 } 14083 14084 /** 14085 * Amount by which to extend the left fading region. Called only when 14086 * {@link #isPaddingOffsetRequired()} returns true. 14087 * 14088 * @return The left padding offset in pixels. 14089 * 14090 * @see #isPaddingOffsetRequired() 14091 * 14092 * @since CURRENT 14093 */ 14094 protected int getLeftPaddingOffset() { 14095 return 0; 14096 } 14097 14098 /** 14099 * Amount by which to extend the right fading region. Called only when 14100 * {@link #isPaddingOffsetRequired()} returns true. 14101 * 14102 * @return The right padding offset in pixels. 14103 * 14104 * @see #isPaddingOffsetRequired() 14105 * 14106 * @since CURRENT 14107 */ 14108 protected int getRightPaddingOffset() { 14109 return 0; 14110 } 14111 14112 /** 14113 * Amount by which to extend the top fading region. Called only when 14114 * {@link #isPaddingOffsetRequired()} returns true. 14115 * 14116 * @return The top padding offset in pixels. 14117 * 14118 * @see #isPaddingOffsetRequired() 14119 * 14120 * @since CURRENT 14121 */ 14122 protected int getTopPaddingOffset() { 14123 return 0; 14124 } 14125 14126 /** 14127 * Amount by which to extend the bottom fading region. Called only when 14128 * {@link #isPaddingOffsetRequired()} returns true. 14129 * 14130 * @return The bottom padding offset in pixels. 14131 * 14132 * @see #isPaddingOffsetRequired() 14133 * 14134 * @since CURRENT 14135 */ 14136 protected int getBottomPaddingOffset() { 14137 return 0; 14138 } 14139 14140 /** 14141 * @hide 14142 * @param offsetRequired 14143 */ 14144 protected int getFadeTop(boolean offsetRequired) { 14145 int top = mPaddingTop; 14146 if (offsetRequired) top += getTopPaddingOffset(); 14147 return top; 14148 } 14149 14150 /** 14151 * @hide 14152 * @param offsetRequired 14153 */ 14154 protected int getFadeHeight(boolean offsetRequired) { 14155 int padding = mPaddingTop; 14156 if (offsetRequired) padding += getTopPaddingOffset(); 14157 return mBottom - mTop - mPaddingBottom - padding; 14158 } 14159 14160 /** 14161 * <p>Indicates whether this view is attached to a hardware accelerated 14162 * window or not.</p> 14163 * 14164 * <p>Even if this method returns true, it does not mean that every call 14165 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 14166 * accelerated {@link android.graphics.Canvas}. For instance, if this view 14167 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 14168 * window is hardware accelerated, 14169 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 14170 * return false, and this method will return true.</p> 14171 * 14172 * @return True if the view is attached to a window and the window is 14173 * hardware accelerated; false in any other case. 14174 */ 14175 public boolean isHardwareAccelerated() { 14176 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 14177 } 14178 14179 /** 14180 * Sets a rectangular area on this view to which the view will be clipped 14181 * when it is drawn. Setting the value to null will remove the clip bounds 14182 * and the view will draw normally, using its full bounds. 14183 * 14184 * @param clipBounds The rectangular area, in the local coordinates of 14185 * this view, to which future drawing operations will be clipped. 14186 */ 14187 public void setClipBounds(Rect clipBounds) { 14188 if (clipBounds != null) { 14189 if (clipBounds.equals(mClipBounds)) { 14190 return; 14191 } 14192 if (mClipBounds == null) { 14193 invalidate(); 14194 mClipBounds = new Rect(clipBounds); 14195 } else { 14196 invalidate(Math.min(mClipBounds.left, clipBounds.left), 14197 Math.min(mClipBounds.top, clipBounds.top), 14198 Math.max(mClipBounds.right, clipBounds.right), 14199 Math.max(mClipBounds.bottom, clipBounds.bottom)); 14200 mClipBounds.set(clipBounds); 14201 } 14202 } else { 14203 if (mClipBounds != null) { 14204 invalidate(); 14205 mClipBounds = null; 14206 } 14207 } 14208 } 14209 14210 /** 14211 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 14212 * 14213 * @return A copy of the current clip bounds if clip bounds are set, 14214 * otherwise null. 14215 */ 14216 public Rect getClipBounds() { 14217 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 14218 } 14219 14220 /** 14221 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 14222 * case of an active Animation being run on the view. 14223 */ 14224 private boolean drawAnimation(ViewGroup parent, long drawingTime, 14225 Animation a, boolean scalingRequired) { 14226 Transformation invalidationTransform; 14227 final int flags = parent.mGroupFlags; 14228 final boolean initialized = a.isInitialized(); 14229 if (!initialized) { 14230 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 14231 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 14232 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 14233 onAnimationStart(); 14234 } 14235 14236 final Transformation t = parent.getChildTransformation(); 14237 boolean more = a.getTransformation(drawingTime, t, 1f); 14238 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 14239 if (parent.mInvalidationTransformation == null) { 14240 parent.mInvalidationTransformation = new Transformation(); 14241 } 14242 invalidationTransform = parent.mInvalidationTransformation; 14243 a.getTransformation(drawingTime, invalidationTransform, 1f); 14244 } else { 14245 invalidationTransform = t; 14246 } 14247 14248 if (more) { 14249 if (!a.willChangeBounds()) { 14250 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 14251 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 14252 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 14253 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 14254 // The child need to draw an animation, potentially offscreen, so 14255 // make sure we do not cancel invalidate requests 14256 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 14257 parent.invalidate(mLeft, mTop, mRight, mBottom); 14258 } 14259 } else { 14260 if (parent.mInvalidateRegion == null) { 14261 parent.mInvalidateRegion = new RectF(); 14262 } 14263 final RectF region = parent.mInvalidateRegion; 14264 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 14265 invalidationTransform); 14266 14267 // The child need to draw an animation, potentially offscreen, so 14268 // make sure we do not cancel invalidate requests 14269 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 14270 14271 final int left = mLeft + (int) region.left; 14272 final int top = mTop + (int) region.top; 14273 parent.invalidate(left, top, left + (int) (region.width() + .5f), 14274 top + (int) (region.height() + .5f)); 14275 } 14276 } 14277 return more; 14278 } 14279 14280 /** 14281 * This method is called by getDisplayList() when a display list is recorded for a View. 14282 * It pushes any properties to the RenderNode that aren't managed by the RenderNode. 14283 */ 14284 void setDisplayListProperties(RenderNode renderNode) { 14285 if (renderNode != null) { 14286 renderNode.setHasOverlappingRendering(hasOverlappingRendering()); 14287 if (mParent instanceof ViewGroup) { 14288 renderNode.setClipToBounds( 14289 (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0); 14290 } 14291 float alpha = 1; 14292 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 14293 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 14294 ViewGroup parentVG = (ViewGroup) mParent; 14295 final Transformation t = parentVG.getChildTransformation(); 14296 if (parentVG.getChildStaticTransformation(this, t)) { 14297 final int transformType = t.getTransformationType(); 14298 if (transformType != Transformation.TYPE_IDENTITY) { 14299 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 14300 alpha = t.getAlpha(); 14301 } 14302 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 14303 renderNode.setStaticMatrix(t.getMatrix()); 14304 } 14305 } 14306 } 14307 } 14308 if (mTransformationInfo != null) { 14309 alpha *= getFinalAlpha(); 14310 if (alpha < 1) { 14311 final int multipliedAlpha = (int) (255 * alpha); 14312 if (onSetAlpha(multipliedAlpha)) { 14313 alpha = 1; 14314 } 14315 } 14316 renderNode.setAlpha(alpha); 14317 } else if (alpha < 1) { 14318 renderNode.setAlpha(alpha); 14319 } 14320 } 14321 } 14322 14323 /** 14324 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 14325 * This draw() method is an implementation detail and is not intended to be overridden or 14326 * to be called from anywhere else other than ViewGroup.drawChild(). 14327 */ 14328 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 14329 boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 14330 boolean more = false; 14331 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 14332 final int flags = parent.mGroupFlags; 14333 14334 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) { 14335 parent.getChildTransformation().clear(); 14336 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14337 } 14338 14339 Transformation transformToApply = null; 14340 boolean concatMatrix = false; 14341 14342 boolean scalingRequired = false; 14343 boolean caching; 14344 int layerType = getLayerType(); 14345 14346 final boolean hardwareAccelerated = canvas.isHardwareAccelerated(); 14347 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 || 14348 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) { 14349 caching = true; 14350 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList 14351 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; 14352 } else { 14353 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated; 14354 } 14355 14356 final Animation a = getAnimation(); 14357 if (a != null) { 14358 more = drawAnimation(parent, drawingTime, a, scalingRequired); 14359 concatMatrix = a.willChangeTransformationMatrix(); 14360 if (concatMatrix) { 14361 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 14362 } 14363 transformToApply = parent.getChildTransformation(); 14364 } else { 14365 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { 14366 // No longer animating: clear out old animation matrix 14367 mRenderNode.setAnimationMatrix(null); 14368 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 14369 } 14370 if (!useDisplayListProperties && 14371 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 14372 final Transformation t = parent.getChildTransformation(); 14373 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 14374 if (hasTransform) { 14375 final int transformType = t.getTransformationType(); 14376 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 14377 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 14378 } 14379 } 14380 } 14381 14382 concatMatrix |= !childHasIdentityMatrix; 14383 14384 // Sets the flag as early as possible to allow draw() implementations 14385 // to call invalidate() successfully when doing animations 14386 mPrivateFlags |= PFLAG_DRAWN; 14387 14388 if (!concatMatrix && 14389 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 14390 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 14391 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 14392 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 14393 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 14394 return more; 14395 } 14396 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 14397 14398 if (hardwareAccelerated) { 14399 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 14400 // retain the flag's value temporarily in the mRecreateDisplayList flag 14401 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED; 14402 mPrivateFlags &= ~PFLAG_INVALIDATED; 14403 } 14404 14405 RenderNode displayList = null; 14406 Bitmap cache = null; 14407 boolean hasDisplayList = false; 14408 if (caching) { 14409 if (!hardwareAccelerated) { 14410 if (layerType != LAYER_TYPE_NONE) { 14411 layerType = LAYER_TYPE_SOFTWARE; 14412 buildDrawingCache(true); 14413 } 14414 cache = getDrawingCache(true); 14415 } else { 14416 switch (layerType) { 14417 case LAYER_TYPE_SOFTWARE: 14418 if (useDisplayListProperties) { 14419 hasDisplayList = canHaveDisplayList(); 14420 } else { 14421 buildDrawingCache(true); 14422 cache = getDrawingCache(true); 14423 } 14424 break; 14425 case LAYER_TYPE_HARDWARE: 14426 if (useDisplayListProperties) { 14427 hasDisplayList = canHaveDisplayList(); 14428 } 14429 break; 14430 case LAYER_TYPE_NONE: 14431 // Delay getting the display list until animation-driven alpha values are 14432 // set up and possibly passed on to the view 14433 hasDisplayList = canHaveDisplayList(); 14434 break; 14435 } 14436 } 14437 } 14438 useDisplayListProperties &= hasDisplayList; 14439 if (useDisplayListProperties) { 14440 displayList = getDisplayList(); 14441 if (!displayList.isValid()) { 14442 // Uncommon, but possible. If a view is removed from the hierarchy during the call 14443 // to getDisplayList(), the display list will be marked invalid and we should not 14444 // try to use it again. 14445 displayList = null; 14446 hasDisplayList = false; 14447 useDisplayListProperties = false; 14448 } 14449 } 14450 14451 int sx = 0; 14452 int sy = 0; 14453 if (!hasDisplayList) { 14454 computeScroll(); 14455 sx = mScrollX; 14456 sy = mScrollY; 14457 } 14458 14459 final boolean hasNoCache = cache == null || hasDisplayList; 14460 final boolean offsetForScroll = cache == null && !hasDisplayList && 14461 layerType != LAYER_TYPE_HARDWARE; 14462 14463 int restoreTo = -1; 14464 if (!useDisplayListProperties || transformToApply != null) { 14465 restoreTo = canvas.save(); 14466 } 14467 if (offsetForScroll) { 14468 canvas.translate(mLeft - sx, mTop - sy); 14469 } else { 14470 if (!useDisplayListProperties) { 14471 canvas.translate(mLeft, mTop); 14472 } 14473 if (scalingRequired) { 14474 if (useDisplayListProperties) { 14475 // TODO: Might not need this if we put everything inside the DL 14476 restoreTo = canvas.save(); 14477 } 14478 // mAttachInfo cannot be null, otherwise scalingRequired == false 14479 final float scale = 1.0f / mAttachInfo.mApplicationScale; 14480 canvas.scale(scale, scale); 14481 } 14482 } 14483 14484 float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha()); 14485 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || 14486 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) { 14487 if (transformToApply != null || !childHasIdentityMatrix) { 14488 int transX = 0; 14489 int transY = 0; 14490 14491 if (offsetForScroll) { 14492 transX = -sx; 14493 transY = -sy; 14494 } 14495 14496 if (transformToApply != null) { 14497 if (concatMatrix) { 14498 if (useDisplayListProperties) { 14499 displayList.setAnimationMatrix(transformToApply.getMatrix()); 14500 } else { 14501 // Undo the scroll translation, apply the transformation matrix, 14502 // then redo the scroll translate to get the correct result. 14503 canvas.translate(-transX, -transY); 14504 canvas.concat(transformToApply.getMatrix()); 14505 canvas.translate(transX, transY); 14506 } 14507 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14508 } 14509 14510 float transformAlpha = transformToApply.getAlpha(); 14511 if (transformAlpha < 1) { 14512 alpha *= transformAlpha; 14513 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14514 } 14515 } 14516 14517 if (!childHasIdentityMatrix && !useDisplayListProperties) { 14518 canvas.translate(-transX, -transY); 14519 canvas.concat(getMatrix()); 14520 canvas.translate(transX, transY); 14521 } 14522 } 14523 14524 // Deal with alpha if it is or used to be <1 14525 if (alpha < 1 || 14526 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) { 14527 if (alpha < 1) { 14528 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 14529 } else { 14530 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 14531 } 14532 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 14533 if (hasNoCache) { 14534 final int multipliedAlpha = (int) (255 * alpha); 14535 if (!onSetAlpha(multipliedAlpha)) { 14536 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 14537 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 || 14538 layerType != LAYER_TYPE_NONE) { 14539 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; 14540 } 14541 if (useDisplayListProperties) { 14542 displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 14543 } else if (layerType == LAYER_TYPE_NONE) { 14544 final int scrollX = hasDisplayList ? 0 : sx; 14545 final int scrollY = hasDisplayList ? 0 : sy; 14546 canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft, 14547 scrollY + mBottom - mTop, multipliedAlpha, layerFlags); 14548 } 14549 } else { 14550 // Alpha is handled by the child directly, clobber the layer's alpha 14551 mPrivateFlags |= PFLAG_ALPHA_SET; 14552 } 14553 } 14554 } 14555 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 14556 onSetAlpha(255); 14557 mPrivateFlags &= ~PFLAG_ALPHA_SET; 14558 } 14559 14560 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN && 14561 !useDisplayListProperties && cache == null) { 14562 if (offsetForScroll) { 14563 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop)); 14564 } else { 14565 if (!scalingRequired || cache == null) { 14566 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop); 14567 } else { 14568 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 14569 } 14570 } 14571 } 14572 14573 if (!useDisplayListProperties && hasDisplayList) { 14574 displayList = getDisplayList(); 14575 if (!displayList.isValid()) { 14576 // Uncommon, but possible. If a view is removed from the hierarchy during the call 14577 // to getDisplayList(), the display list will be marked invalid and we should not 14578 // try to use it again. 14579 displayList = null; 14580 hasDisplayList = false; 14581 } 14582 } 14583 14584 if (hasNoCache) { 14585 boolean layerRendered = false; 14586 if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) { 14587 final HardwareLayer layer = getHardwareLayer(); 14588 if (layer != null && layer.isValid()) { 14589 mLayerPaint.setAlpha((int) (alpha * 255)); 14590 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint); 14591 layerRendered = true; 14592 } else { 14593 final int scrollX = hasDisplayList ? 0 : sx; 14594 final int scrollY = hasDisplayList ? 0 : sy; 14595 canvas.saveLayer(scrollX, scrollY, 14596 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint, 14597 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); 14598 } 14599 } 14600 14601 if (!layerRendered) { 14602 if (!hasDisplayList) { 14603 // Fast path for layouts with no backgrounds 14604 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 14605 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14606 dispatchDraw(canvas); 14607 } else { 14608 draw(canvas); 14609 } 14610 } else { 14611 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14612 ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags); 14613 } 14614 } 14615 } else if (cache != null) { 14616 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 14617 Paint cachePaint; 14618 14619 if (layerType == LAYER_TYPE_NONE) { 14620 cachePaint = parent.mCachePaint; 14621 if (cachePaint == null) { 14622 cachePaint = new Paint(); 14623 cachePaint.setDither(false); 14624 parent.mCachePaint = cachePaint; 14625 } 14626 if (alpha < 1) { 14627 cachePaint.setAlpha((int) (alpha * 255)); 14628 parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; 14629 } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) { 14630 cachePaint.setAlpha(255); 14631 parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE; 14632 } 14633 } else { 14634 cachePaint = mLayerPaint; 14635 cachePaint.setAlpha((int) (alpha * 255)); 14636 } 14637 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 14638 } 14639 14640 if (restoreTo >= 0) { 14641 canvas.restoreToCount(restoreTo); 14642 } 14643 14644 if (a != null && !more) { 14645 if (!hardwareAccelerated && !a.getFillAfter()) { 14646 onSetAlpha(255); 14647 } 14648 parent.finishAnimatingView(this, a); 14649 } 14650 14651 if (more && hardwareAccelerated) { 14652 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 14653 // alpha animations should cause the child to recreate its display list 14654 invalidate(true); 14655 } 14656 } 14657 14658 mRecreateDisplayList = false; 14659 14660 return more; 14661 } 14662 14663 /** 14664 * Manually render this view (and all of its children) to the given Canvas. 14665 * The view must have already done a full layout before this function is 14666 * called. When implementing a view, implement 14667 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 14668 * If you do need to override this method, call the superclass version. 14669 * 14670 * @param canvas The Canvas to which the View is rendered. 14671 */ 14672 public void draw(Canvas canvas) { 14673 if (mClipBounds != null) { 14674 canvas.clipRect(mClipBounds); 14675 } 14676 final int privateFlags = mPrivateFlags; 14677 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 14678 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 14679 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 14680 14681 /* 14682 * Draw traversal performs several drawing steps which must be executed 14683 * in the appropriate order: 14684 * 14685 * 1. Draw the background 14686 * 2. If necessary, save the canvas' layers to prepare for fading 14687 * 3. Draw view's content 14688 * 4. Draw children 14689 * 5. If necessary, draw the fading edges and restore layers 14690 * 6. Draw decorations (scrollbars for instance) 14691 */ 14692 14693 // Step 1, draw the background, if needed 14694 int saveCount; 14695 14696 if (!dirtyOpaque) { 14697 drawBackground(canvas); 14698 } 14699 14700 // skip step 2 & 5 if possible (common case) 14701 final int viewFlags = mViewFlags; 14702 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 14703 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 14704 if (!verticalEdges && !horizontalEdges) { 14705 // Step 3, draw the content 14706 if (!dirtyOpaque) onDraw(canvas); 14707 14708 // Step 4, draw the children 14709 dispatchDraw(canvas); 14710 14711 // Step 6, draw decorations (scrollbars) 14712 onDrawScrollBars(canvas); 14713 14714 if (mOverlay != null && !mOverlay.isEmpty()) { 14715 mOverlay.getOverlayView().dispatchDraw(canvas); 14716 } 14717 14718 // we're done... 14719 return; 14720 } 14721 14722 /* 14723 * Here we do the full fledged routine... 14724 * (this is an uncommon case where speed matters less, 14725 * this is why we repeat some of the tests that have been 14726 * done above) 14727 */ 14728 14729 boolean drawTop = false; 14730 boolean drawBottom = false; 14731 boolean drawLeft = false; 14732 boolean drawRight = false; 14733 14734 float topFadeStrength = 0.0f; 14735 float bottomFadeStrength = 0.0f; 14736 float leftFadeStrength = 0.0f; 14737 float rightFadeStrength = 0.0f; 14738 14739 // Step 2, save the canvas' layers 14740 int paddingLeft = mPaddingLeft; 14741 14742 final boolean offsetRequired = isPaddingOffsetRequired(); 14743 if (offsetRequired) { 14744 paddingLeft += getLeftPaddingOffset(); 14745 } 14746 14747 int left = mScrollX + paddingLeft; 14748 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 14749 int top = mScrollY + getFadeTop(offsetRequired); 14750 int bottom = top + getFadeHeight(offsetRequired); 14751 14752 if (offsetRequired) { 14753 right += getRightPaddingOffset(); 14754 bottom += getBottomPaddingOffset(); 14755 } 14756 14757 final ScrollabilityCache scrollabilityCache = mScrollCache; 14758 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 14759 int length = (int) fadeHeight; 14760 14761 // clip the fade length if top and bottom fades overlap 14762 // overlapping fades produce odd-looking artifacts 14763 if (verticalEdges && (top + length > bottom - length)) { 14764 length = (bottom - top) / 2; 14765 } 14766 14767 // also clip horizontal fades if necessary 14768 if (horizontalEdges && (left + length > right - length)) { 14769 length = (right - left) / 2; 14770 } 14771 14772 if (verticalEdges) { 14773 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 14774 drawTop = topFadeStrength * fadeHeight > 1.0f; 14775 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 14776 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 14777 } 14778 14779 if (horizontalEdges) { 14780 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 14781 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 14782 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 14783 drawRight = rightFadeStrength * fadeHeight > 1.0f; 14784 } 14785 14786 saveCount = canvas.getSaveCount(); 14787 14788 int solidColor = getSolidColor(); 14789 if (solidColor == 0) { 14790 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 14791 14792 if (drawTop) { 14793 canvas.saveLayer(left, top, right, top + length, null, flags); 14794 } 14795 14796 if (drawBottom) { 14797 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 14798 } 14799 14800 if (drawLeft) { 14801 canvas.saveLayer(left, top, left + length, bottom, null, flags); 14802 } 14803 14804 if (drawRight) { 14805 canvas.saveLayer(right - length, top, right, bottom, null, flags); 14806 } 14807 } else { 14808 scrollabilityCache.setFadeColor(solidColor); 14809 } 14810 14811 // Step 3, draw the content 14812 if (!dirtyOpaque) onDraw(canvas); 14813 14814 // Step 4, draw the children 14815 dispatchDraw(canvas); 14816 14817 // Step 5, draw the fade effect and restore layers 14818 final Paint p = scrollabilityCache.paint; 14819 final Matrix matrix = scrollabilityCache.matrix; 14820 final Shader fade = scrollabilityCache.shader; 14821 14822 if (drawTop) { 14823 matrix.setScale(1, fadeHeight * topFadeStrength); 14824 matrix.postTranslate(left, top); 14825 fade.setLocalMatrix(matrix); 14826 canvas.drawRect(left, top, right, top + length, p); 14827 } 14828 14829 if (drawBottom) { 14830 matrix.setScale(1, fadeHeight * bottomFadeStrength); 14831 matrix.postRotate(180); 14832 matrix.postTranslate(left, bottom); 14833 fade.setLocalMatrix(matrix); 14834 canvas.drawRect(left, bottom - length, right, bottom, p); 14835 } 14836 14837 if (drawLeft) { 14838 matrix.setScale(1, fadeHeight * leftFadeStrength); 14839 matrix.postRotate(-90); 14840 matrix.postTranslate(left, top); 14841 fade.setLocalMatrix(matrix); 14842 canvas.drawRect(left, top, left + length, bottom, p); 14843 } 14844 14845 if (drawRight) { 14846 matrix.setScale(1, fadeHeight * rightFadeStrength); 14847 matrix.postRotate(90); 14848 matrix.postTranslate(right, top); 14849 fade.setLocalMatrix(matrix); 14850 canvas.drawRect(right - length, top, right, bottom, p); 14851 } 14852 14853 canvas.restoreToCount(saveCount); 14854 14855 // Step 6, draw decorations (scrollbars) 14856 onDrawScrollBars(canvas); 14857 14858 if (mOverlay != null && !mOverlay.isEmpty()) { 14859 mOverlay.getOverlayView().dispatchDraw(canvas); 14860 } 14861 } 14862 14863 /** 14864 * Draws the background onto the specified canvas. 14865 * 14866 * @param canvas Canvas on which to draw the background 14867 */ 14868 private void drawBackground(Canvas canvas) { 14869 final Drawable background = mBackground; 14870 if (background == null) { 14871 return; 14872 } 14873 14874 if (mBackgroundSizeChanged) { 14875 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 14876 mBackgroundSizeChanged = false; 14877 queryOutlineFromBackgroundIfUndefined(); 14878 } 14879 14880 // Attempt to use a display list if requested. 14881 if (canvas.isHardwareAccelerated() && mAttachInfo != null 14882 && mAttachInfo.mHardwareRenderer != null) { 14883 mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList); 14884 14885 final RenderNode displayList = mBackgroundDisplayList; 14886 if (displayList != null && displayList.isValid()) { 14887 setBackgroundDisplayListProperties(displayList); 14888 ((HardwareCanvas) canvas).drawDisplayList(displayList); 14889 return; 14890 } 14891 } 14892 14893 final int scrollX = mScrollX; 14894 final int scrollY = mScrollY; 14895 if ((scrollX | scrollY) == 0) { 14896 background.draw(canvas); 14897 } else { 14898 canvas.translate(scrollX, scrollY); 14899 background.draw(canvas); 14900 canvas.translate(-scrollX, -scrollY); 14901 } 14902 } 14903 14904 /** 14905 * Set up background drawable display list properties. 14906 * 14907 * @param displayList Valid display list for the background drawable 14908 */ 14909 private void setBackgroundDisplayListProperties(RenderNode displayList) { 14910 displayList.setTranslationX(mScrollX); 14911 displayList.setTranslationY(mScrollY); 14912 } 14913 14914 /** 14915 * Creates a new display list or updates the existing display list for the 14916 * specified Drawable. 14917 * 14918 * @param drawable Drawable for which to create a display list 14919 * @param displayList Existing display list, or {@code null} 14920 * @return A valid display list for the specified drawable 14921 */ 14922 private RenderNode getDrawableDisplayList(Drawable drawable, RenderNode displayList) { 14923 if (displayList == null) { 14924 displayList = RenderNode.create(drawable.getClass().getName()); 14925 } 14926 14927 final Rect bounds = drawable.getBounds(); 14928 final int width = bounds.width(); 14929 final int height = bounds.height(); 14930 final HardwareCanvas canvas = displayList.start(width, height); 14931 try { 14932 drawable.draw(canvas); 14933 } finally { 14934 displayList.end(canvas); 14935 } 14936 14937 // Set up drawable properties that are view-independent. 14938 displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); 14939 displayList.setProjectBackwards(drawable.isProjected()); 14940 displayList.setProjectionReceiver(true); 14941 displayList.setClipToBounds(false); 14942 return displayList; 14943 } 14944 14945 /** 14946 * Returns the overlay for this view, creating it if it does not yet exist. 14947 * Adding drawables to the overlay will cause them to be displayed whenever 14948 * the view itself is redrawn. Objects in the overlay should be actively 14949 * managed: remove them when they should not be displayed anymore. The 14950 * overlay will always have the same size as its host view. 14951 * 14952 * <p>Note: Overlays do not currently work correctly with {@link 14953 * SurfaceView} or {@link TextureView}; contents in overlays for these 14954 * types of views may not display correctly.</p> 14955 * 14956 * @return The ViewOverlay object for this view. 14957 * @see ViewOverlay 14958 */ 14959 public ViewOverlay getOverlay() { 14960 if (mOverlay == null) { 14961 mOverlay = new ViewOverlay(mContext, this); 14962 } 14963 return mOverlay; 14964 } 14965 14966 /** 14967 * Override this if your view is known to always be drawn on top of a solid color background, 14968 * and needs to draw fading edges. Returning a non-zero color enables the view system to 14969 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 14970 * should be set to 0xFF. 14971 * 14972 * @see #setVerticalFadingEdgeEnabled(boolean) 14973 * @see #setHorizontalFadingEdgeEnabled(boolean) 14974 * 14975 * @return The known solid color background for this view, or 0 if the color may vary 14976 */ 14977 @ViewDebug.ExportedProperty(category = "drawing") 14978 public int getSolidColor() { 14979 return 0; 14980 } 14981 14982 /** 14983 * Build a human readable string representation of the specified view flags. 14984 * 14985 * @param flags the view flags to convert to a string 14986 * @return a String representing the supplied flags 14987 */ 14988 private static String printFlags(int flags) { 14989 String output = ""; 14990 int numFlags = 0; 14991 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 14992 output += "TAKES_FOCUS"; 14993 numFlags++; 14994 } 14995 14996 switch (flags & VISIBILITY_MASK) { 14997 case INVISIBLE: 14998 if (numFlags > 0) { 14999 output += " "; 15000 } 15001 output += "INVISIBLE"; 15002 // USELESS HERE numFlags++; 15003 break; 15004 case GONE: 15005 if (numFlags > 0) { 15006 output += " "; 15007 } 15008 output += "GONE"; 15009 // USELESS HERE numFlags++; 15010 break; 15011 default: 15012 break; 15013 } 15014 return output; 15015 } 15016 15017 /** 15018 * Build a human readable string representation of the specified private 15019 * view flags. 15020 * 15021 * @param privateFlags the private view flags to convert to a string 15022 * @return a String representing the supplied flags 15023 */ 15024 private static String printPrivateFlags(int privateFlags) { 15025 String output = ""; 15026 int numFlags = 0; 15027 15028 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 15029 output += "WANTS_FOCUS"; 15030 numFlags++; 15031 } 15032 15033 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 15034 if (numFlags > 0) { 15035 output += " "; 15036 } 15037 output += "FOCUSED"; 15038 numFlags++; 15039 } 15040 15041 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 15042 if (numFlags > 0) { 15043 output += " "; 15044 } 15045 output += "SELECTED"; 15046 numFlags++; 15047 } 15048 15049 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 15050 if (numFlags > 0) { 15051 output += " "; 15052 } 15053 output += "IS_ROOT_NAMESPACE"; 15054 numFlags++; 15055 } 15056 15057 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 15058 if (numFlags > 0) { 15059 output += " "; 15060 } 15061 output += "HAS_BOUNDS"; 15062 numFlags++; 15063 } 15064 15065 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 15066 if (numFlags > 0) { 15067 output += " "; 15068 } 15069 output += "DRAWN"; 15070 // USELESS HERE numFlags++; 15071 } 15072 return output; 15073 } 15074 15075 /** 15076 * <p>Indicates whether or not this view's layout will be requested during 15077 * the next hierarchy layout pass.</p> 15078 * 15079 * @return true if the layout will be forced during next layout pass 15080 */ 15081 public boolean isLayoutRequested() { 15082 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 15083 } 15084 15085 /** 15086 * Return true if o is a ViewGroup that is laying out using optical bounds. 15087 * @hide 15088 */ 15089 public static boolean isLayoutModeOptical(Object o) { 15090 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 15091 } 15092 15093 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 15094 Insets parentInsets = mParent instanceof View ? 15095 ((View) mParent).getOpticalInsets() : Insets.NONE; 15096 Insets childInsets = getOpticalInsets(); 15097 return setFrame( 15098 left + parentInsets.left - childInsets.left, 15099 top + parentInsets.top - childInsets.top, 15100 right + parentInsets.left + childInsets.right, 15101 bottom + parentInsets.top + childInsets.bottom); 15102 } 15103 15104 /** 15105 * Assign a size and position to a view and all of its 15106 * descendants 15107 * 15108 * <p>This is the second phase of the layout mechanism. 15109 * (The first is measuring). In this phase, each parent calls 15110 * layout on all of its children to position them. 15111 * This is typically done using the child measurements 15112 * that were stored in the measure pass().</p> 15113 * 15114 * <p>Derived classes should not override this method. 15115 * Derived classes with children should override 15116 * onLayout. In that method, they should 15117 * call layout on each of their children.</p> 15118 * 15119 * @param l Left position, relative to parent 15120 * @param t Top position, relative to parent 15121 * @param r Right position, relative to parent 15122 * @param b Bottom position, relative to parent 15123 */ 15124 @SuppressWarnings({"unchecked"}) 15125 public void layout(int l, int t, int r, int b) { 15126 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 15127 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 15128 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 15129 } 15130 15131 int oldL = mLeft; 15132 int oldT = mTop; 15133 int oldB = mBottom; 15134 int oldR = mRight; 15135 15136 boolean changed = isLayoutModeOptical(mParent) ? 15137 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 15138 15139 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 15140 onLayout(changed, l, t, r, b); 15141 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 15142 15143 ListenerInfo li = mListenerInfo; 15144 if (li != null && li.mOnLayoutChangeListeners != null) { 15145 ArrayList<OnLayoutChangeListener> listenersCopy = 15146 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 15147 int numListeners = listenersCopy.size(); 15148 for (int i = 0; i < numListeners; ++i) { 15149 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 15150 } 15151 } 15152 } 15153 15154 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 15155 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 15156 } 15157 15158 /** 15159 * Called from layout when this view should 15160 * assign a size and position to each of its children. 15161 * 15162 * Derived classes with children should override 15163 * this method and call layout on each of 15164 * their children. 15165 * @param changed This is a new size or position for this view 15166 * @param left Left position, relative to parent 15167 * @param top Top position, relative to parent 15168 * @param right Right position, relative to parent 15169 * @param bottom Bottom position, relative to parent 15170 */ 15171 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 15172 } 15173 15174 /** 15175 * Assign a size and position to this view. 15176 * 15177 * This is called from layout. 15178 * 15179 * @param left Left position, relative to parent 15180 * @param top Top position, relative to parent 15181 * @param right Right position, relative to parent 15182 * @param bottom Bottom position, relative to parent 15183 * @return true if the new size and position are different than the 15184 * previous ones 15185 * {@hide} 15186 */ 15187 protected boolean setFrame(int left, int top, int right, int bottom) { 15188 boolean changed = false; 15189 15190 if (DBG) { 15191 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 15192 + right + "," + bottom + ")"); 15193 } 15194 15195 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 15196 changed = true; 15197 15198 // Remember our drawn bit 15199 int drawn = mPrivateFlags & PFLAG_DRAWN; 15200 15201 int oldWidth = mRight - mLeft; 15202 int oldHeight = mBottom - mTop; 15203 int newWidth = right - left; 15204 int newHeight = bottom - top; 15205 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 15206 15207 // Invalidate our old position 15208 invalidate(sizeChanged); 15209 15210 mLeft = left; 15211 mTop = top; 15212 mRight = right; 15213 mBottom = bottom; 15214 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 15215 15216 mPrivateFlags |= PFLAG_HAS_BOUNDS; 15217 15218 15219 if (sizeChanged) { 15220 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 15221 } 15222 15223 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { 15224 // If we are visible, force the DRAWN bit to on so that 15225 // this invalidate will go through (at least to our parent). 15226 // This is because someone may have invalidated this view 15227 // before this call to setFrame came in, thereby clearing 15228 // the DRAWN bit. 15229 mPrivateFlags |= PFLAG_DRAWN; 15230 invalidate(sizeChanged); 15231 // parent display list may need to be recreated based on a change in the bounds 15232 // of any child 15233 invalidateParentCaches(); 15234 } 15235 15236 // Reset drawn bit to original value (invalidate turns it off) 15237 mPrivateFlags |= drawn; 15238 15239 mBackgroundSizeChanged = true; 15240 15241 notifySubtreeAccessibilityStateChangedIfNeeded(); 15242 } 15243 return changed; 15244 } 15245 15246 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 15247 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 15248 if (mOverlay != null) { 15249 mOverlay.getOverlayView().setRight(newWidth); 15250 mOverlay.getOverlayView().setBottom(newHeight); 15251 } 15252 } 15253 15254 /** 15255 * Finalize inflating a view from XML. This is called as the last phase 15256 * of inflation, after all child views have been added. 15257 * 15258 * <p>Even if the subclass overrides onFinishInflate, they should always be 15259 * sure to call the super method, so that we get called. 15260 */ 15261 protected void onFinishInflate() { 15262 } 15263 15264 /** 15265 * Returns the resources associated with this view. 15266 * 15267 * @return Resources object. 15268 */ 15269 public Resources getResources() { 15270 return mResources; 15271 } 15272 15273 /** 15274 * Invalidates the specified Drawable. 15275 * 15276 * @param drawable the drawable to invalidate 15277 */ 15278 @Override 15279 public void invalidateDrawable(@NonNull Drawable drawable) { 15280 if (verifyDrawable(drawable)) { 15281 final Rect dirty = drawable.getDirtyBounds(); 15282 final int scrollX = mScrollX; 15283 final int scrollY = mScrollY; 15284 15285 invalidate(dirty.left + scrollX, dirty.top + scrollY, 15286 dirty.right + scrollX, dirty.bottom + scrollY); 15287 15288 if (drawable == mBackground) { 15289 queryOutlineFromBackgroundIfUndefined(); 15290 } 15291 } 15292 } 15293 15294 /** 15295 * Schedules an action on a drawable to occur at a specified time. 15296 * 15297 * @param who the recipient of the action 15298 * @param what the action to run on the drawable 15299 * @param when the time at which the action must occur. Uses the 15300 * {@link SystemClock#uptimeMillis} timebase. 15301 */ 15302 @Override 15303 public void scheduleDrawable(Drawable who, Runnable what, long when) { 15304 if (verifyDrawable(who) && what != null) { 15305 final long delay = when - SystemClock.uptimeMillis(); 15306 if (mAttachInfo != null) { 15307 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 15308 Choreographer.CALLBACK_ANIMATION, what, who, 15309 Choreographer.subtractFrameDelay(delay)); 15310 } else { 15311 ViewRootImpl.getRunQueue().postDelayed(what, delay); 15312 } 15313 } 15314 } 15315 15316 /** 15317 * Cancels a scheduled action on a drawable. 15318 * 15319 * @param who the recipient of the action 15320 * @param what the action to cancel 15321 */ 15322 @Override 15323 public void unscheduleDrawable(Drawable who, Runnable what) { 15324 if (verifyDrawable(who) && what != null) { 15325 if (mAttachInfo != null) { 15326 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 15327 Choreographer.CALLBACK_ANIMATION, what, who); 15328 } 15329 ViewRootImpl.getRunQueue().removeCallbacks(what); 15330 } 15331 } 15332 15333 /** 15334 * Unschedule any events associated with the given Drawable. This can be 15335 * used when selecting a new Drawable into a view, so that the previous 15336 * one is completely unscheduled. 15337 * 15338 * @param who The Drawable to unschedule. 15339 * 15340 * @see #drawableStateChanged 15341 */ 15342 public void unscheduleDrawable(Drawable who) { 15343 if (mAttachInfo != null && who != null) { 15344 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 15345 Choreographer.CALLBACK_ANIMATION, null, who); 15346 } 15347 } 15348 15349 /** 15350 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 15351 * that the View directionality can and will be resolved before its Drawables. 15352 * 15353 * Will call {@link View#onResolveDrawables} when resolution is done. 15354 * 15355 * @hide 15356 */ 15357 protected void resolveDrawables() { 15358 // Drawables resolution may need to happen before resolving the layout direction (which is 15359 // done only during the measure() call). 15360 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 15361 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 15362 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 15363 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 15364 // direction to be resolved as its resolved value will be the same as its raw value. 15365 if (!isLayoutDirectionResolved() && 15366 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 15367 return; 15368 } 15369 15370 final int layoutDirection = isLayoutDirectionResolved() ? 15371 getLayoutDirection() : getRawLayoutDirection(); 15372 15373 if (mBackground != null) { 15374 mBackground.setLayoutDirection(layoutDirection); 15375 } 15376 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 15377 onResolveDrawables(layoutDirection); 15378 } 15379 15380 /** 15381 * Called when layout direction has been resolved. 15382 * 15383 * The default implementation does nothing. 15384 * 15385 * @param layoutDirection The resolved layout direction. 15386 * 15387 * @see #LAYOUT_DIRECTION_LTR 15388 * @see #LAYOUT_DIRECTION_RTL 15389 * 15390 * @hide 15391 */ 15392 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 15393 } 15394 15395 /** 15396 * @hide 15397 */ 15398 protected void resetResolvedDrawables() { 15399 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 15400 } 15401 15402 private boolean isDrawablesResolved() { 15403 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 15404 } 15405 15406 /** 15407 * If your view subclass is displaying its own Drawable objects, it should 15408 * override this function and return true for any Drawable it is 15409 * displaying. This allows animations for those drawables to be 15410 * scheduled. 15411 * 15412 * <p>Be sure to call through to the super class when overriding this 15413 * function. 15414 * 15415 * @param who The Drawable to verify. Return true if it is one you are 15416 * displaying, else return the result of calling through to the 15417 * super class. 15418 * 15419 * @return boolean If true than the Drawable is being displayed in the 15420 * view; else false and it is not allowed to animate. 15421 * 15422 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 15423 * @see #drawableStateChanged() 15424 */ 15425 protected boolean verifyDrawable(Drawable who) { 15426 return who == mBackground; 15427 } 15428 15429 /** 15430 * This function is called whenever the state of the view changes in such 15431 * a way that it impacts the state of drawables being shown. 15432 * 15433 * <p>Be sure to call through to the superclass when overriding this 15434 * function. 15435 * 15436 * @see Drawable#setState(int[]) 15437 */ 15438 protected void drawableStateChanged() { 15439 final Drawable d = mBackground; 15440 if (d != null && d.isStateful()) { 15441 d.setState(getDrawableState()); 15442 } 15443 } 15444 15445 /** 15446 * Call this to force a view to update its drawable state. This will cause 15447 * drawableStateChanged to be called on this view. Views that are interested 15448 * in the new state should call getDrawableState. 15449 * 15450 * @see #drawableStateChanged 15451 * @see #getDrawableState 15452 */ 15453 public void refreshDrawableState() { 15454 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 15455 drawableStateChanged(); 15456 15457 ViewParent parent = mParent; 15458 if (parent != null) { 15459 parent.childDrawableStateChanged(this); 15460 } 15461 } 15462 15463 /** 15464 * Return an array of resource IDs of the drawable states representing the 15465 * current state of the view. 15466 * 15467 * @return The current drawable state 15468 * 15469 * @see Drawable#setState(int[]) 15470 * @see #drawableStateChanged() 15471 * @see #onCreateDrawableState(int) 15472 */ 15473 public final int[] getDrawableState() { 15474 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 15475 return mDrawableState; 15476 } else { 15477 mDrawableState = onCreateDrawableState(0); 15478 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 15479 return mDrawableState; 15480 } 15481 } 15482 15483 /** 15484 * Generate the new {@link android.graphics.drawable.Drawable} state for 15485 * this view. This is called by the view 15486 * system when the cached Drawable state is determined to be invalid. To 15487 * retrieve the current state, you should use {@link #getDrawableState}. 15488 * 15489 * @param extraSpace if non-zero, this is the number of extra entries you 15490 * would like in the returned array in which you can place your own 15491 * states. 15492 * 15493 * @return Returns an array holding the current {@link Drawable} state of 15494 * the view. 15495 * 15496 * @see #mergeDrawableStates(int[], int[]) 15497 */ 15498 protected int[] onCreateDrawableState(int extraSpace) { 15499 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 15500 mParent instanceof View) { 15501 return ((View) mParent).onCreateDrawableState(extraSpace); 15502 } 15503 15504 int[] drawableState; 15505 15506 int privateFlags = mPrivateFlags; 15507 15508 int viewStateIndex = 0; 15509 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED; 15510 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED; 15511 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED; 15512 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED; 15513 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED; 15514 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED; 15515 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 15516 HardwareRenderer.isAvailable()) { 15517 // This is set if HW acceleration is requested, even if the current 15518 // process doesn't allow it. This is just to allow app preview 15519 // windows to better match their app. 15520 viewStateIndex |= VIEW_STATE_ACCELERATED; 15521 } 15522 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED; 15523 15524 final int privateFlags2 = mPrivateFlags2; 15525 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT; 15526 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED; 15527 15528 drawableState = VIEW_STATE_SETS[viewStateIndex]; 15529 15530 //noinspection ConstantIfStatement 15531 if (false) { 15532 Log.i("View", "drawableStateIndex=" + viewStateIndex); 15533 Log.i("View", toString() 15534 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 15535 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 15536 + " fo=" + hasFocus() 15537 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 15538 + " wf=" + hasWindowFocus() 15539 + ": " + Arrays.toString(drawableState)); 15540 } 15541 15542 if (extraSpace == 0) { 15543 return drawableState; 15544 } 15545 15546 final int[] fullState; 15547 if (drawableState != null) { 15548 fullState = new int[drawableState.length + extraSpace]; 15549 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 15550 } else { 15551 fullState = new int[extraSpace]; 15552 } 15553 15554 return fullState; 15555 } 15556 15557 /** 15558 * Merge your own state values in <var>additionalState</var> into the base 15559 * state values <var>baseState</var> that were returned by 15560 * {@link #onCreateDrawableState(int)}. 15561 * 15562 * @param baseState The base state values returned by 15563 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 15564 * own additional state values. 15565 * 15566 * @param additionalState The additional state values you would like 15567 * added to <var>baseState</var>; this array is not modified. 15568 * 15569 * @return As a convenience, the <var>baseState</var> array you originally 15570 * passed into the function is returned. 15571 * 15572 * @see #onCreateDrawableState(int) 15573 */ 15574 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 15575 final int N = baseState.length; 15576 int i = N - 1; 15577 while (i >= 0 && baseState[i] == 0) { 15578 i--; 15579 } 15580 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 15581 return baseState; 15582 } 15583 15584 /** 15585 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 15586 * on all Drawable objects associated with this view. 15587 */ 15588 public void jumpDrawablesToCurrentState() { 15589 if (mBackground != null) { 15590 mBackground.jumpToCurrentState(); 15591 } 15592 } 15593 15594 /** 15595 * Sets the background color for this view. 15596 * @param color the color of the background 15597 */ 15598 @RemotableViewMethod 15599 public void setBackgroundColor(int color) { 15600 if (mBackground instanceof ColorDrawable) { 15601 ((ColorDrawable) mBackground.mutate()).setColor(color); 15602 computeOpaqueFlags(); 15603 mBackgroundResource = 0; 15604 } else { 15605 setBackground(new ColorDrawable(color)); 15606 } 15607 } 15608 15609 /** 15610 * Set the background to a given resource. The resource should refer to 15611 * a Drawable object or 0 to remove the background. 15612 * @param resid The identifier of the resource. 15613 * 15614 * @attr ref android.R.styleable#View_background 15615 */ 15616 @RemotableViewMethod 15617 public void setBackgroundResource(int resid) { 15618 if (resid != 0 && resid == mBackgroundResource) { 15619 return; 15620 } 15621 15622 Drawable d= null; 15623 if (resid != 0) { 15624 d = mContext.getDrawable(resid); 15625 } 15626 setBackground(d); 15627 15628 mBackgroundResource = resid; 15629 } 15630 15631 /** 15632 * Set the background to a given Drawable, or remove the background. If the 15633 * background has padding, this View's padding is set to the background's 15634 * padding. However, when a background is removed, this View's padding isn't 15635 * touched. If setting the padding is desired, please use 15636 * {@link #setPadding(int, int, int, int)}. 15637 * 15638 * @param background The Drawable to use as the background, or null to remove the 15639 * background 15640 */ 15641 public void setBackground(Drawable background) { 15642 //noinspection deprecation 15643 setBackgroundDrawable(background); 15644 } 15645 15646 /** 15647 * @deprecated use {@link #setBackground(Drawable)} instead 15648 */ 15649 @Deprecated 15650 public void setBackgroundDrawable(Drawable background) { 15651 computeOpaqueFlags(); 15652 15653 if (background == mBackground) { 15654 return; 15655 } 15656 15657 boolean requestLayout = false; 15658 15659 mBackgroundResource = 0; 15660 15661 /* 15662 * Regardless of whether we're setting a new background or not, we want 15663 * to clear the previous drawable. 15664 */ 15665 if (mBackground != null) { 15666 mBackground.setCallback(null); 15667 unscheduleDrawable(mBackground); 15668 } 15669 15670 if (background != null) { 15671 Rect padding = sThreadLocal.get(); 15672 if (padding == null) { 15673 padding = new Rect(); 15674 sThreadLocal.set(padding); 15675 } 15676 resetResolvedDrawables(); 15677 background.setLayoutDirection(getLayoutDirection()); 15678 if (background.getPadding(padding)) { 15679 resetResolvedPadding(); 15680 switch (background.getLayoutDirection()) { 15681 case LAYOUT_DIRECTION_RTL: 15682 mUserPaddingLeftInitial = padding.right; 15683 mUserPaddingRightInitial = padding.left; 15684 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 15685 break; 15686 case LAYOUT_DIRECTION_LTR: 15687 default: 15688 mUserPaddingLeftInitial = padding.left; 15689 mUserPaddingRightInitial = padding.right; 15690 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 15691 } 15692 mLeftPaddingDefined = false; 15693 mRightPaddingDefined = false; 15694 } 15695 15696 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 15697 // if it has a different minimum size, we should layout again 15698 if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() || 15699 mBackground.getMinimumWidth() != background.getMinimumWidth()) { 15700 requestLayout = true; 15701 } 15702 15703 background.setCallback(this); 15704 if (background.isStateful()) { 15705 background.setState(getDrawableState()); 15706 } 15707 background.setVisible(getVisibility() == VISIBLE, false); 15708 mBackground = background; 15709 15710 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 15711 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 15712 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND; 15713 requestLayout = true; 15714 } 15715 } else { 15716 /* Remove the background */ 15717 mBackground = null; 15718 15719 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) { 15720 /* 15721 * This view ONLY drew the background before and we're removing 15722 * the background, so now it won't draw anything 15723 * (hence we SKIP_DRAW) 15724 */ 15725 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND; 15726 mPrivateFlags |= PFLAG_SKIP_DRAW; 15727 } 15728 15729 /* 15730 * When the background is set, we try to apply its padding to this 15731 * View. When the background is removed, we don't touch this View's 15732 * padding. This is noted in the Javadocs. Hence, we don't need to 15733 * requestLayout(), the invalidate() below is sufficient. 15734 */ 15735 15736 // The old background's minimum size could have affected this 15737 // View's layout, so let's requestLayout 15738 requestLayout = true; 15739 } 15740 15741 computeOpaqueFlags(); 15742 15743 if (requestLayout) { 15744 requestLayout(); 15745 } 15746 15747 mBackgroundSizeChanged = true; 15748 invalidate(true); 15749 } 15750 15751 /** 15752 * Gets the background drawable 15753 * 15754 * @return The drawable used as the background for this view, if any. 15755 * 15756 * @see #setBackground(Drawable) 15757 * 15758 * @attr ref android.R.styleable#View_background 15759 */ 15760 public Drawable getBackground() { 15761 return mBackground; 15762 } 15763 15764 /** 15765 * Sets the padding. The view may add on the space required to display 15766 * the scrollbars, depending on the style and visibility of the scrollbars. 15767 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 15768 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 15769 * from the values set in this call. 15770 * 15771 * @attr ref android.R.styleable#View_padding 15772 * @attr ref android.R.styleable#View_paddingBottom 15773 * @attr ref android.R.styleable#View_paddingLeft 15774 * @attr ref android.R.styleable#View_paddingRight 15775 * @attr ref android.R.styleable#View_paddingTop 15776 * @param left the left padding in pixels 15777 * @param top the top padding in pixels 15778 * @param right the right padding in pixels 15779 * @param bottom the bottom padding in pixels 15780 */ 15781 public void setPadding(int left, int top, int right, int bottom) { 15782 resetResolvedPadding(); 15783 15784 mUserPaddingStart = UNDEFINED_PADDING; 15785 mUserPaddingEnd = UNDEFINED_PADDING; 15786 15787 mUserPaddingLeftInitial = left; 15788 mUserPaddingRightInitial = right; 15789 15790 mLeftPaddingDefined = true; 15791 mRightPaddingDefined = true; 15792 15793 internalSetPadding(left, top, right, bottom); 15794 } 15795 15796 /** 15797 * @hide 15798 */ 15799 protected void internalSetPadding(int left, int top, int right, int bottom) { 15800 mUserPaddingLeft = left; 15801 mUserPaddingRight = right; 15802 mUserPaddingBottom = bottom; 15803 15804 final int viewFlags = mViewFlags; 15805 boolean changed = false; 15806 15807 // Common case is there are no scroll bars. 15808 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 15809 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 15810 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 15811 ? 0 : getVerticalScrollbarWidth(); 15812 switch (mVerticalScrollbarPosition) { 15813 case SCROLLBAR_POSITION_DEFAULT: 15814 if (isLayoutRtl()) { 15815 left += offset; 15816 } else { 15817 right += offset; 15818 } 15819 break; 15820 case SCROLLBAR_POSITION_RIGHT: 15821 right += offset; 15822 break; 15823 case SCROLLBAR_POSITION_LEFT: 15824 left += offset; 15825 break; 15826 } 15827 } 15828 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 15829 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 15830 ? 0 : getHorizontalScrollbarHeight(); 15831 } 15832 } 15833 15834 if (mPaddingLeft != left) { 15835 changed = true; 15836 mPaddingLeft = left; 15837 } 15838 if (mPaddingTop != top) { 15839 changed = true; 15840 mPaddingTop = top; 15841 } 15842 if (mPaddingRight != right) { 15843 changed = true; 15844 mPaddingRight = right; 15845 } 15846 if (mPaddingBottom != bottom) { 15847 changed = true; 15848 mPaddingBottom = bottom; 15849 } 15850 15851 if (changed) { 15852 requestLayout(); 15853 } 15854 } 15855 15856 /** 15857 * Sets the relative padding. The view may add on the space required to display 15858 * the scrollbars, depending on the style and visibility of the scrollbars. 15859 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 15860 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 15861 * from the values set in this call. 15862 * 15863 * @attr ref android.R.styleable#View_padding 15864 * @attr ref android.R.styleable#View_paddingBottom 15865 * @attr ref android.R.styleable#View_paddingStart 15866 * @attr ref android.R.styleable#View_paddingEnd 15867 * @attr ref android.R.styleable#View_paddingTop 15868 * @param start the start padding in pixels 15869 * @param top the top padding in pixels 15870 * @param end the end padding in pixels 15871 * @param bottom the bottom padding in pixels 15872 */ 15873 public void setPaddingRelative(int start, int top, int end, int bottom) { 15874 resetResolvedPadding(); 15875 15876 mUserPaddingStart = start; 15877 mUserPaddingEnd = end; 15878 mLeftPaddingDefined = true; 15879 mRightPaddingDefined = true; 15880 15881 switch(getLayoutDirection()) { 15882 case LAYOUT_DIRECTION_RTL: 15883 mUserPaddingLeftInitial = end; 15884 mUserPaddingRightInitial = start; 15885 internalSetPadding(end, top, start, bottom); 15886 break; 15887 case LAYOUT_DIRECTION_LTR: 15888 default: 15889 mUserPaddingLeftInitial = start; 15890 mUserPaddingRightInitial = end; 15891 internalSetPadding(start, top, end, bottom); 15892 } 15893 } 15894 15895 /** 15896 * Returns the top padding of this view. 15897 * 15898 * @return the top padding in pixels 15899 */ 15900 public int getPaddingTop() { 15901 return mPaddingTop; 15902 } 15903 15904 /** 15905 * Returns the bottom padding of this view. If there are inset and enabled 15906 * scrollbars, this value may include the space required to display the 15907 * scrollbars as well. 15908 * 15909 * @return the bottom padding in pixels 15910 */ 15911 public int getPaddingBottom() { 15912 return mPaddingBottom; 15913 } 15914 15915 /** 15916 * Returns the left padding of this view. If there are inset and enabled 15917 * scrollbars, this value may include the space required to display the 15918 * scrollbars as well. 15919 * 15920 * @return the left padding in pixels 15921 */ 15922 public int getPaddingLeft() { 15923 if (!isPaddingResolved()) { 15924 resolvePadding(); 15925 } 15926 return mPaddingLeft; 15927 } 15928 15929 /** 15930 * Returns the start padding of this view depending on its resolved layout direction. 15931 * If there are inset and enabled scrollbars, this value may include the space 15932 * required to display the scrollbars as well. 15933 * 15934 * @return the start padding in pixels 15935 */ 15936 public int getPaddingStart() { 15937 if (!isPaddingResolved()) { 15938 resolvePadding(); 15939 } 15940 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 15941 mPaddingRight : mPaddingLeft; 15942 } 15943 15944 /** 15945 * Returns the right padding of this view. If there are inset and enabled 15946 * scrollbars, this value may include the space required to display the 15947 * scrollbars as well. 15948 * 15949 * @return the right padding in pixels 15950 */ 15951 public int getPaddingRight() { 15952 if (!isPaddingResolved()) { 15953 resolvePadding(); 15954 } 15955 return mPaddingRight; 15956 } 15957 15958 /** 15959 * Returns the end padding of this view depending on its resolved layout direction. 15960 * If there are inset and enabled scrollbars, this value may include the space 15961 * required to display the scrollbars as well. 15962 * 15963 * @return the end padding in pixels 15964 */ 15965 public int getPaddingEnd() { 15966 if (!isPaddingResolved()) { 15967 resolvePadding(); 15968 } 15969 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 15970 mPaddingLeft : mPaddingRight; 15971 } 15972 15973 /** 15974 * Return if the padding as been set thru relative values 15975 * {@link #setPaddingRelative(int, int, int, int)} or thru 15976 * @attr ref android.R.styleable#View_paddingStart or 15977 * @attr ref android.R.styleable#View_paddingEnd 15978 * 15979 * @return true if the padding is relative or false if it is not. 15980 */ 15981 public boolean isPaddingRelative() { 15982 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 15983 } 15984 15985 Insets computeOpticalInsets() { 15986 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 15987 } 15988 15989 /** 15990 * @hide 15991 */ 15992 public void resetPaddingToInitialValues() { 15993 if (isRtlCompatibilityMode()) { 15994 mPaddingLeft = mUserPaddingLeftInitial; 15995 mPaddingRight = mUserPaddingRightInitial; 15996 return; 15997 } 15998 if (isLayoutRtl()) { 15999 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 16000 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 16001 } else { 16002 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 16003 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 16004 } 16005 } 16006 16007 /** 16008 * @hide 16009 */ 16010 public Insets getOpticalInsets() { 16011 if (mLayoutInsets == null) { 16012 mLayoutInsets = computeOpticalInsets(); 16013 } 16014 return mLayoutInsets; 16015 } 16016 16017 /** 16018 * Changes the selection state of this view. A view can be selected or not. 16019 * Note that selection is not the same as focus. Views are typically 16020 * selected in the context of an AdapterView like ListView or GridView; 16021 * the selected view is the view that is highlighted. 16022 * 16023 * @param selected true if the view must be selected, false otherwise 16024 */ 16025 public void setSelected(boolean selected) { 16026 //noinspection DoubleNegation 16027 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 16028 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 16029 if (!selected) resetPressedState(); 16030 invalidate(true); 16031 refreshDrawableState(); 16032 dispatchSetSelected(selected); 16033 notifyViewAccessibilityStateChangedIfNeeded( 16034 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 16035 } 16036 } 16037 16038 /** 16039 * Dispatch setSelected to all of this View's children. 16040 * 16041 * @see #setSelected(boolean) 16042 * 16043 * @param selected The new selected state 16044 */ 16045 protected void dispatchSetSelected(boolean selected) { 16046 } 16047 16048 /** 16049 * Indicates the selection state of this view. 16050 * 16051 * @return true if the view is selected, false otherwise 16052 */ 16053 @ViewDebug.ExportedProperty 16054 public boolean isSelected() { 16055 return (mPrivateFlags & PFLAG_SELECTED) != 0; 16056 } 16057 16058 /** 16059 * Changes the activated state of this view. A view can be activated or not. 16060 * Note that activation is not the same as selection. Selection is 16061 * a transient property, representing the view (hierarchy) the user is 16062 * currently interacting with. Activation is a longer-term state that the 16063 * user can move views in and out of. For example, in a list view with 16064 * single or multiple selection enabled, the views in the current selection 16065 * set are activated. (Um, yeah, we are deeply sorry about the terminology 16066 * here.) The activated state is propagated down to children of the view it 16067 * is set on. 16068 * 16069 * @param activated true if the view must be activated, false otherwise 16070 */ 16071 public void setActivated(boolean activated) { 16072 //noinspection DoubleNegation 16073 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 16074 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 16075 invalidate(true); 16076 refreshDrawableState(); 16077 dispatchSetActivated(activated); 16078 } 16079 } 16080 16081 /** 16082 * Dispatch setActivated to all of this View's children. 16083 * 16084 * @see #setActivated(boolean) 16085 * 16086 * @param activated The new activated state 16087 */ 16088 protected void dispatchSetActivated(boolean activated) { 16089 } 16090 16091 /** 16092 * Indicates the activation state of this view. 16093 * 16094 * @return true if the view is activated, false otherwise 16095 */ 16096 @ViewDebug.ExportedProperty 16097 public boolean isActivated() { 16098 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 16099 } 16100 16101 /** 16102 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 16103 * observer can be used to get notifications when global events, like 16104 * layout, happen. 16105 * 16106 * The returned ViewTreeObserver observer is not guaranteed to remain 16107 * valid for the lifetime of this View. If the caller of this method keeps 16108 * a long-lived reference to ViewTreeObserver, it should always check for 16109 * the return value of {@link ViewTreeObserver#isAlive()}. 16110 * 16111 * @return The ViewTreeObserver for this view's hierarchy. 16112 */ 16113 public ViewTreeObserver getViewTreeObserver() { 16114 if (mAttachInfo != null) { 16115 return mAttachInfo.mTreeObserver; 16116 } 16117 if (mFloatingTreeObserver == null) { 16118 mFloatingTreeObserver = new ViewTreeObserver(); 16119 } 16120 return mFloatingTreeObserver; 16121 } 16122 16123 /** 16124 * <p>Finds the topmost view in the current view hierarchy.</p> 16125 * 16126 * @return the topmost view containing this view 16127 */ 16128 public View getRootView() { 16129 if (mAttachInfo != null) { 16130 final View v = mAttachInfo.mRootView; 16131 if (v != null) { 16132 return v; 16133 } 16134 } 16135 16136 View parent = this; 16137 16138 while (parent.mParent != null && parent.mParent instanceof View) { 16139 parent = (View) parent.mParent; 16140 } 16141 16142 return parent; 16143 } 16144 16145 /** 16146 * Transforms a motion event from view-local coordinates to on-screen 16147 * coordinates. 16148 * 16149 * @param ev the view-local motion event 16150 * @return false if the transformation could not be applied 16151 * @hide 16152 */ 16153 public boolean toGlobalMotionEvent(MotionEvent ev) { 16154 final AttachInfo info = mAttachInfo; 16155 if (info == null) { 16156 return false; 16157 } 16158 16159 final Matrix m = info.mTmpMatrix; 16160 m.set(Matrix.IDENTITY_MATRIX); 16161 transformMatrixToGlobal(m); 16162 ev.transform(m); 16163 return true; 16164 } 16165 16166 /** 16167 * Transforms a motion event from on-screen coordinates to view-local 16168 * coordinates. 16169 * 16170 * @param ev the on-screen motion event 16171 * @return false if the transformation could not be applied 16172 * @hide 16173 */ 16174 public boolean toLocalMotionEvent(MotionEvent ev) { 16175 final AttachInfo info = mAttachInfo; 16176 if (info == null) { 16177 return false; 16178 } 16179 16180 final Matrix m = info.mTmpMatrix; 16181 m.set(Matrix.IDENTITY_MATRIX); 16182 transformMatrixToLocal(m); 16183 ev.transform(m); 16184 return true; 16185 } 16186 16187 /** 16188 * Modifies the input matrix such that it maps view-local coordinates to 16189 * on-screen coordinates. 16190 * 16191 * @param m input matrix to modify 16192 */ 16193 void transformMatrixToGlobal(Matrix m) { 16194 final ViewParent parent = mParent; 16195 if (parent instanceof View) { 16196 final View vp = (View) parent; 16197 vp.transformMatrixToGlobal(m); 16198 m.postTranslate(-vp.mScrollX, -vp.mScrollY); 16199 } else if (parent instanceof ViewRootImpl) { 16200 final ViewRootImpl vr = (ViewRootImpl) parent; 16201 vr.transformMatrixToGlobal(m); 16202 m.postTranslate(0, -vr.mCurScrollY); 16203 } 16204 16205 m.postTranslate(mLeft, mTop); 16206 16207 if (!hasIdentityMatrix()) { 16208 m.postConcat(getMatrix()); 16209 } 16210 } 16211 16212 /** 16213 * Modifies the input matrix such that it maps on-screen coordinates to 16214 * view-local coordinates. 16215 * 16216 * @param m input matrix to modify 16217 */ 16218 void transformMatrixToLocal(Matrix m) { 16219 final ViewParent parent = mParent; 16220 if (parent instanceof View) { 16221 final View vp = (View) parent; 16222 vp.transformMatrixToLocal(m); 16223 m.preTranslate(vp.mScrollX, vp.mScrollY); 16224 } else if (parent instanceof ViewRootImpl) { 16225 final ViewRootImpl vr = (ViewRootImpl) parent; 16226 vr.transformMatrixToLocal(m); 16227 m.preTranslate(0, vr.mCurScrollY); 16228 } 16229 16230 m.preTranslate(-mLeft, -mTop); 16231 16232 if (!hasIdentityMatrix()) { 16233 m.preConcat(getInverseMatrix()); 16234 } 16235 } 16236 16237 /** 16238 * <p>Computes the coordinates of this view on the screen. The argument 16239 * must be an array of two integers. After the method returns, the array 16240 * contains the x and y location in that order.</p> 16241 * 16242 * @param location an array of two integers in which to hold the coordinates 16243 */ 16244 public void getLocationOnScreen(int[] location) { 16245 getLocationInWindow(location); 16246 16247 final AttachInfo info = mAttachInfo; 16248 if (info != null) { 16249 location[0] += info.mWindowLeft; 16250 location[1] += info.mWindowTop; 16251 } 16252 } 16253 16254 /** 16255 * <p>Computes the coordinates of this view in its window. The argument 16256 * must be an array of two integers. After the method returns, the array 16257 * contains the x and y location in that order.</p> 16258 * 16259 * @param location an array of two integers in which to hold the coordinates 16260 */ 16261 public void getLocationInWindow(int[] location) { 16262 if (location == null || location.length < 2) { 16263 throw new IllegalArgumentException("location must be an array of two integers"); 16264 } 16265 16266 if (mAttachInfo == null) { 16267 // When the view is not attached to a window, this method does not make sense 16268 location[0] = location[1] = 0; 16269 return; 16270 } 16271 16272 float[] position = mAttachInfo.mTmpTransformLocation; 16273 position[0] = position[1] = 0.0f; 16274 16275 if (!hasIdentityMatrix()) { 16276 getMatrix().mapPoints(position); 16277 } 16278 16279 position[0] += mLeft; 16280 position[1] += mTop; 16281 16282 ViewParent viewParent = mParent; 16283 while (viewParent instanceof View) { 16284 final View view = (View) viewParent; 16285 16286 position[0] -= view.mScrollX; 16287 position[1] -= view.mScrollY; 16288 16289 if (!view.hasIdentityMatrix()) { 16290 view.getMatrix().mapPoints(position); 16291 } 16292 16293 position[0] += view.mLeft; 16294 position[1] += view.mTop; 16295 16296 viewParent = view.mParent; 16297 } 16298 16299 if (viewParent instanceof ViewRootImpl) { 16300 // *cough* 16301 final ViewRootImpl vr = (ViewRootImpl) viewParent; 16302 position[1] -= vr.mCurScrollY; 16303 } 16304 16305 location[0] = (int) (position[0] + 0.5f); 16306 location[1] = (int) (position[1] + 0.5f); 16307 } 16308 16309 /** 16310 * {@hide} 16311 * @param id the id of the view to be found 16312 * @return the view of the specified id, null if cannot be found 16313 */ 16314 protected View findViewTraversal(int id) { 16315 if (id == mID) { 16316 return this; 16317 } 16318 return null; 16319 } 16320 16321 /** 16322 * {@hide} 16323 * @param tag the tag of the view to be found 16324 * @return the view of specified tag, null if cannot be found 16325 */ 16326 protected View findViewWithTagTraversal(Object tag) { 16327 if (tag != null && tag.equals(mTag)) { 16328 return this; 16329 } 16330 return null; 16331 } 16332 16333 /** 16334 * {@hide} 16335 * @param predicate The predicate to evaluate. 16336 * @param childToSkip If not null, ignores this child during the recursive traversal. 16337 * @return The first view that matches the predicate or null. 16338 */ 16339 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 16340 if (predicate.apply(this)) { 16341 return this; 16342 } 16343 return null; 16344 } 16345 16346 /** 16347 * Look for a child view with the given id. If this view has the given 16348 * id, return this view. 16349 * 16350 * @param id The id to search for. 16351 * @return The view that has the given id in the hierarchy or null 16352 */ 16353 public final View findViewById(int id) { 16354 if (id < 0) { 16355 return null; 16356 } 16357 return findViewTraversal(id); 16358 } 16359 16360 /** 16361 * Finds a view by its unuque and stable accessibility id. 16362 * 16363 * @param accessibilityId The searched accessibility id. 16364 * @return The found view. 16365 */ 16366 final View findViewByAccessibilityId(int accessibilityId) { 16367 if (accessibilityId < 0) { 16368 return null; 16369 } 16370 return findViewByAccessibilityIdTraversal(accessibilityId); 16371 } 16372 16373 /** 16374 * Performs the traversal to find a view by its unuque and stable accessibility id. 16375 * 16376 * <strong>Note:</strong>This method does not stop at the root namespace 16377 * boundary since the user can touch the screen at an arbitrary location 16378 * potentially crossing the root namespace bounday which will send an 16379 * accessibility event to accessibility services and they should be able 16380 * to obtain the event source. Also accessibility ids are guaranteed to be 16381 * unique in the window. 16382 * 16383 * @param accessibilityId The accessibility id. 16384 * @return The found view. 16385 * 16386 * @hide 16387 */ 16388 public View findViewByAccessibilityIdTraversal(int accessibilityId) { 16389 if (getAccessibilityViewId() == accessibilityId) { 16390 return this; 16391 } 16392 return null; 16393 } 16394 16395 /** 16396 * Look for a child view with the given tag. If this view has the given 16397 * tag, return this view. 16398 * 16399 * @param tag The tag to search for, using "tag.equals(getTag())". 16400 * @return The View that has the given tag in the hierarchy or null 16401 */ 16402 public final View findViewWithTag(Object tag) { 16403 if (tag == null) { 16404 return null; 16405 } 16406 return findViewWithTagTraversal(tag); 16407 } 16408 16409 /** 16410 * {@hide} 16411 * Look for a child view that matches the specified predicate. 16412 * If this view matches the predicate, return this view. 16413 * 16414 * @param predicate The predicate to evaluate. 16415 * @return The first view that matches the predicate or null. 16416 */ 16417 public final View findViewByPredicate(Predicate<View> predicate) { 16418 return findViewByPredicateTraversal(predicate, null); 16419 } 16420 16421 /** 16422 * {@hide} 16423 * Look for a child view that matches the specified predicate, 16424 * starting with the specified view and its descendents and then 16425 * recusively searching the ancestors and siblings of that view 16426 * until this view is reached. 16427 * 16428 * This method is useful in cases where the predicate does not match 16429 * a single unique view (perhaps multiple views use the same id) 16430 * and we are trying to find the view that is "closest" in scope to the 16431 * starting view. 16432 * 16433 * @param start The view to start from. 16434 * @param predicate The predicate to evaluate. 16435 * @return The first view that matches the predicate or null. 16436 */ 16437 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 16438 View childToSkip = null; 16439 for (;;) { 16440 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 16441 if (view != null || start == this) { 16442 return view; 16443 } 16444 16445 ViewParent parent = start.getParent(); 16446 if (parent == null || !(parent instanceof View)) { 16447 return null; 16448 } 16449 16450 childToSkip = start; 16451 start = (View) parent; 16452 } 16453 } 16454 16455 /** 16456 * Sets the identifier for this view. The identifier does not have to be 16457 * unique in this view's hierarchy. The identifier should be a positive 16458 * number. 16459 * 16460 * @see #NO_ID 16461 * @see #getId() 16462 * @see #findViewById(int) 16463 * 16464 * @param id a number used to identify the view 16465 * 16466 * @attr ref android.R.styleable#View_id 16467 */ 16468 public void setId(int id) { 16469 mID = id; 16470 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 16471 mID = generateViewId(); 16472 } 16473 } 16474 16475 /** 16476 * {@hide} 16477 * 16478 * @param isRoot true if the view belongs to the root namespace, false 16479 * otherwise 16480 */ 16481 public void setIsRootNamespace(boolean isRoot) { 16482 if (isRoot) { 16483 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 16484 } else { 16485 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 16486 } 16487 } 16488 16489 /** 16490 * {@hide} 16491 * 16492 * @return true if the view belongs to the root namespace, false otherwise 16493 */ 16494 public boolean isRootNamespace() { 16495 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 16496 } 16497 16498 /** 16499 * Returns this view's identifier. 16500 * 16501 * @return a positive integer used to identify the view or {@link #NO_ID} 16502 * if the view has no ID 16503 * 16504 * @see #setId(int) 16505 * @see #findViewById(int) 16506 * @attr ref android.R.styleable#View_id 16507 */ 16508 @ViewDebug.CapturedViewProperty 16509 public int getId() { 16510 return mID; 16511 } 16512 16513 /** 16514 * Returns this view's tag. 16515 * 16516 * @return the Object stored in this view as a tag, or {@code null} if not 16517 * set 16518 * 16519 * @see #setTag(Object) 16520 * @see #getTag(int) 16521 */ 16522 @ViewDebug.ExportedProperty 16523 public Object getTag() { 16524 return mTag; 16525 } 16526 16527 /** 16528 * Sets the tag associated with this view. A tag can be used to mark 16529 * a view in its hierarchy and does not have to be unique within the 16530 * hierarchy. Tags can also be used to store data within a view without 16531 * resorting to another data structure. 16532 * 16533 * @param tag an Object to tag the view with 16534 * 16535 * @see #getTag() 16536 * @see #setTag(int, Object) 16537 */ 16538 public void setTag(final Object tag) { 16539 mTag = tag; 16540 } 16541 16542 /** 16543 * Returns the tag associated with this view and the specified key. 16544 * 16545 * @param key The key identifying the tag 16546 * 16547 * @return the Object stored in this view as a tag, or {@code null} if not 16548 * set 16549 * 16550 * @see #setTag(int, Object) 16551 * @see #getTag() 16552 */ 16553 public Object getTag(int key) { 16554 if (mKeyedTags != null) return mKeyedTags.get(key); 16555 return null; 16556 } 16557 16558 /** 16559 * Sets a tag associated with this view and a key. A tag can be used 16560 * to mark a view in its hierarchy and does not have to be unique within 16561 * the hierarchy. Tags can also be used to store data within a view 16562 * without resorting to another data structure. 16563 * 16564 * The specified key should be an id declared in the resources of the 16565 * application to ensure it is unique (see the <a 16566 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 16567 * Keys identified as belonging to 16568 * the Android framework or not associated with any package will cause 16569 * an {@link IllegalArgumentException} to be thrown. 16570 * 16571 * @param key The key identifying the tag 16572 * @param tag An Object to tag the view with 16573 * 16574 * @throws IllegalArgumentException If they specified key is not valid 16575 * 16576 * @see #setTag(Object) 16577 * @see #getTag(int) 16578 */ 16579 public void setTag(int key, final Object tag) { 16580 // If the package id is 0x00 or 0x01, it's either an undefined package 16581 // or a framework id 16582 if ((key >>> 24) < 2) { 16583 throw new IllegalArgumentException("The key must be an application-specific " 16584 + "resource id."); 16585 } 16586 16587 setKeyedTag(key, tag); 16588 } 16589 16590 /** 16591 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 16592 * framework id. 16593 * 16594 * @hide 16595 */ 16596 public void setTagInternal(int key, Object tag) { 16597 if ((key >>> 24) != 0x1) { 16598 throw new IllegalArgumentException("The key must be a framework-specific " 16599 + "resource id."); 16600 } 16601 16602 setKeyedTag(key, tag); 16603 } 16604 16605 private void setKeyedTag(int key, Object tag) { 16606 if (mKeyedTags == null) { 16607 mKeyedTags = new SparseArray<Object>(2); 16608 } 16609 16610 mKeyedTags.put(key, tag); 16611 } 16612 16613 /** 16614 * Prints information about this view in the log output, with the tag 16615 * {@link #VIEW_LOG_TAG}. 16616 * 16617 * @hide 16618 */ 16619 public void debug() { 16620 debug(0); 16621 } 16622 16623 /** 16624 * Prints information about this view in the log output, with the tag 16625 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 16626 * indentation defined by the <code>depth</code>. 16627 * 16628 * @param depth the indentation level 16629 * 16630 * @hide 16631 */ 16632 protected void debug(int depth) { 16633 String output = debugIndent(depth - 1); 16634 16635 output += "+ " + this; 16636 int id = getId(); 16637 if (id != -1) { 16638 output += " (id=" + id + ")"; 16639 } 16640 Object tag = getTag(); 16641 if (tag != null) { 16642 output += " (tag=" + tag + ")"; 16643 } 16644 Log.d(VIEW_LOG_TAG, output); 16645 16646 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 16647 output = debugIndent(depth) + " FOCUSED"; 16648 Log.d(VIEW_LOG_TAG, output); 16649 } 16650 16651 output = debugIndent(depth); 16652 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 16653 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 16654 + "} "; 16655 Log.d(VIEW_LOG_TAG, output); 16656 16657 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 16658 || mPaddingBottom != 0) { 16659 output = debugIndent(depth); 16660 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 16661 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 16662 Log.d(VIEW_LOG_TAG, output); 16663 } 16664 16665 output = debugIndent(depth); 16666 output += "mMeasureWidth=" + mMeasuredWidth + 16667 " mMeasureHeight=" + mMeasuredHeight; 16668 Log.d(VIEW_LOG_TAG, output); 16669 16670 output = debugIndent(depth); 16671 if (mLayoutParams == null) { 16672 output += "BAD! no layout params"; 16673 } else { 16674 output = mLayoutParams.debug(output); 16675 } 16676 Log.d(VIEW_LOG_TAG, output); 16677 16678 output = debugIndent(depth); 16679 output += "flags={"; 16680 output += View.printFlags(mViewFlags); 16681 output += "}"; 16682 Log.d(VIEW_LOG_TAG, output); 16683 16684 output = debugIndent(depth); 16685 output += "privateFlags={"; 16686 output += View.printPrivateFlags(mPrivateFlags); 16687 output += "}"; 16688 Log.d(VIEW_LOG_TAG, output); 16689 } 16690 16691 /** 16692 * Creates a string of whitespaces used for indentation. 16693 * 16694 * @param depth the indentation level 16695 * @return a String containing (depth * 2 + 3) * 2 white spaces 16696 * 16697 * @hide 16698 */ 16699 protected static String debugIndent(int depth) { 16700 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 16701 for (int i = 0; i < (depth * 2) + 3; i++) { 16702 spaces.append(' ').append(' '); 16703 } 16704 return spaces.toString(); 16705 } 16706 16707 /** 16708 * <p>Return the offset of the widget's text baseline from the widget's top 16709 * boundary. If this widget does not support baseline alignment, this 16710 * method returns -1. </p> 16711 * 16712 * @return the offset of the baseline within the widget's bounds or -1 16713 * if baseline alignment is not supported 16714 */ 16715 @ViewDebug.ExportedProperty(category = "layout") 16716 public int getBaseline() { 16717 return -1; 16718 } 16719 16720 /** 16721 * Returns whether the view hierarchy is currently undergoing a layout pass. This 16722 * information is useful to avoid situations such as calling {@link #requestLayout()} during 16723 * a layout pass. 16724 * 16725 * @return whether the view hierarchy is currently undergoing a layout pass 16726 */ 16727 public boolean isInLayout() { 16728 ViewRootImpl viewRoot = getViewRootImpl(); 16729 return (viewRoot != null && viewRoot.isInLayout()); 16730 } 16731 16732 /** 16733 * Call this when something has changed which has invalidated the 16734 * layout of this view. This will schedule a layout pass of the view 16735 * tree. This should not be called while the view hierarchy is currently in a layout 16736 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 16737 * end of the current layout pass (and then layout will run again) or after the current 16738 * frame is drawn and the next layout occurs. 16739 * 16740 * <p>Subclasses which override this method should call the superclass method to 16741 * handle possible request-during-layout errors correctly.</p> 16742 */ 16743 public void requestLayout() { 16744 if (mMeasureCache != null) mMeasureCache.clear(); 16745 16746 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 16747 // Only trigger request-during-layout logic if this is the view requesting it, 16748 // not the views in its parent hierarchy 16749 ViewRootImpl viewRoot = getViewRootImpl(); 16750 if (viewRoot != null && viewRoot.isInLayout()) { 16751 if (!viewRoot.requestLayoutDuringLayout(this)) { 16752 return; 16753 } 16754 } 16755 mAttachInfo.mViewRequestingLayout = this; 16756 } 16757 16758 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 16759 mPrivateFlags |= PFLAG_INVALIDATED; 16760 16761 if (mParent != null && !mParent.isLayoutRequested()) { 16762 mParent.requestLayout(); 16763 } 16764 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 16765 mAttachInfo.mViewRequestingLayout = null; 16766 } 16767 } 16768 16769 /** 16770 * Forces this view to be laid out during the next layout pass. 16771 * This method does not call requestLayout() or forceLayout() 16772 * on the parent. 16773 */ 16774 public void forceLayout() { 16775 if (mMeasureCache != null) mMeasureCache.clear(); 16776 16777 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 16778 mPrivateFlags |= PFLAG_INVALIDATED; 16779 } 16780 16781 /** 16782 * <p> 16783 * This is called to find out how big a view should be. The parent 16784 * supplies constraint information in the width and height parameters. 16785 * </p> 16786 * 16787 * <p> 16788 * The actual measurement work of a view is performed in 16789 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 16790 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 16791 * </p> 16792 * 16793 * 16794 * @param widthMeasureSpec Horizontal space requirements as imposed by the 16795 * parent 16796 * @param heightMeasureSpec Vertical space requirements as imposed by the 16797 * parent 16798 * 16799 * @see #onMeasure(int, int) 16800 */ 16801 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 16802 boolean optical = isLayoutModeOptical(this); 16803 if (optical != isLayoutModeOptical(mParent)) { 16804 Insets insets = getOpticalInsets(); 16805 int oWidth = insets.left + insets.right; 16806 int oHeight = insets.top + insets.bottom; 16807 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 16808 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 16809 } 16810 16811 // Suppress sign extension for the low bytes 16812 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 16813 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 16814 16815 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || 16816 widthMeasureSpec != mOldWidthMeasureSpec || 16817 heightMeasureSpec != mOldHeightMeasureSpec) { 16818 16819 // first clears the measured dimension flag 16820 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 16821 16822 resolveRtlPropertiesIfNeeded(); 16823 16824 int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : 16825 mMeasureCache.indexOfKey(key); 16826 if (cacheIndex < 0 || sIgnoreMeasureCache) { 16827 // measure ourselves, this should set the measured dimension flag back 16828 onMeasure(widthMeasureSpec, heightMeasureSpec); 16829 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 16830 } else { 16831 long value = mMeasureCache.valueAt(cacheIndex); 16832 // Casting a long to int drops the high 32 bits, no mask needed 16833 setMeasuredDimensionRaw((int) (value >> 32), (int) value); 16834 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 16835 } 16836 16837 // flag not set, setMeasuredDimension() was not invoked, we raise 16838 // an exception to warn the developer 16839 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 16840 throw new IllegalStateException("onMeasure() did not set the" 16841 + " measured dimension by calling" 16842 + " setMeasuredDimension()"); 16843 } 16844 16845 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 16846 } 16847 16848 mOldWidthMeasureSpec = widthMeasureSpec; 16849 mOldHeightMeasureSpec = heightMeasureSpec; 16850 16851 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 16852 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 16853 } 16854 16855 /** 16856 * <p> 16857 * Measure the view and its content to determine the measured width and the 16858 * measured height. This method is invoked by {@link #measure(int, int)} and 16859 * should be overriden by subclasses to provide accurate and efficient 16860 * measurement of their contents. 16861 * </p> 16862 * 16863 * <p> 16864 * <strong>CONTRACT:</strong> When overriding this method, you 16865 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 16866 * measured width and height of this view. Failure to do so will trigger an 16867 * <code>IllegalStateException</code>, thrown by 16868 * {@link #measure(int, int)}. Calling the superclass' 16869 * {@link #onMeasure(int, int)} is a valid use. 16870 * </p> 16871 * 16872 * <p> 16873 * The base class implementation of measure defaults to the background size, 16874 * unless a larger size is allowed by the MeasureSpec. Subclasses should 16875 * override {@link #onMeasure(int, int)} to provide better measurements of 16876 * their content. 16877 * </p> 16878 * 16879 * <p> 16880 * If this method is overridden, it is the subclass's responsibility to make 16881 * sure the measured height and width are at least the view's minimum height 16882 * and width ({@link #getSuggestedMinimumHeight()} and 16883 * {@link #getSuggestedMinimumWidth()}). 16884 * </p> 16885 * 16886 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 16887 * The requirements are encoded with 16888 * {@link android.view.View.MeasureSpec}. 16889 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 16890 * The requirements are encoded with 16891 * {@link android.view.View.MeasureSpec}. 16892 * 16893 * @see #getMeasuredWidth() 16894 * @see #getMeasuredHeight() 16895 * @see #setMeasuredDimension(int, int) 16896 * @see #getSuggestedMinimumHeight() 16897 * @see #getSuggestedMinimumWidth() 16898 * @see android.view.View.MeasureSpec#getMode(int) 16899 * @see android.view.View.MeasureSpec#getSize(int) 16900 */ 16901 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 16902 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 16903 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 16904 } 16905 16906 /** 16907 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 16908 * measured width and measured height. Failing to do so will trigger an 16909 * exception at measurement time.</p> 16910 * 16911 * @param measuredWidth The measured width of this view. May be a complex 16912 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16913 * {@link #MEASURED_STATE_TOO_SMALL}. 16914 * @param measuredHeight The measured height of this view. May be a complex 16915 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16916 * {@link #MEASURED_STATE_TOO_SMALL}. 16917 */ 16918 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 16919 boolean optical = isLayoutModeOptical(this); 16920 if (optical != isLayoutModeOptical(mParent)) { 16921 Insets insets = getOpticalInsets(); 16922 int opticalWidth = insets.left + insets.right; 16923 int opticalHeight = insets.top + insets.bottom; 16924 16925 measuredWidth += optical ? opticalWidth : -opticalWidth; 16926 measuredHeight += optical ? opticalHeight : -opticalHeight; 16927 } 16928 setMeasuredDimensionRaw(measuredWidth, measuredHeight); 16929 } 16930 16931 /** 16932 * Sets the measured dimension without extra processing for things like optical bounds. 16933 * Useful for reapplying consistent values that have already been cooked with adjustments 16934 * for optical bounds, etc. such as those from the measurement cache. 16935 * 16936 * @param measuredWidth The measured width of this view. May be a complex 16937 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16938 * {@link #MEASURED_STATE_TOO_SMALL}. 16939 * @param measuredHeight The measured height of this view. May be a complex 16940 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 16941 * {@link #MEASURED_STATE_TOO_SMALL}. 16942 */ 16943 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { 16944 mMeasuredWidth = measuredWidth; 16945 mMeasuredHeight = measuredHeight; 16946 16947 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 16948 } 16949 16950 /** 16951 * Merge two states as returned by {@link #getMeasuredState()}. 16952 * @param curState The current state as returned from a view or the result 16953 * of combining multiple views. 16954 * @param newState The new view state to combine. 16955 * @return Returns a new integer reflecting the combination of the two 16956 * states. 16957 */ 16958 public static int combineMeasuredStates(int curState, int newState) { 16959 return curState | newState; 16960 } 16961 16962 /** 16963 * Version of {@link #resolveSizeAndState(int, int, int)} 16964 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 16965 */ 16966 public static int resolveSize(int size, int measureSpec) { 16967 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 16968 } 16969 16970 /** 16971 * Utility to reconcile a desired size and state, with constraints imposed 16972 * by a MeasureSpec. Will take the desired size, unless a different size 16973 * is imposed by the constraints. The returned value is a compound integer, 16974 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 16975 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting 16976 * size is smaller than the size the view wants to be. 16977 * 16978 * @param size How big the view wants to be 16979 * @param measureSpec Constraints imposed by the parent 16980 * @return Size information bit mask as defined by 16981 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 16982 */ 16983 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 16984 int result = size; 16985 int specMode = MeasureSpec.getMode(measureSpec); 16986 int specSize = MeasureSpec.getSize(measureSpec); 16987 switch (specMode) { 16988 case MeasureSpec.UNSPECIFIED: 16989 result = size; 16990 break; 16991 case MeasureSpec.AT_MOST: 16992 if (specSize < size) { 16993 result = specSize | MEASURED_STATE_TOO_SMALL; 16994 } else { 16995 result = size; 16996 } 16997 break; 16998 case MeasureSpec.EXACTLY: 16999 result = specSize; 17000 break; 17001 } 17002 return result | (childMeasuredState&MEASURED_STATE_MASK); 17003 } 17004 17005 /** 17006 * Utility to return a default size. Uses the supplied size if the 17007 * MeasureSpec imposed no constraints. Will get larger if allowed 17008 * by the MeasureSpec. 17009 * 17010 * @param size Default size for this view 17011 * @param measureSpec Constraints imposed by the parent 17012 * @return The size this view should be. 17013 */ 17014 public static int getDefaultSize(int size, int measureSpec) { 17015 int result = size; 17016 int specMode = MeasureSpec.getMode(measureSpec); 17017 int specSize = MeasureSpec.getSize(measureSpec); 17018 17019 switch (specMode) { 17020 case MeasureSpec.UNSPECIFIED: 17021 result = size; 17022 break; 17023 case MeasureSpec.AT_MOST: 17024 case MeasureSpec.EXACTLY: 17025 result = specSize; 17026 break; 17027 } 17028 return result; 17029 } 17030 17031 /** 17032 * Returns the suggested minimum height that the view should use. This 17033 * returns the maximum of the view's minimum height 17034 * and the background's minimum height 17035 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 17036 * <p> 17037 * When being used in {@link #onMeasure(int, int)}, the caller should still 17038 * ensure the returned height is within the requirements of the parent. 17039 * 17040 * @return The suggested minimum height of the view. 17041 */ 17042 protected int getSuggestedMinimumHeight() { 17043 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 17044 17045 } 17046 17047 /** 17048 * Returns the suggested minimum width that the view should use. This 17049 * returns the maximum of the view's minimum width) 17050 * and the background's minimum width 17051 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 17052 * <p> 17053 * When being used in {@link #onMeasure(int, int)}, the caller should still 17054 * ensure the returned width is within the requirements of the parent. 17055 * 17056 * @return The suggested minimum width of the view. 17057 */ 17058 protected int getSuggestedMinimumWidth() { 17059 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 17060 } 17061 17062 /** 17063 * Returns the minimum height of the view. 17064 * 17065 * @return the minimum height the view will try to be. 17066 * 17067 * @see #setMinimumHeight(int) 17068 * 17069 * @attr ref android.R.styleable#View_minHeight 17070 */ 17071 public int getMinimumHeight() { 17072 return mMinHeight; 17073 } 17074 17075 /** 17076 * Sets the minimum height of the view. It is not guaranteed the view will 17077 * be able to achieve this minimum height (for example, if its parent layout 17078 * constrains it with less available height). 17079 * 17080 * @param minHeight The minimum height the view will try to be. 17081 * 17082 * @see #getMinimumHeight() 17083 * 17084 * @attr ref android.R.styleable#View_minHeight 17085 */ 17086 public void setMinimumHeight(int minHeight) { 17087 mMinHeight = minHeight; 17088 requestLayout(); 17089 } 17090 17091 /** 17092 * Returns the minimum width of the view. 17093 * 17094 * @return the minimum width the view will try to be. 17095 * 17096 * @see #setMinimumWidth(int) 17097 * 17098 * @attr ref android.R.styleable#View_minWidth 17099 */ 17100 public int getMinimumWidth() { 17101 return mMinWidth; 17102 } 17103 17104 /** 17105 * Sets the minimum width of the view. It is not guaranteed the view will 17106 * be able to achieve this minimum width (for example, if its parent layout 17107 * constrains it with less available width). 17108 * 17109 * @param minWidth The minimum width the view will try to be. 17110 * 17111 * @see #getMinimumWidth() 17112 * 17113 * @attr ref android.R.styleable#View_minWidth 17114 */ 17115 public void setMinimumWidth(int minWidth) { 17116 mMinWidth = minWidth; 17117 requestLayout(); 17118 17119 } 17120 17121 /** 17122 * Get the animation currently associated with this view. 17123 * 17124 * @return The animation that is currently playing or 17125 * scheduled to play for this view. 17126 */ 17127 public Animation getAnimation() { 17128 return mCurrentAnimation; 17129 } 17130 17131 /** 17132 * Start the specified animation now. 17133 * 17134 * @param animation the animation to start now 17135 */ 17136 public void startAnimation(Animation animation) { 17137 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 17138 setAnimation(animation); 17139 invalidateParentCaches(); 17140 invalidate(true); 17141 } 17142 17143 /** 17144 * Cancels any animations for this view. 17145 */ 17146 public void clearAnimation() { 17147 if (mCurrentAnimation != null) { 17148 mCurrentAnimation.detach(); 17149 } 17150 mCurrentAnimation = null; 17151 invalidateParentIfNeeded(); 17152 } 17153 17154 /** 17155 * Sets the next animation to play for this view. 17156 * If you want the animation to play immediately, use 17157 * {@link #startAnimation(android.view.animation.Animation)} instead. 17158 * This method provides allows fine-grained 17159 * control over the start time and invalidation, but you 17160 * must make sure that 1) the animation has a start time set, and 17161 * 2) the view's parent (which controls animations on its children) 17162 * will be invalidated when the animation is supposed to 17163 * start. 17164 * 17165 * @param animation The next animation, or null. 17166 */ 17167 public void setAnimation(Animation animation) { 17168 mCurrentAnimation = animation; 17169 17170 if (animation != null) { 17171 // If the screen is off assume the animation start time is now instead of 17172 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 17173 // would cause the animation to start when the screen turns back on 17174 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF 17175 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 17176 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 17177 } 17178 animation.reset(); 17179 } 17180 } 17181 17182 /** 17183 * Invoked by a parent ViewGroup to notify the start of the animation 17184 * currently associated with this view. If you override this method, 17185 * always call super.onAnimationStart(); 17186 * 17187 * @see #setAnimation(android.view.animation.Animation) 17188 * @see #getAnimation() 17189 */ 17190 protected void onAnimationStart() { 17191 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 17192 } 17193 17194 /** 17195 * Invoked by a parent ViewGroup to notify the end of the animation 17196 * currently associated with this view. If you override this method, 17197 * always call super.onAnimationEnd(); 17198 * 17199 * @see #setAnimation(android.view.animation.Animation) 17200 * @see #getAnimation() 17201 */ 17202 protected void onAnimationEnd() { 17203 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 17204 } 17205 17206 /** 17207 * Invoked if there is a Transform that involves alpha. Subclass that can 17208 * draw themselves with the specified alpha should return true, and then 17209 * respect that alpha when their onDraw() is called. If this returns false 17210 * then the view may be redirected to draw into an offscreen buffer to 17211 * fulfill the request, which will look fine, but may be slower than if the 17212 * subclass handles it internally. The default implementation returns false. 17213 * 17214 * @param alpha The alpha (0..255) to apply to the view's drawing 17215 * @return true if the view can draw with the specified alpha. 17216 */ 17217 protected boolean onSetAlpha(int alpha) { 17218 return false; 17219 } 17220 17221 /** 17222 * This is used by the RootView to perform an optimization when 17223 * the view hierarchy contains one or several SurfaceView. 17224 * SurfaceView is always considered transparent, but its children are not, 17225 * therefore all View objects remove themselves from the global transparent 17226 * region (passed as a parameter to this function). 17227 * 17228 * @param region The transparent region for this ViewAncestor (window). 17229 * 17230 * @return Returns true if the effective visibility of the view at this 17231 * point is opaque, regardless of the transparent region; returns false 17232 * if it is possible for underlying windows to be seen behind the view. 17233 * 17234 * {@hide} 17235 */ 17236 public boolean gatherTransparentRegion(Region region) { 17237 final AttachInfo attachInfo = mAttachInfo; 17238 if (region != null && attachInfo != null) { 17239 final int pflags = mPrivateFlags; 17240 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 17241 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 17242 // remove it from the transparent region. 17243 final int[] location = attachInfo.mTransparentLocation; 17244 getLocationInWindow(location); 17245 region.op(location[0], location[1], location[0] + mRight - mLeft, 17246 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 17247 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) { 17248 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable 17249 // exists, so we remove the background drawable's non-transparent 17250 // parts from this transparent region. 17251 applyDrawableToTransparentRegion(mBackground, region); 17252 } 17253 } 17254 return true; 17255 } 17256 17257 /** 17258 * Play a sound effect for this view. 17259 * 17260 * <p>The framework will play sound effects for some built in actions, such as 17261 * clicking, but you may wish to play these effects in your widget, 17262 * for instance, for internal navigation. 17263 * 17264 * <p>The sound effect will only be played if sound effects are enabled by the user, and 17265 * {@link #isSoundEffectsEnabled()} is true. 17266 * 17267 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 17268 */ 17269 public void playSoundEffect(int soundConstant) { 17270 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 17271 return; 17272 } 17273 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 17274 } 17275 17276 /** 17277 * BZZZTT!!1! 17278 * 17279 * <p>Provide haptic feedback to the user for this view. 17280 * 17281 * <p>The framework will provide haptic feedback for some built in actions, 17282 * such as long presses, but you may wish to provide feedback for your 17283 * own widget. 17284 * 17285 * <p>The feedback will only be performed if 17286 * {@link #isHapticFeedbackEnabled()} is true. 17287 * 17288 * @param feedbackConstant One of the constants defined in 17289 * {@link HapticFeedbackConstants} 17290 */ 17291 public boolean performHapticFeedback(int feedbackConstant) { 17292 return performHapticFeedback(feedbackConstant, 0); 17293 } 17294 17295 /** 17296 * BZZZTT!!1! 17297 * 17298 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 17299 * 17300 * @param feedbackConstant One of the constants defined in 17301 * {@link HapticFeedbackConstants} 17302 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 17303 */ 17304 public boolean performHapticFeedback(int feedbackConstant, int flags) { 17305 if (mAttachInfo == null) { 17306 return false; 17307 } 17308 //noinspection SimplifiableIfStatement 17309 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 17310 && !isHapticFeedbackEnabled()) { 17311 return false; 17312 } 17313 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 17314 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 17315 } 17316 17317 /** 17318 * Request that the visibility of the status bar or other screen/window 17319 * decorations be changed. 17320 * 17321 * <p>This method is used to put the over device UI into temporary modes 17322 * where the user's attention is focused more on the application content, 17323 * by dimming or hiding surrounding system affordances. This is typically 17324 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 17325 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 17326 * to be placed behind the action bar (and with these flags other system 17327 * affordances) so that smooth transitions between hiding and showing them 17328 * can be done. 17329 * 17330 * <p>Two representative examples of the use of system UI visibility is 17331 * implementing a content browsing application (like a magazine reader) 17332 * and a video playing application. 17333 * 17334 * <p>The first code shows a typical implementation of a View in a content 17335 * browsing application. In this implementation, the application goes 17336 * into a content-oriented mode by hiding the status bar and action bar, 17337 * and putting the navigation elements into lights out mode. The user can 17338 * then interact with content while in this mode. Such an application should 17339 * provide an easy way for the user to toggle out of the mode (such as to 17340 * check information in the status bar or access notifications). In the 17341 * implementation here, this is done simply by tapping on the content. 17342 * 17343 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 17344 * content} 17345 * 17346 * <p>This second code sample shows a typical implementation of a View 17347 * in a video playing application. In this situation, while the video is 17348 * playing the application would like to go into a complete full-screen mode, 17349 * to use as much of the display as possible for the video. When in this state 17350 * the user can not interact with the application; the system intercepts 17351 * touching on the screen to pop the UI out of full screen mode. See 17352 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 17353 * 17354 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 17355 * content} 17356 * 17357 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 17358 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 17359 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 17360 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 17361 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 17362 */ 17363 public void setSystemUiVisibility(int visibility) { 17364 if (visibility != mSystemUiVisibility) { 17365 mSystemUiVisibility = visibility; 17366 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 17367 mParent.recomputeViewAttributes(this); 17368 } 17369 } 17370 } 17371 17372 /** 17373 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 17374 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 17375 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 17376 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 17377 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 17378 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 17379 */ 17380 public int getSystemUiVisibility() { 17381 return mSystemUiVisibility; 17382 } 17383 17384 /** 17385 * Returns the current system UI visibility that is currently set for 17386 * the entire window. This is the combination of the 17387 * {@link #setSystemUiVisibility(int)} values supplied by all of the 17388 * views in the window. 17389 */ 17390 public int getWindowSystemUiVisibility() { 17391 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 17392 } 17393 17394 /** 17395 * Override to find out when the window's requested system UI visibility 17396 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 17397 * This is different from the callbacks received through 17398 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 17399 * in that this is only telling you about the local request of the window, 17400 * not the actual values applied by the system. 17401 */ 17402 public void onWindowSystemUiVisibilityChanged(int visible) { 17403 } 17404 17405 /** 17406 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 17407 * the view hierarchy. 17408 */ 17409 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 17410 onWindowSystemUiVisibilityChanged(visible); 17411 } 17412 17413 /** 17414 * Set a listener to receive callbacks when the visibility of the system bar changes. 17415 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 17416 */ 17417 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 17418 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 17419 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 17420 mParent.recomputeViewAttributes(this); 17421 } 17422 } 17423 17424 /** 17425 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 17426 * the view hierarchy. 17427 */ 17428 public void dispatchSystemUiVisibilityChanged(int visibility) { 17429 ListenerInfo li = mListenerInfo; 17430 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 17431 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 17432 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 17433 } 17434 } 17435 17436 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 17437 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 17438 if (val != mSystemUiVisibility) { 17439 setSystemUiVisibility(val); 17440 return true; 17441 } 17442 return false; 17443 } 17444 17445 /** @hide */ 17446 public void setDisabledSystemUiVisibility(int flags) { 17447 if (mAttachInfo != null) { 17448 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 17449 mAttachInfo.mDisabledSystemUiVisibility = flags; 17450 if (mParent != null) { 17451 mParent.recomputeViewAttributes(this); 17452 } 17453 } 17454 } 17455 } 17456 17457 /** 17458 * Creates an image that the system displays during the drag and drop 17459 * operation. This is called a "drag shadow". The default implementation 17460 * for a DragShadowBuilder based on a View returns an image that has exactly the same 17461 * appearance as the given View. The default also positions the center of the drag shadow 17462 * directly under the touch point. If no View is provided (the constructor with no parameters 17463 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 17464 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the 17465 * default is an invisible drag shadow. 17466 * <p> 17467 * You are not required to use the View you provide to the constructor as the basis of the 17468 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 17469 * anything you want as the drag shadow. 17470 * </p> 17471 * <p> 17472 * You pass a DragShadowBuilder object to the system when you start the drag. The system 17473 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 17474 * size and position of the drag shadow. It uses this data to construct a 17475 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 17476 * so that your application can draw the shadow image in the Canvas. 17477 * </p> 17478 * 17479 * <div class="special reference"> 17480 * <h3>Developer Guides</h3> 17481 * <p>For a guide to implementing drag and drop features, read the 17482 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 17483 * </div> 17484 */ 17485 public static class DragShadowBuilder { 17486 private final WeakReference<View> mView; 17487 17488 /** 17489 * Constructs a shadow image builder based on a View. By default, the resulting drag 17490 * shadow will have the same appearance and dimensions as the View, with the touch point 17491 * over the center of the View. 17492 * @param view A View. Any View in scope can be used. 17493 */ 17494 public DragShadowBuilder(View view) { 17495 mView = new WeakReference<View>(view); 17496 } 17497 17498 /** 17499 * Construct a shadow builder object with no associated View. This 17500 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 17501 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 17502 * to supply the drag shadow's dimensions and appearance without 17503 * reference to any View object. If they are not overridden, then the result is an 17504 * invisible drag shadow. 17505 */ 17506 public DragShadowBuilder() { 17507 mView = new WeakReference<View>(null); 17508 } 17509 17510 /** 17511 * Returns the View object that had been passed to the 17512 * {@link #View.DragShadowBuilder(View)} 17513 * constructor. If that View parameter was {@code null} or if the 17514 * {@link #View.DragShadowBuilder()} 17515 * constructor was used to instantiate the builder object, this method will return 17516 * null. 17517 * 17518 * @return The View object associate with this builder object. 17519 */ 17520 @SuppressWarnings({"JavadocReference"}) 17521 final public View getView() { 17522 return mView.get(); 17523 } 17524 17525 /** 17526 * Provides the metrics for the shadow image. These include the dimensions of 17527 * the shadow image, and the point within that shadow that should 17528 * be centered under the touch location while dragging. 17529 * <p> 17530 * The default implementation sets the dimensions of the shadow to be the 17531 * same as the dimensions of the View itself and centers the shadow under 17532 * the touch point. 17533 * </p> 17534 * 17535 * @param shadowSize A {@link android.graphics.Point} containing the width and height 17536 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 17537 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 17538 * image. 17539 * 17540 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the 17541 * shadow image that should be underneath the touch point during the drag and drop 17542 * operation. Your application must set {@link android.graphics.Point#x} to the 17543 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 17544 */ 17545 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 17546 final View view = mView.get(); 17547 if (view != null) { 17548 shadowSize.set(view.getWidth(), view.getHeight()); 17549 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 17550 } else { 17551 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 17552 } 17553 } 17554 17555 /** 17556 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 17557 * based on the dimensions it received from the 17558 * {@link #onProvideShadowMetrics(Point, Point)} callback. 17559 * 17560 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 17561 */ 17562 public void onDrawShadow(Canvas canvas) { 17563 final View view = mView.get(); 17564 if (view != null) { 17565 view.draw(canvas); 17566 } else { 17567 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 17568 } 17569 } 17570 } 17571 17572 /** 17573 * Starts a drag and drop operation. When your application calls this method, it passes a 17574 * {@link android.view.View.DragShadowBuilder} object to the system. The 17575 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 17576 * to get metrics for the drag shadow, and then calls the object's 17577 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 17578 * <p> 17579 * Once the system has the drag shadow, it begins the drag and drop operation by sending 17580 * drag events to all the View objects in your application that are currently visible. It does 17581 * this either by calling the View object's drag listener (an implementation of 17582 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 17583 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 17584 * Both are passed a {@link android.view.DragEvent} object that has a 17585 * {@link android.view.DragEvent#getAction()} value of 17586 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 17587 * </p> 17588 * <p> 17589 * Your application can invoke startDrag() on any attached View object. The View object does not 17590 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to 17591 * be related to the View the user selected for dragging. 17592 * </p> 17593 * @param data A {@link android.content.ClipData} object pointing to the data to be 17594 * transferred by the drag and drop operation. 17595 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 17596 * drag shadow. 17597 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 17598 * drop operation. This Object is put into every DragEvent object sent by the system during the 17599 * current drag. 17600 * <p> 17601 * myLocalState is a lightweight mechanism for the sending information from the dragged View 17602 * to the target Views. For example, it can contain flags that differentiate between a 17603 * a copy operation and a move operation. 17604 * </p> 17605 * @param flags Flags that control the drag and drop operation. No flags are currently defined, 17606 * so the parameter should be set to 0. 17607 * @return {@code true} if the method completes successfully, or 17608 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 17609 * do a drag, and so no drag operation is in progress. 17610 */ 17611 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 17612 Object myLocalState, int flags) { 17613 if (ViewDebug.DEBUG_DRAG) { 17614 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags); 17615 } 17616 boolean okay = false; 17617 17618 Point shadowSize = new Point(); 17619 Point shadowTouchPoint = new Point(); 17620 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 17621 17622 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 17623 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 17624 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 17625 } 17626 17627 if (ViewDebug.DEBUG_DRAG) { 17628 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 17629 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 17630 } 17631 Surface surface = new Surface(); 17632 try { 17633 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 17634 flags, shadowSize.x, shadowSize.y, surface); 17635 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token 17636 + " surface=" + surface); 17637 if (token != null) { 17638 Canvas canvas = surface.lockCanvas(null); 17639 try { 17640 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 17641 shadowBuilder.onDrawShadow(canvas); 17642 } finally { 17643 surface.unlockCanvasAndPost(canvas); 17644 } 17645 17646 final ViewRootImpl root = getViewRootImpl(); 17647 17648 // Cache the local state object for delivery with DragEvents 17649 root.setLocalDragState(myLocalState); 17650 17651 // repurpose 'shadowSize' for the last touch point 17652 root.getLastTouchPoint(shadowSize); 17653 17654 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token, 17655 shadowSize.x, shadowSize.y, 17656 shadowTouchPoint.x, shadowTouchPoint.y, data); 17657 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 17658 17659 // Off and running! Release our local surface instance; the drag 17660 // shadow surface is now managed by the system process. 17661 surface.release(); 17662 } 17663 } catch (Exception e) { 17664 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 17665 surface.destroy(); 17666 } 17667 17668 return okay; 17669 } 17670 17671 /** 17672 * Handles drag events sent by the system following a call to 17673 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}. 17674 *<p> 17675 * When the system calls this method, it passes a 17676 * {@link android.view.DragEvent} object. A call to 17677 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 17678 * in DragEvent. The method uses these to determine what is happening in the drag and drop 17679 * operation. 17680 * @param event The {@link android.view.DragEvent} sent by the system. 17681 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 17682 * in DragEvent, indicating the type of drag event represented by this object. 17683 * @return {@code true} if the method was successful, otherwise {@code false}. 17684 * <p> 17685 * The method should return {@code true} in response to an action type of 17686 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 17687 * operation. 17688 * </p> 17689 * <p> 17690 * The method should also return {@code true} in response to an action type of 17691 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 17692 * {@code false} if it didn't. 17693 * </p> 17694 */ 17695 public boolean onDragEvent(DragEvent event) { 17696 return false; 17697 } 17698 17699 /** 17700 * Detects if this View is enabled and has a drag event listener. 17701 * If both are true, then it calls the drag event listener with the 17702 * {@link android.view.DragEvent} it received. If the drag event listener returns 17703 * {@code true}, then dispatchDragEvent() returns {@code true}. 17704 * <p> 17705 * For all other cases, the method calls the 17706 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 17707 * method and returns its result. 17708 * </p> 17709 * <p> 17710 * This ensures that a drag event is always consumed, even if the View does not have a drag 17711 * event listener. However, if the View has a listener and the listener returns true, then 17712 * onDragEvent() is not called. 17713 * </p> 17714 */ 17715 public boolean dispatchDragEvent(DragEvent event) { 17716 ListenerInfo li = mListenerInfo; 17717 //noinspection SimplifiableIfStatement 17718 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 17719 && li.mOnDragListener.onDrag(this, event)) { 17720 return true; 17721 } 17722 return onDragEvent(event); 17723 } 17724 17725 boolean canAcceptDrag() { 17726 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 17727 } 17728 17729 /** 17730 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 17731 * it is ever exposed at all. 17732 * @hide 17733 */ 17734 public void onCloseSystemDialogs(String reason) { 17735 } 17736 17737 /** 17738 * Given a Drawable whose bounds have been set to draw into this view, 17739 * update a Region being computed for 17740 * {@link #gatherTransparentRegion(android.graphics.Region)} so 17741 * that any non-transparent parts of the Drawable are removed from the 17742 * given transparent region. 17743 * 17744 * @param dr The Drawable whose transparency is to be applied to the region. 17745 * @param region A Region holding the current transparency information, 17746 * where any parts of the region that are set are considered to be 17747 * transparent. On return, this region will be modified to have the 17748 * transparency information reduced by the corresponding parts of the 17749 * Drawable that are not transparent. 17750 * {@hide} 17751 */ 17752 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 17753 if (DBG) { 17754 Log.i("View", "Getting transparent region for: " + this); 17755 } 17756 final Region r = dr.getTransparentRegion(); 17757 final Rect db = dr.getBounds(); 17758 final AttachInfo attachInfo = mAttachInfo; 17759 if (r != null && attachInfo != null) { 17760 final int w = getRight()-getLeft(); 17761 final int h = getBottom()-getTop(); 17762 if (db.left > 0) { 17763 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 17764 r.op(0, 0, db.left, h, Region.Op.UNION); 17765 } 17766 if (db.right < w) { 17767 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 17768 r.op(db.right, 0, w, h, Region.Op.UNION); 17769 } 17770 if (db.top > 0) { 17771 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 17772 r.op(0, 0, w, db.top, Region.Op.UNION); 17773 } 17774 if (db.bottom < h) { 17775 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 17776 r.op(0, db.bottom, w, h, Region.Op.UNION); 17777 } 17778 final int[] location = attachInfo.mTransparentLocation; 17779 getLocationInWindow(location); 17780 r.translate(location[0], location[1]); 17781 region.op(r, Region.Op.INTERSECT); 17782 } else { 17783 region.op(db, Region.Op.DIFFERENCE); 17784 } 17785 } 17786 17787 private void checkForLongClick(int delayOffset) { 17788 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 17789 mHasPerformedLongPress = false; 17790 17791 if (mPendingCheckForLongPress == null) { 17792 mPendingCheckForLongPress = new CheckForLongPress(); 17793 } 17794 mPendingCheckForLongPress.rememberWindowAttachCount(); 17795 postDelayed(mPendingCheckForLongPress, 17796 ViewConfiguration.getLongPressTimeout() - delayOffset); 17797 } 17798 } 17799 17800 /** 17801 * Inflate a view from an XML resource. This convenience method wraps the {@link 17802 * LayoutInflater} class, which provides a full range of options for view inflation. 17803 * 17804 * @param context The Context object for your activity or application. 17805 * @param resource The resource ID to inflate 17806 * @param root A view group that will be the parent. Used to properly inflate the 17807 * layout_* parameters. 17808 * @see LayoutInflater 17809 */ 17810 public static View inflate(Context context, int resource, ViewGroup root) { 17811 LayoutInflater factory = LayoutInflater.from(context); 17812 return factory.inflate(resource, root); 17813 } 17814 17815 /** 17816 * Scroll the view with standard behavior for scrolling beyond the normal 17817 * content boundaries. Views that call this method should override 17818 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 17819 * results of an over-scroll operation. 17820 * 17821 * Views can use this method to handle any touch or fling-based scrolling. 17822 * 17823 * @param deltaX Change in X in pixels 17824 * @param deltaY Change in Y in pixels 17825 * @param scrollX Current X scroll value in pixels before applying deltaX 17826 * @param scrollY Current Y scroll value in pixels before applying deltaY 17827 * @param scrollRangeX Maximum content scroll range along the X axis 17828 * @param scrollRangeY Maximum content scroll range along the Y axis 17829 * @param maxOverScrollX Number of pixels to overscroll by in either direction 17830 * along the X axis. 17831 * @param maxOverScrollY Number of pixels to overscroll by in either direction 17832 * along the Y axis. 17833 * @param isTouchEvent true if this scroll operation is the result of a touch event. 17834 * @return true if scrolling was clamped to an over-scroll boundary along either 17835 * axis, false otherwise. 17836 */ 17837 @SuppressWarnings({"UnusedParameters"}) 17838 protected boolean overScrollBy(int deltaX, int deltaY, 17839 int scrollX, int scrollY, 17840 int scrollRangeX, int scrollRangeY, 17841 int maxOverScrollX, int maxOverScrollY, 17842 boolean isTouchEvent) { 17843 final int overScrollMode = mOverScrollMode; 17844 final boolean canScrollHorizontal = 17845 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 17846 final boolean canScrollVertical = 17847 computeVerticalScrollRange() > computeVerticalScrollExtent(); 17848 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 17849 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 17850 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 17851 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 17852 17853 int newScrollX = scrollX + deltaX; 17854 if (!overScrollHorizontal) { 17855 maxOverScrollX = 0; 17856 } 17857 17858 int newScrollY = scrollY + deltaY; 17859 if (!overScrollVertical) { 17860 maxOverScrollY = 0; 17861 } 17862 17863 // Clamp values if at the limits and record 17864 final int left = -maxOverScrollX; 17865 final int right = maxOverScrollX + scrollRangeX; 17866 final int top = -maxOverScrollY; 17867 final int bottom = maxOverScrollY + scrollRangeY; 17868 17869 boolean clampedX = false; 17870 if (newScrollX > right) { 17871 newScrollX = right; 17872 clampedX = true; 17873 } else if (newScrollX < left) { 17874 newScrollX = left; 17875 clampedX = true; 17876 } 17877 17878 boolean clampedY = false; 17879 if (newScrollY > bottom) { 17880 newScrollY = bottom; 17881 clampedY = true; 17882 } else if (newScrollY < top) { 17883 newScrollY = top; 17884 clampedY = true; 17885 } 17886 17887 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 17888 17889 return clampedX || clampedY; 17890 } 17891 17892 /** 17893 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 17894 * respond to the results of an over-scroll operation. 17895 * 17896 * @param scrollX New X scroll value in pixels 17897 * @param scrollY New Y scroll value in pixels 17898 * @param clampedX True if scrollX was clamped to an over-scroll boundary 17899 * @param clampedY True if scrollY was clamped to an over-scroll boundary 17900 */ 17901 protected void onOverScrolled(int scrollX, int scrollY, 17902 boolean clampedX, boolean clampedY) { 17903 // Intentionally empty. 17904 } 17905 17906 /** 17907 * Returns the over-scroll mode for this view. The result will be 17908 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 17909 * (allow over-scrolling only if the view content is larger than the container), 17910 * or {@link #OVER_SCROLL_NEVER}. 17911 * 17912 * @return This view's over-scroll mode. 17913 */ 17914 public int getOverScrollMode() { 17915 return mOverScrollMode; 17916 } 17917 17918 /** 17919 * Set the over-scroll mode for this view. Valid over-scroll modes are 17920 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 17921 * (allow over-scrolling only if the view content is larger than the container), 17922 * or {@link #OVER_SCROLL_NEVER}. 17923 * 17924 * Setting the over-scroll mode of a view will have an effect only if the 17925 * view is capable of scrolling. 17926 * 17927 * @param overScrollMode The new over-scroll mode for this view. 17928 */ 17929 public void setOverScrollMode(int overScrollMode) { 17930 if (overScrollMode != OVER_SCROLL_ALWAYS && 17931 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 17932 overScrollMode != OVER_SCROLL_NEVER) { 17933 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 17934 } 17935 mOverScrollMode = overScrollMode; 17936 } 17937 17938 /** 17939 * Enable or disable nested scrolling for this view. 17940 * 17941 * <p>If this property is set to true the view will be permitted to initiate nested 17942 * scrolling operations with a compatible parent view in the current hierarchy. If this 17943 * view does not implement nested scrolling this will have no effect.</p> 17944 * 17945 * @param enabled true to enable nested scrolling, false to disable 17946 * 17947 * @see #isNestedScrollingEnabled() 17948 */ 17949 public void setNestedScrollingEnabled(boolean enabled) { 17950 if (enabled) { 17951 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED; 17952 } else { 17953 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED; 17954 } 17955 } 17956 17957 /** 17958 * Returns true if nested scrolling is enabled for this view. 17959 * 17960 * <p>If nested scrolling is enabled and this View class implementation supports it, 17961 * this view will act as a nested scrolling child view when applicable, forwarding data 17962 * about the scroll operation in progress to a compatible and cooperating nested scrolling 17963 * parent.</p> 17964 * 17965 * @return true if nested scrolling is enabled 17966 * 17967 * @see #setNestedScrollingEnabled(boolean) 17968 */ 17969 public boolean isNestedScrollingEnabled() { 17970 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) == 17971 PFLAG3_NESTED_SCROLLING_ENABLED; 17972 } 17973 17974 /** 17975 * Begin a nestable scroll operation along the given axes. 17976 * 17977 * <p>A view starting a nested scroll promises to abide by the following contract:</p> 17978 * 17979 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case 17980 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}. 17981 * In the case of touch scrolling the nested scroll will be terminated automatically in 17982 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}. 17983 * In the event of programmatic scrolling the caller must explicitly call 17984 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p> 17985 * 17986 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found. 17987 * If it returns false the caller may ignore the rest of this contract until the next scroll. 17988 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p> 17989 * 17990 * <p>At each incremental step of the scroll the caller should invoke 17991 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} 17992 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling 17993 * parent at least partially consumed the scroll and the caller should adjust the amount it 17994 * scrolls by.</p> 17995 * 17996 * <p>After applying the remainder of the scroll delta the caller should invoke 17997 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing 17998 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat 17999 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}. 18000 * </p> 18001 * 18002 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or 18003 * {@link #SCROLL_AXIS_VERTICAL}. 18004 * @return true if a cooperative parent was found and nested scrolling has been enabled for 18005 * the current gesture. 18006 * 18007 * @see #stopNestedScroll() 18008 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 18009 * @see #dispatchNestedScroll(int, int, int, int, int[]) 18010 */ 18011 public boolean startNestedScroll(int axes) { 18012 if (hasNestedScrollingParent()) { 18013 // Already in progress 18014 return true; 18015 } 18016 if (isNestedScrollingEnabled()) { 18017 ViewParent p = getParent(); 18018 View child = this; 18019 while (p != null) { 18020 try { 18021 if (p.onStartNestedScroll(child, this, axes)) { 18022 mNestedScrollingParent = p; 18023 p.onNestedScrollAccepted(child, this, axes); 18024 return true; 18025 } 18026 } catch (AbstractMethodError e) { 18027 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " + 18028 "method onStartNestedScroll", e); 18029 // Allow the search upward to continue 18030 } 18031 if (p instanceof View) { 18032 child = (View) p; 18033 } 18034 p = p.getParent(); 18035 } 18036 } 18037 return false; 18038 } 18039 18040 /** 18041 * Stop a nested scroll in progress. 18042 * 18043 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p> 18044 * 18045 * @see #startNestedScroll(int) 18046 */ 18047 public void stopNestedScroll() { 18048 if (mNestedScrollingParent != null) { 18049 mNestedScrollingParent.onStopNestedScroll(this); 18050 mNestedScrollingParent = null; 18051 } 18052 } 18053 18054 /** 18055 * Returns true if this view has a nested scrolling parent. 18056 * 18057 * <p>The presence of a nested scrolling parent indicates that this view has initiated 18058 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p> 18059 * 18060 * @return whether this view has a nested scrolling parent 18061 */ 18062 public boolean hasNestedScrollingParent() { 18063 return mNestedScrollingParent != null; 18064 } 18065 18066 /** 18067 * Dispatch one step of a nested scroll in progress. 18068 * 18069 * <p>Implementations of views that support nested scrolling should call this to report 18070 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll 18071 * is not currently in progress or nested scrolling is not 18072 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p> 18073 * 18074 * <p>Compatible View implementations should also call 18075 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before 18076 * consuming a component of the scroll event themselves.</p> 18077 * 18078 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step 18079 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step 18080 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view 18081 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view 18082 * @param offsetInWindow Optional. If not null, on return this will contain the offset 18083 * in local view coordinates of this view from before this operation 18084 * to after it completes. View implementations may use this to adjust 18085 * expected input coordinate tracking. 18086 * @return true if the event was dispatched, false if it could not be dispatched. 18087 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 18088 */ 18089 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 18090 int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) { 18091 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 18092 int startX = 0; 18093 int startY = 0; 18094 if (offsetInWindow != null) { 18095 getLocationInWindow(offsetInWindow); 18096 startX = offsetInWindow[0]; 18097 startY = offsetInWindow[1]; 18098 } 18099 18100 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed, 18101 dxUnconsumed, dyUnconsumed); 18102 18103 if (offsetInWindow != null) { 18104 getLocationInWindow(offsetInWindow); 18105 offsetInWindow[0] -= startX; 18106 offsetInWindow[1] -= startY; 18107 } 18108 return true; 18109 } 18110 return false; 18111 } 18112 18113 /** 18114 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it. 18115 * 18116 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch. 18117 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested 18118 * scrolling operation to consume some or all of the scroll operation before the child view 18119 * consumes it.</p> 18120 * 18121 * @param dx Horizontal scroll distance in pixels 18122 * @param dy Vertical scroll distance in pixels 18123 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx 18124 * and consumed[1] the consumed dy. 18125 * @param offsetInWindow Optional. If not null, on return this will contain the offset 18126 * in local view coordinates of this view from before this operation 18127 * to after it completes. View implementations may use this to adjust 18128 * expected input coordinate tracking. 18129 * @return true if the parent consumed some or all of the scroll delta 18130 * @see #dispatchNestedScroll(int, int, int, int, int[]) 18131 */ 18132 public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { 18133 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 18134 int startX = 0; 18135 int startY = 0; 18136 if (offsetInWindow != null) { 18137 getLocationInWindow(offsetInWindow); 18138 startX = offsetInWindow[0]; 18139 startY = offsetInWindow[1]; 18140 } 18141 18142 if (consumed == null) { 18143 if (mTempNestedScrollConsumed == null) { 18144 mTempNestedScrollConsumed = new int[2]; 18145 } 18146 consumed = mTempNestedScrollConsumed; 18147 } 18148 consumed[0] = 0; 18149 consumed[1] = 0; 18150 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed); 18151 18152 if (offsetInWindow != null) { 18153 getLocationInWindow(offsetInWindow); 18154 offsetInWindow[0] -= startX; 18155 offsetInWindow[1] -= startY; 18156 } 18157 return consumed[0] != 0 || consumed[1] != 0; 18158 } 18159 return false; 18160 } 18161 18162 /** 18163 * Dispatch a fling to a nested scrolling parent. 18164 * 18165 * <p>If a nested scrolling child view would normally fling but it is at the edge of its 18166 * own content it should use this method to delegate the fling to its nested scrolling parent. 18167 * The view implementation can use a {@link VelocityTracker} to obtain the velocity values 18168 * to pass.</p> 18169 * 18170 * @param velocityX Horizontal fling velocity in pixels per second 18171 * @param velocityY Vertical fling velocity in pixels per second 18172 * @return true if the nested scrolling parent consumed the fling 18173 */ 18174 public boolean dispatchNestedFling(float velocityX, float velocityY) { 18175 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 18176 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY); 18177 } 18178 return false; 18179 } 18180 18181 /** 18182 * Gets a scale factor that determines the distance the view should scroll 18183 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 18184 * @return The vertical scroll scale factor. 18185 * @hide 18186 */ 18187 protected float getVerticalScrollFactor() { 18188 if (mVerticalScrollFactor == 0) { 18189 TypedValue outValue = new TypedValue(); 18190 if (!mContext.getTheme().resolveAttribute( 18191 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 18192 throw new IllegalStateException( 18193 "Expected theme to define listPreferredItemHeight."); 18194 } 18195 mVerticalScrollFactor = outValue.getDimension( 18196 mContext.getResources().getDisplayMetrics()); 18197 } 18198 return mVerticalScrollFactor; 18199 } 18200 18201 /** 18202 * Gets a scale factor that determines the distance the view should scroll 18203 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 18204 * @return The horizontal scroll scale factor. 18205 * @hide 18206 */ 18207 protected float getHorizontalScrollFactor() { 18208 // TODO: Should use something else. 18209 return getVerticalScrollFactor(); 18210 } 18211 18212 /** 18213 * Return the value specifying the text direction or policy that was set with 18214 * {@link #setTextDirection(int)}. 18215 * 18216 * @return the defined text direction. It can be one of: 18217 * 18218 * {@link #TEXT_DIRECTION_INHERIT}, 18219 * {@link #TEXT_DIRECTION_FIRST_STRONG} 18220 * {@link #TEXT_DIRECTION_ANY_RTL}, 18221 * {@link #TEXT_DIRECTION_LTR}, 18222 * {@link #TEXT_DIRECTION_RTL}, 18223 * {@link #TEXT_DIRECTION_LOCALE} 18224 * 18225 * @attr ref android.R.styleable#View_textDirection 18226 * 18227 * @hide 18228 */ 18229 @ViewDebug.ExportedProperty(category = "text", mapping = { 18230 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 18231 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 18232 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 18233 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 18234 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 18235 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE") 18236 }) 18237 public int getRawTextDirection() { 18238 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 18239 } 18240 18241 /** 18242 * Set the text direction. 18243 * 18244 * @param textDirection the direction to set. Should be one of: 18245 * 18246 * {@link #TEXT_DIRECTION_INHERIT}, 18247 * {@link #TEXT_DIRECTION_FIRST_STRONG} 18248 * {@link #TEXT_DIRECTION_ANY_RTL}, 18249 * {@link #TEXT_DIRECTION_LTR}, 18250 * {@link #TEXT_DIRECTION_RTL}, 18251 * {@link #TEXT_DIRECTION_LOCALE} 18252 * 18253 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 18254 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 18255 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 18256 * 18257 * @attr ref android.R.styleable#View_textDirection 18258 */ 18259 public void setTextDirection(int textDirection) { 18260 if (getRawTextDirection() != textDirection) { 18261 // Reset the current text direction and the resolved one 18262 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 18263 resetResolvedTextDirection(); 18264 // Set the new text direction 18265 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 18266 // Do resolution 18267 resolveTextDirection(); 18268 // Notify change 18269 onRtlPropertiesChanged(getLayoutDirection()); 18270 // Refresh 18271 requestLayout(); 18272 invalidate(true); 18273 } 18274 } 18275 18276 /** 18277 * Return the resolved text direction. 18278 * 18279 * @return the resolved text direction. Returns one of: 18280 * 18281 * {@link #TEXT_DIRECTION_FIRST_STRONG} 18282 * {@link #TEXT_DIRECTION_ANY_RTL}, 18283 * {@link #TEXT_DIRECTION_LTR}, 18284 * {@link #TEXT_DIRECTION_RTL}, 18285 * {@link #TEXT_DIRECTION_LOCALE} 18286 * 18287 * @attr ref android.R.styleable#View_textDirection 18288 */ 18289 @ViewDebug.ExportedProperty(category = "text", mapping = { 18290 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 18291 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 18292 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 18293 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 18294 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 18295 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE") 18296 }) 18297 public int getTextDirection() { 18298 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 18299 } 18300 18301 /** 18302 * Resolve the text direction. 18303 * 18304 * @return true if resolution has been done, false otherwise. 18305 * 18306 * @hide 18307 */ 18308 public boolean resolveTextDirection() { 18309 // Reset any previous text direction resolution 18310 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 18311 18312 if (hasRtlSupport()) { 18313 // Set resolved text direction flag depending on text direction flag 18314 final int textDirection = getRawTextDirection(); 18315 switch(textDirection) { 18316 case TEXT_DIRECTION_INHERIT: 18317 if (!canResolveTextDirection()) { 18318 // We cannot do the resolution if there is no parent, so use the default one 18319 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18320 // Resolution will need to happen again later 18321 return false; 18322 } 18323 18324 // Parent has not yet resolved, so we still return the default 18325 try { 18326 if (!mParent.isTextDirectionResolved()) { 18327 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18328 // Resolution will need to happen again later 18329 return false; 18330 } 18331 } catch (AbstractMethodError e) { 18332 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18333 " does not fully implement ViewParent", e); 18334 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 18335 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18336 return true; 18337 } 18338 18339 // Set current resolved direction to the same value as the parent's one 18340 int parentResolvedDirection; 18341 try { 18342 parentResolvedDirection = mParent.getTextDirection(); 18343 } catch (AbstractMethodError e) { 18344 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18345 " does not fully implement ViewParent", e); 18346 parentResolvedDirection = TEXT_DIRECTION_LTR; 18347 } 18348 switch (parentResolvedDirection) { 18349 case TEXT_DIRECTION_FIRST_STRONG: 18350 case TEXT_DIRECTION_ANY_RTL: 18351 case TEXT_DIRECTION_LTR: 18352 case TEXT_DIRECTION_RTL: 18353 case TEXT_DIRECTION_LOCALE: 18354 mPrivateFlags2 |= 18355 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 18356 break; 18357 default: 18358 // Default resolved direction is "first strong" heuristic 18359 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18360 } 18361 break; 18362 case TEXT_DIRECTION_FIRST_STRONG: 18363 case TEXT_DIRECTION_ANY_RTL: 18364 case TEXT_DIRECTION_LTR: 18365 case TEXT_DIRECTION_RTL: 18366 case TEXT_DIRECTION_LOCALE: 18367 // Resolved direction is the same as text direction 18368 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 18369 break; 18370 default: 18371 // Default resolved direction is "first strong" heuristic 18372 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18373 } 18374 } else { 18375 // Default resolved direction is "first strong" heuristic 18376 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18377 } 18378 18379 // Set to resolved 18380 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 18381 return true; 18382 } 18383 18384 /** 18385 * Check if text direction resolution can be done. 18386 * 18387 * @return true if text direction resolution can be done otherwise return false. 18388 */ 18389 public boolean canResolveTextDirection() { 18390 switch (getRawTextDirection()) { 18391 case TEXT_DIRECTION_INHERIT: 18392 if (mParent != null) { 18393 try { 18394 return mParent.canResolveTextDirection(); 18395 } catch (AbstractMethodError e) { 18396 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18397 " does not fully implement ViewParent", e); 18398 } 18399 } 18400 return false; 18401 18402 default: 18403 return true; 18404 } 18405 } 18406 18407 /** 18408 * Reset resolved text direction. Text direction will be resolved during a call to 18409 * {@link #onMeasure(int, int)}. 18410 * 18411 * @hide 18412 */ 18413 public void resetResolvedTextDirection() { 18414 // Reset any previous text direction resolution 18415 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 18416 // Set to default value 18417 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 18418 } 18419 18420 /** 18421 * @return true if text direction is inherited. 18422 * 18423 * @hide 18424 */ 18425 public boolean isTextDirectionInherited() { 18426 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 18427 } 18428 18429 /** 18430 * @return true if text direction is resolved. 18431 */ 18432 public boolean isTextDirectionResolved() { 18433 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 18434 } 18435 18436 /** 18437 * Return the value specifying the text alignment or policy that was set with 18438 * {@link #setTextAlignment(int)}. 18439 * 18440 * @return the defined text alignment. It can be one of: 18441 * 18442 * {@link #TEXT_ALIGNMENT_INHERIT}, 18443 * {@link #TEXT_ALIGNMENT_GRAVITY}, 18444 * {@link #TEXT_ALIGNMENT_CENTER}, 18445 * {@link #TEXT_ALIGNMENT_TEXT_START}, 18446 * {@link #TEXT_ALIGNMENT_TEXT_END}, 18447 * {@link #TEXT_ALIGNMENT_VIEW_START}, 18448 * {@link #TEXT_ALIGNMENT_VIEW_END} 18449 * 18450 * @attr ref android.R.styleable#View_textAlignment 18451 * 18452 * @hide 18453 */ 18454 @ViewDebug.ExportedProperty(category = "text", mapping = { 18455 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 18456 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 18457 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 18458 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 18459 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 18460 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 18461 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 18462 }) 18463 @TextAlignment 18464 public int getRawTextAlignment() { 18465 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 18466 } 18467 18468 /** 18469 * Set the text alignment. 18470 * 18471 * @param textAlignment The text alignment to set. Should be one of 18472 * 18473 * {@link #TEXT_ALIGNMENT_INHERIT}, 18474 * {@link #TEXT_ALIGNMENT_GRAVITY}, 18475 * {@link #TEXT_ALIGNMENT_CENTER}, 18476 * {@link #TEXT_ALIGNMENT_TEXT_START}, 18477 * {@link #TEXT_ALIGNMENT_TEXT_END}, 18478 * {@link #TEXT_ALIGNMENT_VIEW_START}, 18479 * {@link #TEXT_ALIGNMENT_VIEW_END} 18480 * 18481 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 18482 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 18483 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 18484 * 18485 * @attr ref android.R.styleable#View_textAlignment 18486 */ 18487 public void setTextAlignment(@TextAlignment int textAlignment) { 18488 if (textAlignment != getRawTextAlignment()) { 18489 // Reset the current and resolved text alignment 18490 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 18491 resetResolvedTextAlignment(); 18492 // Set the new text alignment 18493 mPrivateFlags2 |= 18494 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 18495 // Do resolution 18496 resolveTextAlignment(); 18497 // Notify change 18498 onRtlPropertiesChanged(getLayoutDirection()); 18499 // Refresh 18500 requestLayout(); 18501 invalidate(true); 18502 } 18503 } 18504 18505 /** 18506 * Return the resolved text alignment. 18507 * 18508 * @return the resolved text alignment. Returns one of: 18509 * 18510 * {@link #TEXT_ALIGNMENT_GRAVITY}, 18511 * {@link #TEXT_ALIGNMENT_CENTER}, 18512 * {@link #TEXT_ALIGNMENT_TEXT_START}, 18513 * {@link #TEXT_ALIGNMENT_TEXT_END}, 18514 * {@link #TEXT_ALIGNMENT_VIEW_START}, 18515 * {@link #TEXT_ALIGNMENT_VIEW_END} 18516 * 18517 * @attr ref android.R.styleable#View_textAlignment 18518 */ 18519 @ViewDebug.ExportedProperty(category = "text", mapping = { 18520 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 18521 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 18522 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 18523 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 18524 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 18525 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 18526 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 18527 }) 18528 @TextAlignment 18529 public int getTextAlignment() { 18530 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 18531 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 18532 } 18533 18534 /** 18535 * Resolve the text alignment. 18536 * 18537 * @return true if resolution has been done, false otherwise. 18538 * 18539 * @hide 18540 */ 18541 public boolean resolveTextAlignment() { 18542 // Reset any previous text alignment resolution 18543 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 18544 18545 if (hasRtlSupport()) { 18546 // Set resolved text alignment flag depending on text alignment flag 18547 final int textAlignment = getRawTextAlignment(); 18548 switch (textAlignment) { 18549 case TEXT_ALIGNMENT_INHERIT: 18550 // Check if we can resolve the text alignment 18551 if (!canResolveTextAlignment()) { 18552 // We cannot do the resolution if there is no parent so use the default 18553 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18554 // Resolution will need to happen again later 18555 return false; 18556 } 18557 18558 // Parent has not yet resolved, so we still return the default 18559 try { 18560 if (!mParent.isTextAlignmentResolved()) { 18561 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18562 // Resolution will need to happen again later 18563 return false; 18564 } 18565 } catch (AbstractMethodError e) { 18566 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18567 " does not fully implement ViewParent", e); 18568 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 18569 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18570 return true; 18571 } 18572 18573 int parentResolvedTextAlignment; 18574 try { 18575 parentResolvedTextAlignment = mParent.getTextAlignment(); 18576 } catch (AbstractMethodError e) { 18577 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18578 " does not fully implement ViewParent", e); 18579 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 18580 } 18581 switch (parentResolvedTextAlignment) { 18582 case TEXT_ALIGNMENT_GRAVITY: 18583 case TEXT_ALIGNMENT_TEXT_START: 18584 case TEXT_ALIGNMENT_TEXT_END: 18585 case TEXT_ALIGNMENT_CENTER: 18586 case TEXT_ALIGNMENT_VIEW_START: 18587 case TEXT_ALIGNMENT_VIEW_END: 18588 // Resolved text alignment is the same as the parent resolved 18589 // text alignment 18590 mPrivateFlags2 |= 18591 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 18592 break; 18593 default: 18594 // Use default resolved text alignment 18595 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18596 } 18597 break; 18598 case TEXT_ALIGNMENT_GRAVITY: 18599 case TEXT_ALIGNMENT_TEXT_START: 18600 case TEXT_ALIGNMENT_TEXT_END: 18601 case TEXT_ALIGNMENT_CENTER: 18602 case TEXT_ALIGNMENT_VIEW_START: 18603 case TEXT_ALIGNMENT_VIEW_END: 18604 // Resolved text alignment is the same as text alignment 18605 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 18606 break; 18607 default: 18608 // Use default resolved text alignment 18609 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18610 } 18611 } else { 18612 // Use default resolved text alignment 18613 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18614 } 18615 18616 // Set the resolved 18617 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 18618 return true; 18619 } 18620 18621 /** 18622 * Check if text alignment resolution can be done. 18623 * 18624 * @return true if text alignment resolution can be done otherwise return false. 18625 */ 18626 public boolean canResolveTextAlignment() { 18627 switch (getRawTextAlignment()) { 18628 case TEXT_DIRECTION_INHERIT: 18629 if (mParent != null) { 18630 try { 18631 return mParent.canResolveTextAlignment(); 18632 } catch (AbstractMethodError e) { 18633 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 18634 " does not fully implement ViewParent", e); 18635 } 18636 } 18637 return false; 18638 18639 default: 18640 return true; 18641 } 18642 } 18643 18644 /** 18645 * Reset resolved text alignment. Text alignment will be resolved during a call to 18646 * {@link #onMeasure(int, int)}. 18647 * 18648 * @hide 18649 */ 18650 public void resetResolvedTextAlignment() { 18651 // Reset any previous text alignment resolution 18652 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 18653 // Set to default 18654 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 18655 } 18656 18657 /** 18658 * @return true if text alignment is inherited. 18659 * 18660 * @hide 18661 */ 18662 public boolean isTextAlignmentInherited() { 18663 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 18664 } 18665 18666 /** 18667 * @return true if text alignment is resolved. 18668 */ 18669 public boolean isTextAlignmentResolved() { 18670 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 18671 } 18672 18673 /** 18674 * Generate a value suitable for use in {@link #setId(int)}. 18675 * This value will not collide with ID values generated at build time by aapt for R.id. 18676 * 18677 * @return a generated ID value 18678 */ 18679 public static int generateViewId() { 18680 for (;;) { 18681 final int result = sNextGeneratedId.get(); 18682 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 18683 int newValue = result + 1; 18684 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 18685 if (sNextGeneratedId.compareAndSet(result, newValue)) { 18686 return result; 18687 } 18688 } 18689 } 18690 18691 /** 18692 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. 18693 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and 18694 * a normal View or a ViewGroup with 18695 * {@link android.view.ViewGroup#isTransitionGroup()} true. 18696 * @hide 18697 */ 18698 public void captureTransitioningViews(List<View> transitioningViews) { 18699 if (getVisibility() == View.VISIBLE) { 18700 transitioningViews.add(this); 18701 } 18702 } 18703 18704 /** 18705 * Adds all Views that have {@link #getSharedElementName()} non-null to sharedElements. 18706 * @param sharedElements Will contain all Views in the hierarchy having a shared element name. 18707 * @hide 18708 */ 18709 public void findSharedElements(Map<String, View> sharedElements) { 18710 if (getVisibility() == VISIBLE) { 18711 String sharedElementName = getSharedElementName(); 18712 if (sharedElementName != null) { 18713 sharedElements.put(sharedElementName, this); 18714 } 18715 } 18716 } 18717 18718 // 18719 // Properties 18720 // 18721 /** 18722 * A Property wrapper around the <code>alpha</code> functionality handled by the 18723 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 18724 */ 18725 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 18726 @Override 18727 public void setValue(View object, float value) { 18728 object.setAlpha(value); 18729 } 18730 18731 @Override 18732 public Float get(View object) { 18733 return object.getAlpha(); 18734 } 18735 }; 18736 18737 /** 18738 * A Property wrapper around the <code>translationX</code> functionality handled by the 18739 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 18740 */ 18741 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 18742 @Override 18743 public void setValue(View object, float value) { 18744 object.setTranslationX(value); 18745 } 18746 18747 @Override 18748 public Float get(View object) { 18749 return object.getTranslationX(); 18750 } 18751 }; 18752 18753 /** 18754 * A Property wrapper around the <code>translationY</code> functionality handled by the 18755 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 18756 */ 18757 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 18758 @Override 18759 public void setValue(View object, float value) { 18760 object.setTranslationY(value); 18761 } 18762 18763 @Override 18764 public Float get(View object) { 18765 return object.getTranslationY(); 18766 } 18767 }; 18768 18769 /** 18770 * A Property wrapper around the <code>translationZ</code> functionality handled by the 18771 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods. 18772 */ 18773 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") { 18774 @Override 18775 public void setValue(View object, float value) { 18776 object.setTranslationZ(value); 18777 } 18778 18779 @Override 18780 public Float get(View object) { 18781 return object.getTranslationZ(); 18782 } 18783 }; 18784 18785 /** 18786 * A Property wrapper around the <code>x</code> functionality handled by the 18787 * {@link View#setX(float)} and {@link View#getX()} methods. 18788 */ 18789 public static final Property<View, Float> X = new FloatProperty<View>("x") { 18790 @Override 18791 public void setValue(View object, float value) { 18792 object.setX(value); 18793 } 18794 18795 @Override 18796 public Float get(View object) { 18797 return object.getX(); 18798 } 18799 }; 18800 18801 /** 18802 * A Property wrapper around the <code>y</code> functionality handled by the 18803 * {@link View#setY(float)} and {@link View#getY()} methods. 18804 */ 18805 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 18806 @Override 18807 public void setValue(View object, float value) { 18808 object.setY(value); 18809 } 18810 18811 @Override 18812 public Float get(View object) { 18813 return object.getY(); 18814 } 18815 }; 18816 18817 /** 18818 * A Property wrapper around the <code>rotation</code> functionality handled by the 18819 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 18820 */ 18821 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 18822 @Override 18823 public void setValue(View object, float value) { 18824 object.setRotation(value); 18825 } 18826 18827 @Override 18828 public Float get(View object) { 18829 return object.getRotation(); 18830 } 18831 }; 18832 18833 /** 18834 * A Property wrapper around the <code>rotationX</code> functionality handled by the 18835 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 18836 */ 18837 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 18838 @Override 18839 public void setValue(View object, float value) { 18840 object.setRotationX(value); 18841 } 18842 18843 @Override 18844 public Float get(View object) { 18845 return object.getRotationX(); 18846 } 18847 }; 18848 18849 /** 18850 * A Property wrapper around the <code>rotationY</code> functionality handled by the 18851 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 18852 */ 18853 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 18854 @Override 18855 public void setValue(View object, float value) { 18856 object.setRotationY(value); 18857 } 18858 18859 @Override 18860 public Float get(View object) { 18861 return object.getRotationY(); 18862 } 18863 }; 18864 18865 /** 18866 * A Property wrapper around the <code>scaleX</code> functionality handled by the 18867 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 18868 */ 18869 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 18870 @Override 18871 public void setValue(View object, float value) { 18872 object.setScaleX(value); 18873 } 18874 18875 @Override 18876 public Float get(View object) { 18877 return object.getScaleX(); 18878 } 18879 }; 18880 18881 /** 18882 * A Property wrapper around the <code>scaleY</code> functionality handled by the 18883 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 18884 */ 18885 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 18886 @Override 18887 public void setValue(View object, float value) { 18888 object.setScaleY(value); 18889 } 18890 18891 @Override 18892 public Float get(View object) { 18893 return object.getScaleY(); 18894 } 18895 }; 18896 18897 /** 18898 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 18899 * Each MeasureSpec represents a requirement for either the width or the height. 18900 * A MeasureSpec is comprised of a size and a mode. There are three possible 18901 * modes: 18902 * <dl> 18903 * <dt>UNSPECIFIED</dt> 18904 * <dd> 18905 * The parent has not imposed any constraint on the child. It can be whatever size 18906 * it wants. 18907 * </dd> 18908 * 18909 * <dt>EXACTLY</dt> 18910 * <dd> 18911 * The parent has determined an exact size for the child. The child is going to be 18912 * given those bounds regardless of how big it wants to be. 18913 * </dd> 18914 * 18915 * <dt>AT_MOST</dt> 18916 * <dd> 18917 * The child can be as large as it wants up to the specified size. 18918 * </dd> 18919 * </dl> 18920 * 18921 * MeasureSpecs are implemented as ints to reduce object allocation. This class 18922 * is provided to pack and unpack the <size, mode> tuple into the int. 18923 */ 18924 public static class MeasureSpec { 18925 private static final int MODE_SHIFT = 30; 18926 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 18927 18928 /** 18929 * Measure specification mode: The parent has not imposed any constraint 18930 * on the child. It can be whatever size it wants. 18931 */ 18932 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 18933 18934 /** 18935 * Measure specification mode: The parent has determined an exact size 18936 * for the child. The child is going to be given those bounds regardless 18937 * of how big it wants to be. 18938 */ 18939 public static final int EXACTLY = 1 << MODE_SHIFT; 18940 18941 /** 18942 * Measure specification mode: The child can be as large as it wants up 18943 * to the specified size. 18944 */ 18945 public static final int AT_MOST = 2 << MODE_SHIFT; 18946 18947 /** 18948 * Creates a measure specification based on the supplied size and mode. 18949 * 18950 * The mode must always be one of the following: 18951 * <ul> 18952 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 18953 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 18954 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 18955 * </ul> 18956 * 18957 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 18958 * implementation was such that the order of arguments did not matter 18959 * and overflow in either value could impact the resulting MeasureSpec. 18960 * {@link android.widget.RelativeLayout} was affected by this bug. 18961 * Apps targeting API levels greater than 17 will get the fixed, more strict 18962 * behavior.</p> 18963 * 18964 * @param size the size of the measure specification 18965 * @param mode the mode of the measure specification 18966 * @return the measure specification based on size and mode 18967 */ 18968 public static int makeMeasureSpec(int size, int mode) { 18969 if (sUseBrokenMakeMeasureSpec) { 18970 return size + mode; 18971 } else { 18972 return (size & ~MODE_MASK) | (mode & MODE_MASK); 18973 } 18974 } 18975 18976 /** 18977 * Extracts the mode from the supplied measure specification. 18978 * 18979 * @param measureSpec the measure specification to extract the mode from 18980 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 18981 * {@link android.view.View.MeasureSpec#AT_MOST} or 18982 * {@link android.view.View.MeasureSpec#EXACTLY} 18983 */ 18984 public static int getMode(int measureSpec) { 18985 return (measureSpec & MODE_MASK); 18986 } 18987 18988 /** 18989 * Extracts the size from the supplied measure specification. 18990 * 18991 * @param measureSpec the measure specification to extract the size from 18992 * @return the size in pixels defined in the supplied measure specification 18993 */ 18994 public static int getSize(int measureSpec) { 18995 return (measureSpec & ~MODE_MASK); 18996 } 18997 18998 static int adjust(int measureSpec, int delta) { 18999 final int mode = getMode(measureSpec); 19000 if (mode == UNSPECIFIED) { 19001 // No need to adjust size for UNSPECIFIED mode. 19002 return makeMeasureSpec(0, UNSPECIFIED); 19003 } 19004 int size = getSize(measureSpec) + delta; 19005 if (size < 0) { 19006 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + 19007 ") spec: " + toString(measureSpec) + " delta: " + delta); 19008 size = 0; 19009 } 19010 return makeMeasureSpec(size, mode); 19011 } 19012 19013 /** 19014 * Returns a String representation of the specified measure 19015 * specification. 19016 * 19017 * @param measureSpec the measure specification to convert to a String 19018 * @return a String with the following format: "MeasureSpec: MODE SIZE" 19019 */ 19020 public static String toString(int measureSpec) { 19021 int mode = getMode(measureSpec); 19022 int size = getSize(measureSpec); 19023 19024 StringBuilder sb = new StringBuilder("MeasureSpec: "); 19025 19026 if (mode == UNSPECIFIED) 19027 sb.append("UNSPECIFIED "); 19028 else if (mode == EXACTLY) 19029 sb.append("EXACTLY "); 19030 else if (mode == AT_MOST) 19031 sb.append("AT_MOST "); 19032 else 19033 sb.append(mode).append(" "); 19034 19035 sb.append(size); 19036 return sb.toString(); 19037 } 19038 } 19039 19040 private final class CheckForLongPress implements Runnable { 19041 private int mOriginalWindowAttachCount; 19042 19043 @Override 19044 public void run() { 19045 if (isPressed() && (mParent != null) 19046 && mOriginalWindowAttachCount == mWindowAttachCount) { 19047 if (performLongClick()) { 19048 mHasPerformedLongPress = true; 19049 } 19050 } 19051 } 19052 19053 public void rememberWindowAttachCount() { 19054 mOriginalWindowAttachCount = mWindowAttachCount; 19055 } 19056 } 19057 19058 private final class CheckForTap implements Runnable { 19059 public float x; 19060 public float y; 19061 19062 @Override 19063 public void run() { 19064 mPrivateFlags &= ~PFLAG_PREPRESSED; 19065 setHotspot(R.attr.state_pressed, x, y); 19066 setPressed(true); 19067 checkForLongClick(ViewConfiguration.getTapTimeout()); 19068 } 19069 } 19070 19071 private final class PerformClick implements Runnable { 19072 @Override 19073 public void run() { 19074 performClick(); 19075 } 19076 } 19077 19078 /** @hide */ 19079 public void hackTurnOffWindowResizeAnim(boolean off) { 19080 mAttachInfo.mTurnOffWindowResizeAnim = off; 19081 } 19082 19083 /** 19084 * This method returns a ViewPropertyAnimator object, which can be used to animate 19085 * specific properties on this View. 19086 * 19087 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 19088 */ 19089 public ViewPropertyAnimator animate() { 19090 if (mAnimator == null) { 19091 mAnimator = new ViewPropertyAnimator(this); 19092 } 19093 return mAnimator; 19094 } 19095 19096 /** 19097 * Specifies that the shared name of the View to be shared with another Activity. 19098 * When transitioning between Activities, the name links a UI element in the starting 19099 * Activity to UI element in the called Activity. Names should be unique in the 19100 * View hierarchy. 19101 * 19102 * @param sharedElementName The cross-Activity View identifier. The called Activity will use 19103 * the name to match the location with a View in its layout. 19104 * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle) 19105 */ 19106 public void setSharedElementName(String sharedElementName) { 19107 setTagInternal(com.android.internal.R.id.shared_element_name, sharedElementName); 19108 } 19109 19110 /** 19111 * Returns the shared name of the View to be shared with another Activity. 19112 * When transitioning between Activities, the name links a UI element in the starting 19113 * Activity to UI element in the called Activity. Names should be unique in the 19114 * View hierarchy. 19115 * 19116 * <p>This returns null if the View is not a shared element or the name if it is.</p> 19117 * 19118 * @return The name used for this View for cross-Activity transitions or null if 19119 * this View has not been identified as shared. 19120 */ 19121 public String getSharedElementName() { 19122 return (String) getTag(com.android.internal.R.id.shared_element_name); 19123 } 19124 19125 /** 19126 * Interface definition for a callback to be invoked when a hardware key event is 19127 * dispatched to this view. The callback will be invoked before the key event is 19128 * given to the view. This is only useful for hardware keyboards; a software input 19129 * method has no obligation to trigger this listener. 19130 */ 19131 public interface OnKeyListener { 19132 /** 19133 * Called when a hardware key is dispatched to a view. This allows listeners to 19134 * get a chance to respond before the target view. 19135 * <p>Key presses in software keyboards will generally NOT trigger this method, 19136 * although some may elect to do so in some situations. Do not assume a 19137 * software input method has to be key-based; even if it is, it may use key presses 19138 * in a different way than you expect, so there is no way to reliably catch soft 19139 * input key presses. 19140 * 19141 * @param v The view the key has been dispatched to. 19142 * @param keyCode The code for the physical key that was pressed 19143 * @param event The KeyEvent object containing full information about 19144 * the event. 19145 * @return True if the listener has consumed the event, false otherwise. 19146 */ 19147 boolean onKey(View v, int keyCode, KeyEvent event); 19148 } 19149 19150 /** 19151 * Interface definition for a callback to be invoked when a touch event is 19152 * dispatched to this view. The callback will be invoked before the touch 19153 * event is given to the view. 19154 */ 19155 public interface OnTouchListener { 19156 /** 19157 * Called when a touch event is dispatched to a view. This allows listeners to 19158 * get a chance to respond before the target view. 19159 * 19160 * @param v The view the touch event has been dispatched to. 19161 * @param event The MotionEvent object containing full information about 19162 * the event. 19163 * @return True if the listener has consumed the event, false otherwise. 19164 */ 19165 boolean onTouch(View v, MotionEvent event); 19166 } 19167 19168 /** 19169 * Interface definition for a callback to be invoked when a hover event is 19170 * dispatched to this view. The callback will be invoked before the hover 19171 * event is given to the view. 19172 */ 19173 public interface OnHoverListener { 19174 /** 19175 * Called when a hover event is dispatched to a view. This allows listeners to 19176 * get a chance to respond before the target view. 19177 * 19178 * @param v The view the hover event has been dispatched to. 19179 * @param event The MotionEvent object containing full information about 19180 * the event. 19181 * @return True if the listener has consumed the event, false otherwise. 19182 */ 19183 boolean onHover(View v, MotionEvent event); 19184 } 19185 19186 /** 19187 * Interface definition for a callback to be invoked when a generic motion event is 19188 * dispatched to this view. The callback will be invoked before the generic motion 19189 * event is given to the view. 19190 */ 19191 public interface OnGenericMotionListener { 19192 /** 19193 * Called when a generic motion event is dispatched to a view. This allows listeners to 19194 * get a chance to respond before the target view. 19195 * 19196 * @param v The view the generic motion event has been dispatched to. 19197 * @param event The MotionEvent object containing full information about 19198 * the event. 19199 * @return True if the listener has consumed the event, false otherwise. 19200 */ 19201 boolean onGenericMotion(View v, MotionEvent event); 19202 } 19203 19204 /** 19205 * Interface definition for a callback to be invoked when a view has been clicked and held. 19206 */ 19207 public interface OnLongClickListener { 19208 /** 19209 * Called when a view has been clicked and held. 19210 * 19211 * @param v The view that was clicked and held. 19212 * 19213 * @return true if the callback consumed the long click, false otherwise. 19214 */ 19215 boolean onLongClick(View v); 19216 } 19217 19218 /** 19219 * Interface definition for a callback to be invoked when a drag is being dispatched 19220 * to this view. The callback will be invoked before the hosting view's own 19221 * onDrag(event) method. If the listener wants to fall back to the hosting view's 19222 * onDrag(event) behavior, it should return 'false' from this callback. 19223 * 19224 * <div class="special reference"> 19225 * <h3>Developer Guides</h3> 19226 * <p>For a guide to implementing drag and drop features, read the 19227 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 19228 * </div> 19229 */ 19230 public interface OnDragListener { 19231 /** 19232 * Called when a drag event is dispatched to a view. This allows listeners 19233 * to get a chance to override base View behavior. 19234 * 19235 * @param v The View that received the drag event. 19236 * @param event The {@link android.view.DragEvent} object for the drag event. 19237 * @return {@code true} if the drag event was handled successfully, or {@code false} 19238 * if the drag event was not handled. Note that {@code false} will trigger the View 19239 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 19240 */ 19241 boolean onDrag(View v, DragEvent event); 19242 } 19243 19244 /** 19245 * Interface definition for a callback to be invoked when the focus state of 19246 * a view changed. 19247 */ 19248 public interface OnFocusChangeListener { 19249 /** 19250 * Called when the focus state of a view has changed. 19251 * 19252 * @param v The view whose state has changed. 19253 * @param hasFocus The new focus state of v. 19254 */ 19255 void onFocusChange(View v, boolean hasFocus); 19256 } 19257 19258 /** 19259 * Interface definition for a callback to be invoked when a view is clicked. 19260 */ 19261 public interface OnClickListener { 19262 /** 19263 * Called when a view has been clicked. 19264 * 19265 * @param v The view that was clicked. 19266 */ 19267 void onClick(View v); 19268 } 19269 19270 /** 19271 * Interface definition for a callback to be invoked when the context menu 19272 * for this view is being built. 19273 */ 19274 public interface OnCreateContextMenuListener { 19275 /** 19276 * Called when the context menu for this view is being built. It is not 19277 * safe to hold onto the menu after this method returns. 19278 * 19279 * @param menu The context menu that is being built 19280 * @param v The view for which the context menu is being built 19281 * @param menuInfo Extra information about the item for which the 19282 * context menu should be shown. This information will vary 19283 * depending on the class of v. 19284 */ 19285 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 19286 } 19287 19288 /** 19289 * Interface definition for a callback to be invoked when the status bar changes 19290 * visibility. This reports <strong>global</strong> changes to the system UI 19291 * state, not what the application is requesting. 19292 * 19293 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 19294 */ 19295 public interface OnSystemUiVisibilityChangeListener { 19296 /** 19297 * Called when the status bar changes visibility because of a call to 19298 * {@link View#setSystemUiVisibility(int)}. 19299 * 19300 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 19301 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 19302 * This tells you the <strong>global</strong> state of these UI visibility 19303 * flags, not what your app is currently applying. 19304 */ 19305 public void onSystemUiVisibilityChange(int visibility); 19306 } 19307 19308 /** 19309 * Interface definition for a callback to be invoked when this view is attached 19310 * or detached from its window. 19311 */ 19312 public interface OnAttachStateChangeListener { 19313 /** 19314 * Called when the view is attached to a window. 19315 * @param v The view that was attached 19316 */ 19317 public void onViewAttachedToWindow(View v); 19318 /** 19319 * Called when the view is detached from a window. 19320 * @param v The view that was detached 19321 */ 19322 public void onViewDetachedFromWindow(View v); 19323 } 19324 19325 /** 19326 * Listener for applying window insets on a view in a custom way. 19327 * 19328 * <p>Apps may choose to implement this interface if they want to apply custom policy 19329 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener 19330 * is set, its 19331 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 19332 * method will be called instead of the View's own 19333 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener 19334 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply 19335 * the View's normal behavior as part of its own.</p> 19336 */ 19337 public interface OnApplyWindowInsetsListener { 19338 /** 19339 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set} 19340 * on a View, this listener method will be called instead of the view's own 19341 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 19342 * 19343 * @param v The view applying window insets 19344 * @param insets The insets to apply 19345 * @return The insets supplied, minus any insets that were consumed 19346 */ 19347 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets); 19348 } 19349 19350 private final class UnsetPressedState implements Runnable { 19351 @Override 19352 public void run() { 19353 clearHotspot(R.attr.state_pressed); 19354 setPressed(false); 19355 } 19356 } 19357 19358 /** 19359 * Base class for derived classes that want to save and restore their own 19360 * state in {@link android.view.View#onSaveInstanceState()}. 19361 */ 19362 public static class BaseSavedState extends AbsSavedState { 19363 /** 19364 * Constructor used when reading from a parcel. Reads the state of the superclass. 19365 * 19366 * @param source 19367 */ 19368 public BaseSavedState(Parcel source) { 19369 super(source); 19370 } 19371 19372 /** 19373 * Constructor called by derived classes when creating their SavedState objects 19374 * 19375 * @param superState The state of the superclass of this view 19376 */ 19377 public BaseSavedState(Parcelable superState) { 19378 super(superState); 19379 } 19380 19381 public static final Parcelable.Creator<BaseSavedState> CREATOR = 19382 new Parcelable.Creator<BaseSavedState>() { 19383 public BaseSavedState createFromParcel(Parcel in) { 19384 return new BaseSavedState(in); 19385 } 19386 19387 public BaseSavedState[] newArray(int size) { 19388 return new BaseSavedState[size]; 19389 } 19390 }; 19391 } 19392 19393 /** 19394 * A set of information given to a view when it is attached to its parent 19395 * window. 19396 */ 19397 final static class AttachInfo { 19398 interface Callbacks { 19399 void playSoundEffect(int effectId); 19400 boolean performHapticFeedback(int effectId, boolean always); 19401 } 19402 19403 /** 19404 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 19405 * to a Handler. This class contains the target (View) to invalidate and 19406 * the coordinates of the dirty rectangle. 19407 * 19408 * For performance purposes, this class also implements a pool of up to 19409 * POOL_LIMIT objects that get reused. This reduces memory allocations 19410 * whenever possible. 19411 */ 19412 static class InvalidateInfo { 19413 private static final int POOL_LIMIT = 10; 19414 19415 private static final SynchronizedPool<InvalidateInfo> sPool = 19416 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 19417 19418 View target; 19419 19420 int left; 19421 int top; 19422 int right; 19423 int bottom; 19424 19425 public static InvalidateInfo obtain() { 19426 InvalidateInfo instance = sPool.acquire(); 19427 return (instance != null) ? instance : new InvalidateInfo(); 19428 } 19429 19430 public void recycle() { 19431 target = null; 19432 sPool.release(this); 19433 } 19434 } 19435 19436 final IWindowSession mSession; 19437 19438 final IWindow mWindow; 19439 19440 final IBinder mWindowToken; 19441 19442 final Display mDisplay; 19443 19444 final Callbacks mRootCallbacks; 19445 19446 IWindowId mIWindowId; 19447 WindowId mWindowId; 19448 19449 /** 19450 * The top view of the hierarchy. 19451 */ 19452 View mRootView; 19453 19454 IBinder mPanelParentWindowToken; 19455 19456 boolean mHardwareAccelerated; 19457 boolean mHardwareAccelerationRequested; 19458 HardwareRenderer mHardwareRenderer; 19459 19460 /** 19461 * The state of the display to which the window is attached, as reported 19462 * by {@link Display#getState()}. Note that the display state constants 19463 * declared by {@link Display} do not exactly line up with the screen state 19464 * constants declared by {@link View} (there are more display states than 19465 * screen states). 19466 */ 19467 int mDisplayState = Display.STATE_UNKNOWN; 19468 19469 /** 19470 * Scale factor used by the compatibility mode 19471 */ 19472 float mApplicationScale; 19473 19474 /** 19475 * Indicates whether the application is in compatibility mode 19476 */ 19477 boolean mScalingRequired; 19478 19479 /** 19480 * If set, ViewRootImpl doesn't use its lame animation for when the window resizes. 19481 */ 19482 boolean mTurnOffWindowResizeAnim; 19483 19484 /** 19485 * Left position of this view's window 19486 */ 19487 int mWindowLeft; 19488 19489 /** 19490 * Top position of this view's window 19491 */ 19492 int mWindowTop; 19493 19494 /** 19495 * Indicates whether views need to use 32-bit drawing caches 19496 */ 19497 boolean mUse32BitDrawingCache; 19498 19499 /** 19500 * For windows that are full-screen but using insets to layout inside 19501 * of the screen areas, these are the current insets to appear inside 19502 * the overscan area of the display. 19503 */ 19504 final Rect mOverscanInsets = new Rect(); 19505 19506 /** 19507 * For windows that are full-screen but using insets to layout inside 19508 * of the screen decorations, these are the current insets for the 19509 * content of the window. 19510 */ 19511 final Rect mContentInsets = new Rect(); 19512 19513 /** 19514 * For windows that are full-screen but using insets to layout inside 19515 * of the screen decorations, these are the current insets for the 19516 * actual visible parts of the window. 19517 */ 19518 final Rect mVisibleInsets = new Rect(); 19519 19520 /** 19521 * The internal insets given by this window. This value is 19522 * supplied by the client (through 19523 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 19524 * be given to the window manager when changed to be used in laying 19525 * out windows behind it. 19526 */ 19527 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 19528 = new ViewTreeObserver.InternalInsetsInfo(); 19529 19530 /** 19531 * Set to true when mGivenInternalInsets is non-empty. 19532 */ 19533 boolean mHasNonEmptyGivenInternalInsets; 19534 19535 /** 19536 * All views in the window's hierarchy that serve as scroll containers, 19537 * used to determine if the window can be resized or must be panned 19538 * to adjust for a soft input area. 19539 */ 19540 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 19541 19542 final KeyEvent.DispatcherState mKeyDispatchState 19543 = new KeyEvent.DispatcherState(); 19544 19545 /** 19546 * Indicates whether the view's window currently has the focus. 19547 */ 19548 boolean mHasWindowFocus; 19549 19550 /** 19551 * The current visibility of the window. 19552 */ 19553 int mWindowVisibility; 19554 19555 /** 19556 * Indicates the time at which drawing started to occur. 19557 */ 19558 long mDrawingTime; 19559 19560 /** 19561 * Indicates whether or not ignoring the DIRTY_MASK flags. 19562 */ 19563 boolean mIgnoreDirtyState; 19564 19565 /** 19566 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 19567 * to avoid clearing that flag prematurely. 19568 */ 19569 boolean mSetIgnoreDirtyState = false; 19570 19571 /** 19572 * Indicates whether the view's window is currently in touch mode. 19573 */ 19574 boolean mInTouchMode; 19575 19576 /** 19577 * Indicates that ViewAncestor should trigger a global layout change 19578 * the next time it performs a traversal 19579 */ 19580 boolean mRecomputeGlobalAttributes; 19581 19582 /** 19583 * Always report new attributes at next traversal. 19584 */ 19585 boolean mForceReportNewAttributes; 19586 19587 /** 19588 * Set during a traveral if any views want to keep the screen on. 19589 */ 19590 boolean mKeepScreenOn; 19591 19592 /** 19593 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 19594 */ 19595 int mSystemUiVisibility; 19596 19597 /** 19598 * Hack to force certain system UI visibility flags to be cleared. 19599 */ 19600 int mDisabledSystemUiVisibility; 19601 19602 /** 19603 * Last global system UI visibility reported by the window manager. 19604 */ 19605 int mGlobalSystemUiVisibility; 19606 19607 /** 19608 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 19609 * attached. 19610 */ 19611 boolean mHasSystemUiListeners; 19612 19613 /** 19614 * Set if the window has requested to extend into the overscan region 19615 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 19616 */ 19617 boolean mOverscanRequested; 19618 19619 /** 19620 * Set if the visibility of any views has changed. 19621 */ 19622 boolean mViewVisibilityChanged; 19623 19624 /** 19625 * Set to true if a view has been scrolled. 19626 */ 19627 boolean mViewScrollChanged; 19628 19629 /** 19630 * Global to the view hierarchy used as a temporary for dealing with 19631 * x/y points in the transparent region computations. 19632 */ 19633 final int[] mTransparentLocation = new int[2]; 19634 19635 /** 19636 * Global to the view hierarchy used as a temporary for dealing with 19637 * x/y points in the ViewGroup.invalidateChild implementation. 19638 */ 19639 final int[] mInvalidateChildLocation = new int[2]; 19640 19641 19642 /** 19643 * Global to the view hierarchy used as a temporary for dealing with 19644 * x/y location when view is transformed. 19645 */ 19646 final float[] mTmpTransformLocation = new float[2]; 19647 19648 /** 19649 * The view tree observer used to dispatch global events like 19650 * layout, pre-draw, touch mode change, etc. 19651 */ 19652 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 19653 19654 /** 19655 * A Canvas used by the view hierarchy to perform bitmap caching. 19656 */ 19657 Canvas mCanvas; 19658 19659 /** 19660 * The view root impl. 19661 */ 19662 final ViewRootImpl mViewRootImpl; 19663 19664 /** 19665 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 19666 * handler can be used to pump events in the UI events queue. 19667 */ 19668 final Handler mHandler; 19669 19670 /** 19671 * Temporary for use in computing invalidate rectangles while 19672 * calling up the hierarchy. 19673 */ 19674 final Rect mTmpInvalRect = new Rect(); 19675 19676 /** 19677 * Temporary for use in computing hit areas with transformed views 19678 */ 19679 final RectF mTmpTransformRect = new RectF(); 19680 19681 /** 19682 * Temporary for use in transforming invalidation rect 19683 */ 19684 final Matrix mTmpMatrix = new Matrix(); 19685 19686 /** 19687 * Temporary for use in transforming invalidation rect 19688 */ 19689 final Transformation mTmpTransformation = new Transformation(); 19690 19691 /** 19692 * Temporary list for use in collecting focusable descendents of a view. 19693 */ 19694 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 19695 19696 /** 19697 * The id of the window for accessibility purposes. 19698 */ 19699 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 19700 19701 /** 19702 * Flags related to accessibility processing. 19703 * 19704 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 19705 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 19706 */ 19707 int mAccessibilityFetchFlags; 19708 19709 /** 19710 * The drawable for highlighting accessibility focus. 19711 */ 19712 Drawable mAccessibilityFocusDrawable; 19713 19714 /** 19715 * Show where the margins, bounds and layout bounds are for each view. 19716 */ 19717 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 19718 19719 /** 19720 * Point used to compute visible regions. 19721 */ 19722 final Point mPoint = new Point(); 19723 19724 /** 19725 * Used to track which View originated a requestLayout() call, used when 19726 * requestLayout() is called during layout. 19727 */ 19728 View mViewRequestingLayout; 19729 19730 /** 19731 * Creates a new set of attachment information with the specified 19732 * events handler and thread. 19733 * 19734 * @param handler the events handler the view must use 19735 */ 19736 AttachInfo(IWindowSession session, IWindow window, Display display, 19737 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { 19738 mSession = session; 19739 mWindow = window; 19740 mWindowToken = window.asBinder(); 19741 mDisplay = display; 19742 mViewRootImpl = viewRootImpl; 19743 mHandler = handler; 19744 mRootCallbacks = effectPlayer; 19745 } 19746 } 19747 19748 /** 19749 * <p>ScrollabilityCache holds various fields used by a View when scrolling 19750 * is supported. This avoids keeping too many unused fields in most 19751 * instances of View.</p> 19752 */ 19753 private static class ScrollabilityCache implements Runnable { 19754 19755 /** 19756 * Scrollbars are not visible 19757 */ 19758 public static final int OFF = 0; 19759 19760 /** 19761 * Scrollbars are visible 19762 */ 19763 public static final int ON = 1; 19764 19765 /** 19766 * Scrollbars are fading away 19767 */ 19768 public static final int FADING = 2; 19769 19770 public boolean fadeScrollBars; 19771 19772 public int fadingEdgeLength; 19773 public int scrollBarDefaultDelayBeforeFade; 19774 public int scrollBarFadeDuration; 19775 19776 public int scrollBarSize; 19777 public ScrollBarDrawable scrollBar; 19778 public float[] interpolatorValues; 19779 public View host; 19780 19781 public final Paint paint; 19782 public final Matrix matrix; 19783 public Shader shader; 19784 19785 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 19786 19787 private static final float[] OPAQUE = { 255 }; 19788 private static final float[] TRANSPARENT = { 0.0f }; 19789 19790 /** 19791 * When fading should start. This time moves into the future every time 19792 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 19793 */ 19794 public long fadeStartTime; 19795 19796 19797 /** 19798 * The current state of the scrollbars: ON, OFF, or FADING 19799 */ 19800 public int state = OFF; 19801 19802 private int mLastColor; 19803 19804 public ScrollabilityCache(ViewConfiguration configuration, View host) { 19805 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 19806 scrollBarSize = configuration.getScaledScrollBarSize(); 19807 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 19808 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 19809 19810 paint = new Paint(); 19811 matrix = new Matrix(); 19812 // use use a height of 1, and then wack the matrix each time we 19813 // actually use it. 19814 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 19815 paint.setShader(shader); 19816 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 19817 19818 this.host = host; 19819 } 19820 19821 public void setFadeColor(int color) { 19822 if (color != mLastColor) { 19823 mLastColor = color; 19824 19825 if (color != 0) { 19826 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 19827 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 19828 paint.setShader(shader); 19829 // Restore the default transfer mode (src_over) 19830 paint.setXfermode(null); 19831 } else { 19832 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 19833 paint.setShader(shader); 19834 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 19835 } 19836 } 19837 } 19838 19839 public void run() { 19840 long now = AnimationUtils.currentAnimationTimeMillis(); 19841 if (now >= fadeStartTime) { 19842 19843 // the animation fades the scrollbars out by changing 19844 // the opacity (alpha) from fully opaque to fully 19845 // transparent 19846 int nextFrame = (int) now; 19847 int framesCount = 0; 19848 19849 Interpolator interpolator = scrollBarInterpolator; 19850 19851 // Start opaque 19852 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 19853 19854 // End transparent 19855 nextFrame += scrollBarFadeDuration; 19856 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 19857 19858 state = FADING; 19859 19860 // Kick off the fade animation 19861 host.invalidate(true); 19862 } 19863 } 19864 } 19865 19866 /** 19867 * Resuable callback for sending 19868 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 19869 */ 19870 private class SendViewScrolledAccessibilityEvent implements Runnable { 19871 public volatile boolean mIsPending; 19872 19873 public void run() { 19874 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 19875 mIsPending = false; 19876 } 19877 } 19878 19879 /** 19880 * <p> 19881 * This class represents a delegate that can be registered in a {@link View} 19882 * to enhance accessibility support via composition rather via inheritance. 19883 * It is specifically targeted to widget developers that extend basic View 19884 * classes i.e. classes in package android.view, that would like their 19885 * applications to be backwards compatible. 19886 * </p> 19887 * <div class="special reference"> 19888 * <h3>Developer Guides</h3> 19889 * <p>For more information about making applications accessible, read the 19890 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 19891 * developer guide.</p> 19892 * </div> 19893 * <p> 19894 * A scenario in which a developer would like to use an accessibility delegate 19895 * is overriding a method introduced in a later API version then the minimal API 19896 * version supported by the application. For example, the method 19897 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 19898 * in API version 4 when the accessibility APIs were first introduced. If a 19899 * developer would like his application to run on API version 4 devices (assuming 19900 * all other APIs used by the application are version 4 or lower) and take advantage 19901 * of this method, instead of overriding the method which would break the application's 19902 * backwards compatibility, he can override the corresponding method in this 19903 * delegate and register the delegate in the target View if the API version of 19904 * the system is high enough i.e. the API version is same or higher to the API 19905 * version that introduced 19906 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 19907 * </p> 19908 * <p> 19909 * Here is an example implementation: 19910 * </p> 19911 * <code><pre><p> 19912 * if (Build.VERSION.SDK_INT >= 14) { 19913 * // If the API version is equal of higher than the version in 19914 * // which onInitializeAccessibilityNodeInfo was introduced we 19915 * // register a delegate with a customized implementation. 19916 * View view = findViewById(R.id.view_id); 19917 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 19918 * public void onInitializeAccessibilityNodeInfo(View host, 19919 * AccessibilityNodeInfo info) { 19920 * // Let the default implementation populate the info. 19921 * super.onInitializeAccessibilityNodeInfo(host, info); 19922 * // Set some other information. 19923 * info.setEnabled(host.isEnabled()); 19924 * } 19925 * }); 19926 * } 19927 * </code></pre></p> 19928 * <p> 19929 * This delegate contains methods that correspond to the accessibility methods 19930 * in View. If a delegate has been specified the implementation in View hands 19931 * off handling to the corresponding method in this delegate. The default 19932 * implementation the delegate methods behaves exactly as the corresponding 19933 * method in View for the case of no accessibility delegate been set. Hence, 19934 * to customize the behavior of a View method, clients can override only the 19935 * corresponding delegate method without altering the behavior of the rest 19936 * accessibility related methods of the host view. 19937 * </p> 19938 */ 19939 public static class AccessibilityDelegate { 19940 19941 /** 19942 * Sends an accessibility event of the given type. If accessibility is not 19943 * enabled this method has no effect. 19944 * <p> 19945 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 19946 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 19947 * been set. 19948 * </p> 19949 * 19950 * @param host The View hosting the delegate. 19951 * @param eventType The type of the event to send. 19952 * 19953 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 19954 */ 19955 public void sendAccessibilityEvent(View host, int eventType) { 19956 host.sendAccessibilityEventInternal(eventType); 19957 } 19958 19959 /** 19960 * Performs the specified accessibility action on the view. For 19961 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 19962 * <p> 19963 * The default implementation behaves as 19964 * {@link View#performAccessibilityAction(int, Bundle) 19965 * View#performAccessibilityAction(int, Bundle)} for the case of 19966 * no accessibility delegate been set. 19967 * </p> 19968 * 19969 * @param action The action to perform. 19970 * @return Whether the action was performed. 19971 * 19972 * @see View#performAccessibilityAction(int, Bundle) 19973 * View#performAccessibilityAction(int, Bundle) 19974 */ 19975 public boolean performAccessibilityAction(View host, int action, Bundle args) { 19976 return host.performAccessibilityActionInternal(action, args); 19977 } 19978 19979 /** 19980 * Sends an accessibility event. This method behaves exactly as 19981 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 19982 * empty {@link AccessibilityEvent} and does not perform a check whether 19983 * accessibility is enabled. 19984 * <p> 19985 * The default implementation behaves as 19986 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19987 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 19988 * the case of no accessibility delegate been set. 19989 * </p> 19990 * 19991 * @param host The View hosting the delegate. 19992 * @param event The event to send. 19993 * 19994 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19995 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 19996 */ 19997 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 19998 host.sendAccessibilityEventUncheckedInternal(event); 19999 } 20000 20001 /** 20002 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 20003 * to its children for adding their text content to the event. 20004 * <p> 20005 * The default implementation behaves as 20006 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 20007 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 20008 * the case of no accessibility delegate been set. 20009 * </p> 20010 * 20011 * @param host The View hosting the delegate. 20012 * @param event The event. 20013 * @return True if the event population was completed. 20014 * 20015 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 20016 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 20017 */ 20018 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 20019 return host.dispatchPopulateAccessibilityEventInternal(event); 20020 } 20021 20022 /** 20023 * Gives a chance to the host View to populate the accessibility event with its 20024 * text content. 20025 * <p> 20026 * The default implementation behaves as 20027 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 20028 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 20029 * the case of no accessibility delegate been set. 20030 * </p> 20031 * 20032 * @param host The View hosting the delegate. 20033 * @param event The accessibility event which to populate. 20034 * 20035 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 20036 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 20037 */ 20038 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 20039 host.onPopulateAccessibilityEventInternal(event); 20040 } 20041 20042 /** 20043 * Initializes an {@link AccessibilityEvent} with information about the 20044 * the host View which is the event source. 20045 * <p> 20046 * The default implementation behaves as 20047 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 20048 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 20049 * the case of no accessibility delegate been set. 20050 * </p> 20051 * 20052 * @param host The View hosting the delegate. 20053 * @param event The event to initialize. 20054 * 20055 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 20056 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 20057 */ 20058 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 20059 host.onInitializeAccessibilityEventInternal(event); 20060 } 20061 20062 /** 20063 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 20064 * <p> 20065 * The default implementation behaves as 20066 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 20067 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 20068 * the case of no accessibility delegate been set. 20069 * </p> 20070 * 20071 * @param host The View hosting the delegate. 20072 * @param info The instance to initialize. 20073 * 20074 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 20075 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 20076 */ 20077 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 20078 host.onInitializeAccessibilityNodeInfoInternal(info); 20079 } 20080 20081 /** 20082 * Called when a child of the host View has requested sending an 20083 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 20084 * to augment the event. 20085 * <p> 20086 * The default implementation behaves as 20087 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 20088 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 20089 * the case of no accessibility delegate been set. 20090 * </p> 20091 * 20092 * @param host The View hosting the delegate. 20093 * @param child The child which requests sending the event. 20094 * @param event The event to be sent. 20095 * @return True if the event should be sent 20096 * 20097 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 20098 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 20099 */ 20100 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 20101 AccessibilityEvent event) { 20102 return host.onRequestSendAccessibilityEventInternal(child, event); 20103 } 20104 20105 /** 20106 * Gets the provider for managing a virtual view hierarchy rooted at this View 20107 * and reported to {@link android.accessibilityservice.AccessibilityService}s 20108 * that explore the window content. 20109 * <p> 20110 * The default implementation behaves as 20111 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 20112 * the case of no accessibility delegate been set. 20113 * </p> 20114 * 20115 * @return The provider. 20116 * 20117 * @see AccessibilityNodeProvider 20118 */ 20119 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 20120 return null; 20121 } 20122 20123 /** 20124 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 20125 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 20126 * This method is responsible for obtaining an accessibility node info from a 20127 * pool of reusable instances and calling 20128 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 20129 * view to initialize the former. 20130 * <p> 20131 * <strong>Note:</strong> The client is responsible for recycling the obtained 20132 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 20133 * creation. 20134 * </p> 20135 * <p> 20136 * The default implementation behaves as 20137 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 20138 * the case of no accessibility delegate been set. 20139 * </p> 20140 * @return A populated {@link AccessibilityNodeInfo}. 20141 * 20142 * @see AccessibilityNodeInfo 20143 * 20144 * @hide 20145 */ 20146 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 20147 return host.createAccessibilityNodeInfoInternal(); 20148 } 20149 } 20150 20151 private class MatchIdPredicate implements Predicate<View> { 20152 public int mId; 20153 20154 @Override 20155 public boolean apply(View view) { 20156 return (view.mID == mId); 20157 } 20158 } 20159 20160 private class MatchLabelForPredicate implements Predicate<View> { 20161 private int mLabeledId; 20162 20163 @Override 20164 public boolean apply(View view) { 20165 return (view.mLabelForId == mLabeledId); 20166 } 20167 } 20168 20169 private class SendViewStateChangedAccessibilityEvent implements Runnable { 20170 private int mChangeTypes = 0; 20171 private boolean mPosted; 20172 private boolean mPostedWithDelay; 20173 private long mLastEventTimeMillis; 20174 20175 @Override 20176 public void run() { 20177 mPosted = false; 20178 mPostedWithDelay = false; 20179 mLastEventTimeMillis = SystemClock.uptimeMillis(); 20180 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 20181 final AccessibilityEvent event = AccessibilityEvent.obtain(); 20182 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 20183 event.setContentChangeTypes(mChangeTypes); 20184 sendAccessibilityEventUnchecked(event); 20185 } 20186 mChangeTypes = 0; 20187 } 20188 20189 public void runOrPost(int changeType) { 20190 mChangeTypes |= changeType; 20191 20192 // If this is a live region or the child of a live region, collect 20193 // all events from this frame and send them on the next frame. 20194 if (inLiveRegion()) { 20195 // If we're already posted with a delay, remove that. 20196 if (mPostedWithDelay) { 20197 removeCallbacks(this); 20198 mPostedWithDelay = false; 20199 } 20200 // Only post if we're not already posted. 20201 if (!mPosted) { 20202 post(this); 20203 mPosted = true; 20204 } 20205 return; 20206 } 20207 20208 if (mPosted) { 20209 return; 20210 } 20211 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; 20212 final long minEventIntevalMillis = 20213 ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); 20214 if (timeSinceLastMillis >= minEventIntevalMillis) { 20215 removeCallbacks(this); 20216 run(); 20217 } else { 20218 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); 20219 mPosted = true; 20220 mPostedWithDelay = true; 20221 } 20222 } 20223 } 20224 20225 private boolean inLiveRegion() { 20226 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) { 20227 return true; 20228 } 20229 20230 ViewParent parent = getParent(); 20231 while (parent instanceof View) { 20232 if (((View) parent).getAccessibilityLiveRegion() 20233 != View.ACCESSIBILITY_LIVE_REGION_NONE) { 20234 return true; 20235 } 20236 parent = parent.getParent(); 20237 } 20238 20239 return false; 20240 } 20241 20242 /** 20243 * Dump all private flags in readable format, useful for documentation and 20244 * sanity checking. 20245 */ 20246 private static void dumpFlags() { 20247 final HashMap<String, String> found = Maps.newHashMap(); 20248 try { 20249 for (Field field : View.class.getDeclaredFields()) { 20250 final int modifiers = field.getModifiers(); 20251 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 20252 if (field.getType().equals(int.class)) { 20253 final int value = field.getInt(null); 20254 dumpFlag(found, field.getName(), value); 20255 } else if (field.getType().equals(int[].class)) { 20256 final int[] values = (int[]) field.get(null); 20257 for (int i = 0; i < values.length; i++) { 20258 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 20259 } 20260 } 20261 } 20262 } 20263 } catch (IllegalAccessException e) { 20264 throw new RuntimeException(e); 20265 } 20266 20267 final ArrayList<String> keys = Lists.newArrayList(); 20268 keys.addAll(found.keySet()); 20269 Collections.sort(keys); 20270 for (String key : keys) { 20271 Log.d(VIEW_LOG_TAG, found.get(key)); 20272 } 20273 } 20274 20275 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 20276 // Sort flags by prefix, then by bits, always keeping unique keys 20277 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 20278 final int prefix = name.indexOf('_'); 20279 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 20280 final String output = bits + " " + name; 20281 found.put(key, output); 20282 } 20283} 20284