View.java revision 9a230e01a1237749a8a19a5de8d46531b0c8ca6a
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.content.ClipData; 20import android.content.Context; 21import android.content.res.Configuration; 22import android.content.res.Resources; 23import android.content.res.TypedArray; 24import android.graphics.Bitmap; 25import android.graphics.Camera; 26import android.graphics.Canvas; 27import android.graphics.Interpolator; 28import android.graphics.LinearGradient; 29import android.graphics.Matrix; 30import android.graphics.Paint; 31import android.graphics.PixelFormat; 32import android.graphics.Point; 33import android.graphics.PorterDuff; 34import android.graphics.PorterDuffXfermode; 35import android.graphics.Rect; 36import android.graphics.RectF; 37import android.graphics.Region; 38import android.graphics.Shader; 39import android.graphics.drawable.ColorDrawable; 40import android.graphics.drawable.Drawable; 41import android.os.Handler; 42import android.os.IBinder; 43import android.os.Message; 44import android.os.Parcel; 45import android.os.Parcelable; 46import android.os.RemoteException; 47import android.os.SystemClock; 48import android.text.TextUtils; 49import android.util.AttributeSet; 50import android.util.FloatProperty; 51import android.util.LocaleUtil; 52import android.util.Log; 53import android.util.Pool; 54import android.util.Poolable; 55import android.util.PoolableManager; 56import android.util.Pools; 57import android.util.Property; 58import android.util.SparseArray; 59import android.util.TypedValue; 60import android.view.ContextMenu.ContextMenuInfo; 61import android.view.accessibility.AccessibilityEvent; 62import android.view.accessibility.AccessibilityEventSource; 63import android.view.accessibility.AccessibilityManager; 64import android.view.accessibility.AccessibilityNodeInfo; 65import android.view.animation.Animation; 66import android.view.animation.AnimationUtils; 67import android.view.inputmethod.EditorInfo; 68import android.view.inputmethod.InputConnection; 69import android.view.inputmethod.InputMethodManager; 70import android.widget.ScrollBarDrawable; 71 72import static android.os.Build.VERSION_CODES.*; 73 74import com.android.internal.R; 75import com.android.internal.util.Predicate; 76import com.android.internal.view.menu.MenuBuilder; 77 78import java.lang.ref.WeakReference; 79import java.lang.reflect.InvocationTargetException; 80import java.lang.reflect.Method; 81import java.util.ArrayList; 82import java.util.Arrays; 83import java.util.Locale; 84import java.util.concurrent.CopyOnWriteArrayList; 85 86/** 87 * <p> 88 * This class represents the basic building block for user interface components. A View 89 * occupies a rectangular area on the screen and is responsible for drawing and 90 * event handling. View is the base class for <em>widgets</em>, which are 91 * used to create interactive UI components (buttons, text fields, etc.). The 92 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 93 * are invisible containers that hold other Views (or other ViewGroups) and define 94 * their layout properties. 95 * </p> 96 * 97 * <div class="special reference"> 98 * <h3>Developer Guides</h3> 99 * <p>For information about using this class to develop your application's user interface, 100 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 101 * </div> 102 * 103 * <a name="Using"></a> 104 * <h3>Using Views</h3> 105 * <p> 106 * All of the views in a window are arranged in a single tree. You can add views 107 * either from code or by specifying a tree of views in one or more XML layout 108 * files. There are many specialized subclasses of views that act as controls or 109 * are capable of displaying text, images, or other content. 110 * </p> 111 * <p> 112 * Once you have created a tree of views, there are typically a few types of 113 * common operations you may wish to perform: 114 * <ul> 115 * <li><strong>Set properties:</strong> for example setting the text of a 116 * {@link android.widget.TextView}. The available properties and the methods 117 * that set them will vary among the different subclasses of views. Note that 118 * properties that are known at build time can be set in the XML layout 119 * files.</li> 120 * <li><strong>Set focus:</strong> The framework will handled moving focus in 121 * response to user input. To force focus to a specific view, call 122 * {@link #requestFocus}.</li> 123 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 124 * that will be notified when something interesting happens to the view. For 125 * example, all views will let you set a listener to be notified when the view 126 * gains or loses focus. You can register such a listener using 127 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 128 * Other view subclasses offer more specialized listeners. For example, a Button 129 * exposes a listener to notify clients when the button is clicked.</li> 130 * <li><strong>Set visibility:</strong> You can hide or show views using 131 * {@link #setVisibility(int)}.</li> 132 * </ul> 133 * </p> 134 * <p><em> 135 * Note: The Android framework is responsible for measuring, laying out and 136 * drawing views. You should not call methods that perform these actions on 137 * views yourself unless you are actually implementing a 138 * {@link android.view.ViewGroup}. 139 * </em></p> 140 * 141 * <a name="Lifecycle"></a> 142 * <h3>Implementing a Custom View</h3> 143 * 144 * <p> 145 * To implement a custom view, you will usually begin by providing overrides for 146 * some of the standard methods that the framework calls on all views. You do 147 * not need to override all of these methods. In fact, you can start by just 148 * overriding {@link #onDraw(android.graphics.Canvas)}. 149 * <table border="2" width="85%" align="center" cellpadding="5"> 150 * <thead> 151 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 152 * </thead> 153 * 154 * <tbody> 155 * <tr> 156 * <td rowspan="2">Creation</td> 157 * <td>Constructors</td> 158 * <td>There is a form of the constructor that are called when the view 159 * is created from code and a form that is called when the view is 160 * inflated from a layout file. The second form should parse and apply 161 * any attributes defined in the layout file. 162 * </td> 163 * </tr> 164 * <tr> 165 * <td><code>{@link #onFinishInflate()}</code></td> 166 * <td>Called after a view and all of its children has been inflated 167 * from XML.</td> 168 * </tr> 169 * 170 * <tr> 171 * <td rowspan="3">Layout</td> 172 * <td><code>{@link #onMeasure(int, int)}</code></td> 173 * <td>Called to determine the size requirements for this view and all 174 * of its children. 175 * </td> 176 * </tr> 177 * <tr> 178 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 179 * <td>Called when this view should assign a size and position to all 180 * of its children. 181 * </td> 182 * </tr> 183 * <tr> 184 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 185 * <td>Called when the size of this view has changed. 186 * </td> 187 * </tr> 188 * 189 * <tr> 190 * <td>Drawing</td> 191 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 192 * <td>Called when the view should render its content. 193 * </td> 194 * </tr> 195 * 196 * <tr> 197 * <td rowspan="4">Event processing</td> 198 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 199 * <td>Called when a new key event occurs. 200 * </td> 201 * </tr> 202 * <tr> 203 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 204 * <td>Called when a key up event occurs. 205 * </td> 206 * </tr> 207 * <tr> 208 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 209 * <td>Called when a trackball motion event occurs. 210 * </td> 211 * </tr> 212 * <tr> 213 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 214 * <td>Called when a touch screen motion event occurs. 215 * </td> 216 * </tr> 217 * 218 * <tr> 219 * <td rowspan="2">Focus</td> 220 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 221 * <td>Called when the view gains or loses focus. 222 * </td> 223 * </tr> 224 * 225 * <tr> 226 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 227 * <td>Called when the window containing the view gains or loses focus. 228 * </td> 229 * </tr> 230 * 231 * <tr> 232 * <td rowspan="3">Attaching</td> 233 * <td><code>{@link #onAttachedToWindow()}</code></td> 234 * <td>Called when the view is attached to a window. 235 * </td> 236 * </tr> 237 * 238 * <tr> 239 * <td><code>{@link #onDetachedFromWindow}</code></td> 240 * <td>Called when the view is detached from its window. 241 * </td> 242 * </tr> 243 * 244 * <tr> 245 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 246 * <td>Called when the visibility of the window containing the view 247 * has changed. 248 * </td> 249 * </tr> 250 * </tbody> 251 * 252 * </table> 253 * </p> 254 * 255 * <a name="IDs"></a> 256 * <h3>IDs</h3> 257 * Views may have an integer id associated with them. These ids are typically 258 * assigned in the layout XML files, and are used to find specific views within 259 * the view tree. A common pattern is to: 260 * <ul> 261 * <li>Define a Button in the layout file and assign it a unique ID. 262 * <pre> 263 * <Button 264 * android:id="@+id/my_button" 265 * android:layout_width="wrap_content" 266 * android:layout_height="wrap_content" 267 * android:text="@string/my_button_text"/> 268 * </pre></li> 269 * <li>From the onCreate method of an Activity, find the Button 270 * <pre class="prettyprint"> 271 * Button myButton = (Button) findViewById(R.id.my_button); 272 * </pre></li> 273 * </ul> 274 * <p> 275 * View IDs need not be unique throughout the tree, but it is good practice to 276 * ensure that they are at least unique within the part of the tree you are 277 * searching. 278 * </p> 279 * 280 * <a name="Position"></a> 281 * <h3>Position</h3> 282 * <p> 283 * The geometry of a view is that of a rectangle. A view has a location, 284 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 285 * two dimensions, expressed as a width and a height. The unit for location 286 * and dimensions is the pixel. 287 * </p> 288 * 289 * <p> 290 * It is possible to retrieve the location of a view by invoking the methods 291 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 292 * coordinate of the rectangle representing the view. The latter returns the 293 * top, or Y, coordinate of the rectangle representing the view. These methods 294 * both return the location of the view relative to its parent. For instance, 295 * when getLeft() returns 20, that means the view is located 20 pixels to the 296 * right of the left edge of its direct parent. 297 * </p> 298 * 299 * <p> 300 * In addition, several convenience methods are offered to avoid unnecessary 301 * computations, namely {@link #getRight()} and {@link #getBottom()}. 302 * These methods return the coordinates of the right and bottom edges of the 303 * rectangle representing the view. For instance, calling {@link #getRight()} 304 * is similar to the following computation: <code>getLeft() + getWidth()</code> 305 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 306 * </p> 307 * 308 * <a name="SizePaddingMargins"></a> 309 * <h3>Size, padding and margins</h3> 310 * <p> 311 * The size of a view is expressed with a width and a height. A view actually 312 * possess two pairs of width and height values. 313 * </p> 314 * 315 * <p> 316 * The first pair is known as <em>measured width</em> and 317 * <em>measured height</em>. These dimensions define how big a view wants to be 318 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 319 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 320 * and {@link #getMeasuredHeight()}. 321 * </p> 322 * 323 * <p> 324 * The second pair is simply known as <em>width</em> and <em>height</em>, or 325 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 326 * dimensions define the actual size of the view on screen, at drawing time and 327 * after layout. These values may, but do not have to, be different from the 328 * measured width and height. The width and height can be obtained by calling 329 * {@link #getWidth()} and {@link #getHeight()}. 330 * </p> 331 * 332 * <p> 333 * To measure its dimensions, a view takes into account its padding. The padding 334 * is expressed in pixels for the left, top, right and bottom parts of the view. 335 * Padding can be used to offset the content of the view by a specific amount of 336 * pixels. For instance, a left padding of 2 will push the view's content by 337 * 2 pixels to the right of the left edge. Padding can be set using the 338 * {@link #setPadding(int, int, int, int)} method and queried by calling 339 * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 340 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}. 341 * </p> 342 * 343 * <p> 344 * Even though a view can define a padding, it does not provide any support for 345 * margins. However, view groups provide such a support. Refer to 346 * {@link android.view.ViewGroup} and 347 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 348 * </p> 349 * 350 * <a name="Layout"></a> 351 * <h3>Layout</h3> 352 * <p> 353 * Layout is a two pass process: a measure pass and a layout pass. The measuring 354 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 355 * of the view tree. Each view pushes dimension specifications down the tree 356 * during the recursion. At the end of the measure pass, every view has stored 357 * its measurements. The second pass happens in 358 * {@link #layout(int,int,int,int)} and is also top-down. During 359 * this pass each parent is responsible for positioning all of its children 360 * using the sizes computed in the measure pass. 361 * </p> 362 * 363 * <p> 364 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 365 * {@link #getMeasuredHeight()} values must be set, along with those for all of 366 * that view's descendants. A view's measured width and measured height values 367 * must respect the constraints imposed by the view's parents. This guarantees 368 * that at the end of the measure pass, all parents accept all of their 369 * children's measurements. A parent view may call measure() more than once on 370 * its children. For example, the parent may measure each child once with 371 * unspecified dimensions to find out how big they want to be, then call 372 * measure() on them again with actual numbers if the sum of all the children's 373 * unconstrained sizes is too big or too small. 374 * </p> 375 * 376 * <p> 377 * The measure pass uses two classes to communicate dimensions. The 378 * {@link MeasureSpec} class is used by views to tell their parents how they 379 * want to be measured and positioned. The base LayoutParams class just 380 * describes how big the view wants to be for both width and height. For each 381 * dimension, it can specify one of: 382 * <ul> 383 * <li> an exact number 384 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 385 * (minus padding) 386 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 387 * enclose its content (plus padding). 388 * </ul> 389 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 390 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 391 * an X and Y value. 392 * </p> 393 * 394 * <p> 395 * MeasureSpecs are used to push requirements down the tree from parent to 396 * child. A MeasureSpec can be in one of three modes: 397 * <ul> 398 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 399 * of a child view. For example, a LinearLayout may call measure() on its child 400 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 401 * tall the child view wants to be given a width of 240 pixels. 402 * <li>EXACTLY: This is used by the parent to impose an exact size on the 403 * child. The child must use this size, and guarantee that all of its 404 * descendants will fit within this size. 405 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 406 * child. The child must gurantee that it and all of its descendants will fit 407 * within this size. 408 * </ul> 409 * </p> 410 * 411 * <p> 412 * To intiate a layout, call {@link #requestLayout}. This method is typically 413 * called by a view on itself when it believes that is can no longer fit within 414 * its current bounds. 415 * </p> 416 * 417 * <a name="Drawing"></a> 418 * <h3>Drawing</h3> 419 * <p> 420 * Drawing is handled by walking the tree and rendering each view that 421 * intersects the the invalid region. Because the tree is traversed in-order, 422 * this means that parents will draw before (i.e., behind) their children, with 423 * siblings drawn in the order they appear in the tree. 424 * If you set a background drawable for a View, then the View will draw it for you 425 * before calling back to its <code>onDraw()</code> method. 426 * </p> 427 * 428 * <p> 429 * Note that the framework will not draw views that are not in the invalid region. 430 * </p> 431 * 432 * <p> 433 * To force a view to draw, call {@link #invalidate()}. 434 * </p> 435 * 436 * <a name="EventHandlingThreading"></a> 437 * <h3>Event Handling and Threading</h3> 438 * <p> 439 * The basic cycle of a view is as follows: 440 * <ol> 441 * <li>An event comes in and is dispatched to the appropriate view. The view 442 * handles the event and notifies any listeners.</li> 443 * <li>If in the course of processing the event, the view's bounds may need 444 * to be changed, the view will call {@link #requestLayout()}.</li> 445 * <li>Similarly, if in the course of processing the event the view's appearance 446 * may need to be changed, the view will call {@link #invalidate()}.</li> 447 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 448 * the framework will take care of measuring, laying out, and drawing the tree 449 * as appropriate.</li> 450 * </ol> 451 * </p> 452 * 453 * <p><em>Note: The entire view tree is single threaded. You must always be on 454 * the UI thread when calling any method on any view.</em> 455 * If you are doing work on other threads and want to update the state of a view 456 * from that thread, you should use a {@link Handler}. 457 * </p> 458 * 459 * <a name="FocusHandling"></a> 460 * <h3>Focus Handling</h3> 461 * <p> 462 * The framework will handle routine focus movement in response to user input. 463 * This includes changing the focus as views are removed or hidden, or as new 464 * views become available. Views indicate their willingness to take focus 465 * through the {@link #isFocusable} method. To change whether a view can take 466 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 467 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 468 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 469 * </p> 470 * <p> 471 * Focus movement is based on an algorithm which finds the nearest neighbor in a 472 * given direction. In rare cases, the default algorithm may not match the 473 * intended behavior of the developer. In these situations, you can provide 474 * explicit overrides by using these XML attributes in the layout file: 475 * <pre> 476 * nextFocusDown 477 * nextFocusLeft 478 * nextFocusRight 479 * nextFocusUp 480 * </pre> 481 * </p> 482 * 483 * 484 * <p> 485 * To get a particular view to take focus, call {@link #requestFocus()}. 486 * </p> 487 * 488 * <a name="TouchMode"></a> 489 * <h3>Touch Mode</h3> 490 * <p> 491 * When a user is navigating a user interface via directional keys such as a D-pad, it is 492 * necessary to give focus to actionable items such as buttons so the user can see 493 * what will take input. If the device has touch capabilities, however, and the user 494 * begins interacting with the interface by touching it, it is no longer necessary to 495 * always highlight, or give focus to, a particular view. This motivates a mode 496 * for interaction named 'touch mode'. 497 * </p> 498 * <p> 499 * For a touch capable device, once the user touches the screen, the device 500 * will enter touch mode. From this point onward, only views for which 501 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 502 * Other views that are touchable, like buttons, will not take focus when touched; they will 503 * only fire the on click listeners. 504 * </p> 505 * <p> 506 * Any time a user hits a directional key, such as a D-pad direction, the view device will 507 * exit touch mode, and find a view to take focus, so that the user may resume interacting 508 * with the user interface without touching the screen again. 509 * </p> 510 * <p> 511 * The touch mode state is maintained across {@link android.app.Activity}s. Call 512 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 513 * </p> 514 * 515 * <a name="Scrolling"></a> 516 * <h3>Scrolling</h3> 517 * <p> 518 * The framework provides basic support for views that wish to internally 519 * scroll their content. This includes keeping track of the X and Y scroll 520 * offset as well as mechanisms for drawing scrollbars. See 521 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 522 * {@link #awakenScrollBars()} for more details. 523 * </p> 524 * 525 * <a name="Tags"></a> 526 * <h3>Tags</h3> 527 * <p> 528 * Unlike IDs, tags are not used to identify views. Tags are essentially an 529 * extra piece of information that can be associated with a view. They are most 530 * often used as a convenience to store data related to views in the views 531 * themselves rather than by putting them in a separate structure. 532 * </p> 533 * 534 * <a name="Animation"></a> 535 * <h3>Animation</h3> 536 * <p> 537 * You can attach an {@link Animation} object to a view using 538 * {@link #setAnimation(Animation)} or 539 * {@link #startAnimation(Animation)}. The animation can alter the scale, 540 * rotation, translation and alpha of a view over time. If the animation is 541 * attached to a view that has children, the animation will affect the entire 542 * subtree rooted by that node. When an animation is started, the framework will 543 * take care of redrawing the appropriate views until the animation completes. 544 * </p> 545 * <p> 546 * Starting with Android 3.0, the preferred way of animating views is to use the 547 * {@link android.animation} package APIs. 548 * </p> 549 * 550 * <a name="Security"></a> 551 * <h3>Security</h3> 552 * <p> 553 * Sometimes it is essential that an application be able to verify that an action 554 * is being performed with the full knowledge and consent of the user, such as 555 * granting a permission request, making a purchase or clicking on an advertisement. 556 * Unfortunately, a malicious application could try to spoof the user into 557 * performing these actions, unaware, by concealing the intended purpose of the view. 558 * As a remedy, the framework offers a touch filtering mechanism that can be used to 559 * improve the security of views that provide access to sensitive functionality. 560 * </p><p> 561 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 562 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 563 * will discard touches that are received whenever the view's window is obscured by 564 * another visible window. As a result, the view will not receive touches whenever a 565 * toast, dialog or other window appears above the view's window. 566 * </p><p> 567 * For more fine-grained control over security, consider overriding the 568 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 569 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 570 * </p> 571 * 572 * @attr ref android.R.styleable#View_alpha 573 * @attr ref android.R.styleable#View_background 574 * @attr ref android.R.styleable#View_clickable 575 * @attr ref android.R.styleable#View_contentDescription 576 * @attr ref android.R.styleable#View_drawingCacheQuality 577 * @attr ref android.R.styleable#View_duplicateParentState 578 * @attr ref android.R.styleable#View_id 579 * @attr ref android.R.styleable#View_requiresFadingEdge 580 * @attr ref android.R.styleable#View_fadingEdgeLength 581 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 582 * @attr ref android.R.styleable#View_fitsSystemWindows 583 * @attr ref android.R.styleable#View_isScrollContainer 584 * @attr ref android.R.styleable#View_focusable 585 * @attr ref android.R.styleable#View_focusableInTouchMode 586 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 587 * @attr ref android.R.styleable#View_keepScreenOn 588 * @attr ref android.R.styleable#View_layerType 589 * @attr ref android.R.styleable#View_longClickable 590 * @attr ref android.R.styleable#View_minHeight 591 * @attr ref android.R.styleable#View_minWidth 592 * @attr ref android.R.styleable#View_nextFocusDown 593 * @attr ref android.R.styleable#View_nextFocusLeft 594 * @attr ref android.R.styleable#View_nextFocusRight 595 * @attr ref android.R.styleable#View_nextFocusUp 596 * @attr ref android.R.styleable#View_onClick 597 * @attr ref android.R.styleable#View_padding 598 * @attr ref android.R.styleable#View_paddingBottom 599 * @attr ref android.R.styleable#View_paddingLeft 600 * @attr ref android.R.styleable#View_paddingRight 601 * @attr ref android.R.styleable#View_paddingTop 602 * @attr ref android.R.styleable#View_saveEnabled 603 * @attr ref android.R.styleable#View_rotation 604 * @attr ref android.R.styleable#View_rotationX 605 * @attr ref android.R.styleable#View_rotationY 606 * @attr ref android.R.styleable#View_scaleX 607 * @attr ref android.R.styleable#View_scaleY 608 * @attr ref android.R.styleable#View_scrollX 609 * @attr ref android.R.styleable#View_scrollY 610 * @attr ref android.R.styleable#View_scrollbarSize 611 * @attr ref android.R.styleable#View_scrollbarStyle 612 * @attr ref android.R.styleable#View_scrollbars 613 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 614 * @attr ref android.R.styleable#View_scrollbarFadeDuration 615 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 616 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 617 * @attr ref android.R.styleable#View_scrollbarThumbVertical 618 * @attr ref android.R.styleable#View_scrollbarTrackVertical 619 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 620 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 621 * @attr ref android.R.styleable#View_soundEffectsEnabled 622 * @attr ref android.R.styleable#View_tag 623 * @attr ref android.R.styleable#View_transformPivotX 624 * @attr ref android.R.styleable#View_transformPivotY 625 * @attr ref android.R.styleable#View_translationX 626 * @attr ref android.R.styleable#View_translationY 627 * @attr ref android.R.styleable#View_visibility 628 * 629 * @see android.view.ViewGroup 630 */ 631public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback, 632 AccessibilityEventSource { 633 private static final boolean DBG = false; 634 635 /** 636 * The logging tag used by this class with android.util.Log. 637 */ 638 protected static final String VIEW_LOG_TAG = "View"; 639 640 /** 641 * Used to mark a View that has no ID. 642 */ 643 public static final int NO_ID = -1; 644 645 /** 646 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 647 * calling setFlags. 648 */ 649 private static final int NOT_FOCUSABLE = 0x00000000; 650 651 /** 652 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 653 * setFlags. 654 */ 655 private static final int FOCUSABLE = 0x00000001; 656 657 /** 658 * Mask for use with setFlags indicating bits used for focus. 659 */ 660 private static final int FOCUSABLE_MASK = 0x00000001; 661 662 /** 663 * This view will adjust its padding to fit sytem windows (e.g. status bar) 664 */ 665 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 666 667 /** 668 * This view is visible. 669 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 670 * android:visibility}. 671 */ 672 public static final int VISIBLE = 0x00000000; 673 674 /** 675 * This view is invisible, but it still takes up space for layout purposes. 676 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 677 * android:visibility}. 678 */ 679 public static final int INVISIBLE = 0x00000004; 680 681 /** 682 * This view is invisible, and it doesn't take any space for layout 683 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 684 * android:visibility}. 685 */ 686 public static final int GONE = 0x00000008; 687 688 /** 689 * Mask for use with setFlags indicating bits used for visibility. 690 * {@hide} 691 */ 692 static final int VISIBILITY_MASK = 0x0000000C; 693 694 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 695 696 /** 697 * This view is enabled. Intrepretation varies by subclass. 698 * Use with ENABLED_MASK when calling setFlags. 699 * {@hide} 700 */ 701 static final int ENABLED = 0x00000000; 702 703 /** 704 * This view is disabled. Intrepretation varies by subclass. 705 * Use with ENABLED_MASK when calling setFlags. 706 * {@hide} 707 */ 708 static final int DISABLED = 0x00000020; 709 710 /** 711 * Mask for use with setFlags indicating bits used for indicating whether 712 * this view is enabled 713 * {@hide} 714 */ 715 static final int ENABLED_MASK = 0x00000020; 716 717 /** 718 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 719 * called and further optimizations will be performed. It is okay to have 720 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 721 * {@hide} 722 */ 723 static final int WILL_NOT_DRAW = 0x00000080; 724 725 /** 726 * Mask for use with setFlags indicating bits used for indicating whether 727 * this view is will draw 728 * {@hide} 729 */ 730 static final int DRAW_MASK = 0x00000080; 731 732 /** 733 * <p>This view doesn't show scrollbars.</p> 734 * {@hide} 735 */ 736 static final int SCROLLBARS_NONE = 0x00000000; 737 738 /** 739 * <p>This view shows horizontal scrollbars.</p> 740 * {@hide} 741 */ 742 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 743 744 /** 745 * <p>This view shows vertical scrollbars.</p> 746 * {@hide} 747 */ 748 static final int SCROLLBARS_VERTICAL = 0x00000200; 749 750 /** 751 * <p>Mask for use with setFlags indicating bits used for indicating which 752 * scrollbars are enabled.</p> 753 * {@hide} 754 */ 755 static final int SCROLLBARS_MASK = 0x00000300; 756 757 /** 758 * Indicates that the view should filter touches when its window is obscured. 759 * Refer to the class comments for more information about this security feature. 760 * {@hide} 761 */ 762 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 763 764 // note flag value 0x00000800 is now available for next flags... 765 766 /** 767 * <p>This view doesn't show fading edges.</p> 768 * {@hide} 769 */ 770 static final int FADING_EDGE_NONE = 0x00000000; 771 772 /** 773 * <p>This view shows horizontal fading edges.</p> 774 * {@hide} 775 */ 776 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 777 778 /** 779 * <p>This view shows vertical fading edges.</p> 780 * {@hide} 781 */ 782 static final int FADING_EDGE_VERTICAL = 0x00002000; 783 784 /** 785 * <p>Mask for use with setFlags indicating bits used for indicating which 786 * fading edges are enabled.</p> 787 * {@hide} 788 */ 789 static final int FADING_EDGE_MASK = 0x00003000; 790 791 /** 792 * <p>Indicates this view can be clicked. When clickable, a View reacts 793 * to clicks by notifying the OnClickListener.<p> 794 * {@hide} 795 */ 796 static final int CLICKABLE = 0x00004000; 797 798 /** 799 * <p>Indicates this view is caching its drawing into a bitmap.</p> 800 * {@hide} 801 */ 802 static final int DRAWING_CACHE_ENABLED = 0x00008000; 803 804 /** 805 * <p>Indicates that no icicle should be saved for this view.<p> 806 * {@hide} 807 */ 808 static final int SAVE_DISABLED = 0x000010000; 809 810 /** 811 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 812 * property.</p> 813 * {@hide} 814 */ 815 static final int SAVE_DISABLED_MASK = 0x000010000; 816 817 /** 818 * <p>Indicates that no drawing cache should ever be created for this view.<p> 819 * {@hide} 820 */ 821 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 822 823 /** 824 * <p>Indicates this view can take / keep focus when int touch mode.</p> 825 * {@hide} 826 */ 827 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 828 829 /** 830 * <p>Enables low quality mode for the drawing cache.</p> 831 */ 832 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 833 834 /** 835 * <p>Enables high quality mode for the drawing cache.</p> 836 */ 837 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 838 839 /** 840 * <p>Enables automatic quality mode for the drawing cache.</p> 841 */ 842 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 843 844 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 845 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 846 }; 847 848 /** 849 * <p>Mask for use with setFlags indicating bits used for the cache 850 * quality property.</p> 851 * {@hide} 852 */ 853 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 854 855 /** 856 * <p> 857 * Indicates this view can be long clicked. When long clickable, a View 858 * reacts to long clicks by notifying the OnLongClickListener or showing a 859 * context menu. 860 * </p> 861 * {@hide} 862 */ 863 static final int LONG_CLICKABLE = 0x00200000; 864 865 /** 866 * <p>Indicates that this view gets its drawable states from its direct parent 867 * and ignores its original internal states.</p> 868 * 869 * @hide 870 */ 871 static final int DUPLICATE_PARENT_STATE = 0x00400000; 872 873 /** 874 * The scrollbar style to display the scrollbars inside the content area, 875 * without increasing the padding. The scrollbars will be overlaid with 876 * translucency on the view's content. 877 */ 878 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 879 880 /** 881 * The scrollbar style to display the scrollbars inside the padded area, 882 * increasing the padding of the view. The scrollbars will not overlap the 883 * content area of the view. 884 */ 885 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 886 887 /** 888 * The scrollbar style to display the scrollbars at the edge of the view, 889 * without increasing the padding. The scrollbars will be overlaid with 890 * translucency. 891 */ 892 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 893 894 /** 895 * The scrollbar style to display the scrollbars at the edge of the view, 896 * increasing the padding of the view. The scrollbars will only overlap the 897 * background, if any. 898 */ 899 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 900 901 /** 902 * Mask to check if the scrollbar style is overlay or inset. 903 * {@hide} 904 */ 905 static final int SCROLLBARS_INSET_MASK = 0x01000000; 906 907 /** 908 * Mask to check if the scrollbar style is inside or outside. 909 * {@hide} 910 */ 911 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 912 913 /** 914 * Mask for scrollbar style. 915 * {@hide} 916 */ 917 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 918 919 /** 920 * View flag indicating that the screen should remain on while the 921 * window containing this view is visible to the user. This effectively 922 * takes care of automatically setting the WindowManager's 923 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 924 */ 925 public static final int KEEP_SCREEN_ON = 0x04000000; 926 927 /** 928 * View flag indicating whether this view should have sound effects enabled 929 * for events such as clicking and touching. 930 */ 931 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 932 933 /** 934 * View flag indicating whether this view should have haptic feedback 935 * enabled for events such as long presses. 936 */ 937 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 938 939 /** 940 * <p>Indicates that the view hierarchy should stop saving state when 941 * it reaches this view. If state saving is initiated immediately at 942 * the view, it will be allowed. 943 * {@hide} 944 */ 945 static final int PARENT_SAVE_DISABLED = 0x20000000; 946 947 /** 948 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 949 * {@hide} 950 */ 951 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 952 953 /** 954 * Horizontal direction of this view is from Left to Right. 955 * Use with {@link #setLayoutDirection}. 956 * {@hide} 957 */ 958 public static final int LAYOUT_DIRECTION_LTR = 0x00000000; 959 960 /** 961 * Horizontal direction of this view is from Right to Left. 962 * Use with {@link #setLayoutDirection}. 963 * {@hide} 964 */ 965 public static final int LAYOUT_DIRECTION_RTL = 0x40000000; 966 967 /** 968 * Horizontal direction of this view is inherited from its parent. 969 * Use with {@link #setLayoutDirection}. 970 * {@hide} 971 */ 972 public static final int LAYOUT_DIRECTION_INHERIT = 0x80000000; 973 974 /** 975 * Horizontal direction of this view is from deduced from the default language 976 * script for the locale. Use with {@link #setLayoutDirection}. 977 * {@hide} 978 */ 979 public static final int LAYOUT_DIRECTION_LOCALE = 0xC0000000; 980 981 /** 982 * Mask for use with setFlags indicating bits used for horizontalDirection. 983 * {@hide} 984 */ 985 static final int LAYOUT_DIRECTION_MASK = 0xC0000000; 986 987 /* 988 * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct 989 * flag value. 990 * {@hide} 991 */ 992 private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR, 993 LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE}; 994 995 /** 996 * Default horizontalDirection. 997 * {@hide} 998 */ 999 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 1000 1001 /** 1002 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1003 * should add all focusable Views regardless if they are focusable in touch mode. 1004 */ 1005 public static final int FOCUSABLES_ALL = 0x00000000; 1006 1007 /** 1008 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1009 * should add only Views focusable in touch mode. 1010 */ 1011 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1012 1013 /** 1014 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1015 * item. 1016 */ 1017 public static final int FOCUS_BACKWARD = 0x00000001; 1018 1019 /** 1020 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1021 * item. 1022 */ 1023 public static final int FOCUS_FORWARD = 0x00000002; 1024 1025 /** 1026 * Use with {@link #focusSearch(int)}. Move focus to the left. 1027 */ 1028 public static final int FOCUS_LEFT = 0x00000011; 1029 1030 /** 1031 * Use with {@link #focusSearch(int)}. Move focus up. 1032 */ 1033 public static final int FOCUS_UP = 0x00000021; 1034 1035 /** 1036 * Use with {@link #focusSearch(int)}. Move focus to the right. 1037 */ 1038 public static final int FOCUS_RIGHT = 0x00000042; 1039 1040 /** 1041 * Use with {@link #focusSearch(int)}. Move focus down. 1042 */ 1043 public static final int FOCUS_DOWN = 0x00000082; 1044 1045 /** 1046 * Bits of {@link #getMeasuredWidthAndState()} and 1047 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1048 */ 1049 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1050 1051 /** 1052 * Bits of {@link #getMeasuredWidthAndState()} and 1053 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1054 */ 1055 public static final int MEASURED_STATE_MASK = 0xff000000; 1056 1057 /** 1058 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1059 * for functions that combine both width and height into a single int, 1060 * such as {@link #getMeasuredState()} and the childState argument of 1061 * {@link #resolveSizeAndState(int, int, int)}. 1062 */ 1063 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1064 1065 /** 1066 * Bit of {@link #getMeasuredWidthAndState()} and 1067 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1068 * is smaller that the space the view would like to have. 1069 */ 1070 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1071 1072 /** 1073 * Base View state sets 1074 */ 1075 // Singles 1076 /** 1077 * Indicates the view has no states set. States are used with 1078 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1079 * view depending on its state. 1080 * 1081 * @see android.graphics.drawable.Drawable 1082 * @see #getDrawableState() 1083 */ 1084 protected static final int[] EMPTY_STATE_SET; 1085 /** 1086 * Indicates the view is enabled. States are used with 1087 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1088 * view depending on its state. 1089 * 1090 * @see android.graphics.drawable.Drawable 1091 * @see #getDrawableState() 1092 */ 1093 protected static final int[] ENABLED_STATE_SET; 1094 /** 1095 * Indicates the view is focused. States are used with 1096 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1097 * view depending on its state. 1098 * 1099 * @see android.graphics.drawable.Drawable 1100 * @see #getDrawableState() 1101 */ 1102 protected static final int[] FOCUSED_STATE_SET; 1103 /** 1104 * Indicates the view is selected. States are used with 1105 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1106 * view depending on its state. 1107 * 1108 * @see android.graphics.drawable.Drawable 1109 * @see #getDrawableState() 1110 */ 1111 protected static final int[] SELECTED_STATE_SET; 1112 /** 1113 * Indicates the view is pressed. States are used with 1114 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1115 * view depending on its state. 1116 * 1117 * @see android.graphics.drawable.Drawable 1118 * @see #getDrawableState() 1119 * @hide 1120 */ 1121 protected static final int[] PRESSED_STATE_SET; 1122 /** 1123 * Indicates the view's window has focus. States are used with 1124 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1125 * view depending on its state. 1126 * 1127 * @see android.graphics.drawable.Drawable 1128 * @see #getDrawableState() 1129 */ 1130 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1131 // Doubles 1132 /** 1133 * Indicates the view is enabled and has the focus. 1134 * 1135 * @see #ENABLED_STATE_SET 1136 * @see #FOCUSED_STATE_SET 1137 */ 1138 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1139 /** 1140 * Indicates the view is enabled and selected. 1141 * 1142 * @see #ENABLED_STATE_SET 1143 * @see #SELECTED_STATE_SET 1144 */ 1145 protected static final int[] ENABLED_SELECTED_STATE_SET; 1146 /** 1147 * Indicates the view is enabled and that its window has focus. 1148 * 1149 * @see #ENABLED_STATE_SET 1150 * @see #WINDOW_FOCUSED_STATE_SET 1151 */ 1152 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1153 /** 1154 * Indicates the view is focused and selected. 1155 * 1156 * @see #FOCUSED_STATE_SET 1157 * @see #SELECTED_STATE_SET 1158 */ 1159 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1160 /** 1161 * Indicates the view has the focus and that its window has the focus. 1162 * 1163 * @see #FOCUSED_STATE_SET 1164 * @see #WINDOW_FOCUSED_STATE_SET 1165 */ 1166 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1167 /** 1168 * Indicates the view is selected and that its window has the focus. 1169 * 1170 * @see #SELECTED_STATE_SET 1171 * @see #WINDOW_FOCUSED_STATE_SET 1172 */ 1173 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1174 // Triples 1175 /** 1176 * Indicates the view is enabled, focused and selected. 1177 * 1178 * @see #ENABLED_STATE_SET 1179 * @see #FOCUSED_STATE_SET 1180 * @see #SELECTED_STATE_SET 1181 */ 1182 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1183 /** 1184 * Indicates the view is enabled, focused and its window has the focus. 1185 * 1186 * @see #ENABLED_STATE_SET 1187 * @see #FOCUSED_STATE_SET 1188 * @see #WINDOW_FOCUSED_STATE_SET 1189 */ 1190 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1191 /** 1192 * Indicates the view is enabled, selected and its window has the focus. 1193 * 1194 * @see #ENABLED_STATE_SET 1195 * @see #SELECTED_STATE_SET 1196 * @see #WINDOW_FOCUSED_STATE_SET 1197 */ 1198 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1199 /** 1200 * Indicates the view is focused, selected and its window has the focus. 1201 * 1202 * @see #FOCUSED_STATE_SET 1203 * @see #SELECTED_STATE_SET 1204 * @see #WINDOW_FOCUSED_STATE_SET 1205 */ 1206 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1207 /** 1208 * Indicates the view is enabled, focused, selected and its window 1209 * has the focus. 1210 * 1211 * @see #ENABLED_STATE_SET 1212 * @see #FOCUSED_STATE_SET 1213 * @see #SELECTED_STATE_SET 1214 * @see #WINDOW_FOCUSED_STATE_SET 1215 */ 1216 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1217 /** 1218 * Indicates the view is pressed and its window has the focus. 1219 * 1220 * @see #PRESSED_STATE_SET 1221 * @see #WINDOW_FOCUSED_STATE_SET 1222 */ 1223 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1224 /** 1225 * Indicates the view is pressed and selected. 1226 * 1227 * @see #PRESSED_STATE_SET 1228 * @see #SELECTED_STATE_SET 1229 */ 1230 protected static final int[] PRESSED_SELECTED_STATE_SET; 1231 /** 1232 * Indicates the view is pressed, selected and its window has the focus. 1233 * 1234 * @see #PRESSED_STATE_SET 1235 * @see #SELECTED_STATE_SET 1236 * @see #WINDOW_FOCUSED_STATE_SET 1237 */ 1238 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1239 /** 1240 * Indicates the view is pressed and focused. 1241 * 1242 * @see #PRESSED_STATE_SET 1243 * @see #FOCUSED_STATE_SET 1244 */ 1245 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1246 /** 1247 * Indicates the view is pressed, focused and its window has the focus. 1248 * 1249 * @see #PRESSED_STATE_SET 1250 * @see #FOCUSED_STATE_SET 1251 * @see #WINDOW_FOCUSED_STATE_SET 1252 */ 1253 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1254 /** 1255 * Indicates the view is pressed, focused and selected. 1256 * 1257 * @see #PRESSED_STATE_SET 1258 * @see #SELECTED_STATE_SET 1259 * @see #FOCUSED_STATE_SET 1260 */ 1261 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1262 /** 1263 * Indicates the view is pressed, focused, selected and its window has the focus. 1264 * 1265 * @see #PRESSED_STATE_SET 1266 * @see #FOCUSED_STATE_SET 1267 * @see #SELECTED_STATE_SET 1268 * @see #WINDOW_FOCUSED_STATE_SET 1269 */ 1270 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1271 /** 1272 * Indicates the view is pressed and enabled. 1273 * 1274 * @see #PRESSED_STATE_SET 1275 * @see #ENABLED_STATE_SET 1276 */ 1277 protected static final int[] PRESSED_ENABLED_STATE_SET; 1278 /** 1279 * Indicates the view is pressed, enabled and its window has the focus. 1280 * 1281 * @see #PRESSED_STATE_SET 1282 * @see #ENABLED_STATE_SET 1283 * @see #WINDOW_FOCUSED_STATE_SET 1284 */ 1285 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1286 /** 1287 * Indicates the view is pressed, enabled and selected. 1288 * 1289 * @see #PRESSED_STATE_SET 1290 * @see #ENABLED_STATE_SET 1291 * @see #SELECTED_STATE_SET 1292 */ 1293 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1294 /** 1295 * Indicates the view is pressed, enabled, selected and its window has the 1296 * focus. 1297 * 1298 * @see #PRESSED_STATE_SET 1299 * @see #ENABLED_STATE_SET 1300 * @see #SELECTED_STATE_SET 1301 * @see #WINDOW_FOCUSED_STATE_SET 1302 */ 1303 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1304 /** 1305 * Indicates the view is pressed, enabled and focused. 1306 * 1307 * @see #PRESSED_STATE_SET 1308 * @see #ENABLED_STATE_SET 1309 * @see #FOCUSED_STATE_SET 1310 */ 1311 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1312 /** 1313 * Indicates the view is pressed, enabled, focused and its window has the 1314 * focus. 1315 * 1316 * @see #PRESSED_STATE_SET 1317 * @see #ENABLED_STATE_SET 1318 * @see #FOCUSED_STATE_SET 1319 * @see #WINDOW_FOCUSED_STATE_SET 1320 */ 1321 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1322 /** 1323 * Indicates the view is pressed, enabled, focused and selected. 1324 * 1325 * @see #PRESSED_STATE_SET 1326 * @see #ENABLED_STATE_SET 1327 * @see #SELECTED_STATE_SET 1328 * @see #FOCUSED_STATE_SET 1329 */ 1330 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1331 /** 1332 * Indicates the view is pressed, enabled, focused, selected and its window 1333 * has the focus. 1334 * 1335 * @see #PRESSED_STATE_SET 1336 * @see #ENABLED_STATE_SET 1337 * @see #SELECTED_STATE_SET 1338 * @see #FOCUSED_STATE_SET 1339 * @see #WINDOW_FOCUSED_STATE_SET 1340 */ 1341 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1342 1343 /** 1344 * The order here is very important to {@link #getDrawableState()} 1345 */ 1346 private static final int[][] VIEW_STATE_SETS; 1347 1348 static final int VIEW_STATE_WINDOW_FOCUSED = 1; 1349 static final int VIEW_STATE_SELECTED = 1 << 1; 1350 static final int VIEW_STATE_FOCUSED = 1 << 2; 1351 static final int VIEW_STATE_ENABLED = 1 << 3; 1352 static final int VIEW_STATE_PRESSED = 1 << 4; 1353 static final int VIEW_STATE_ACTIVATED = 1 << 5; 1354 static final int VIEW_STATE_ACCELERATED = 1 << 6; 1355 static final int VIEW_STATE_HOVERED = 1 << 7; 1356 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8; 1357 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9; 1358 1359 static final int[] VIEW_STATE_IDS = new int[] { 1360 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED, 1361 R.attr.state_selected, VIEW_STATE_SELECTED, 1362 R.attr.state_focused, VIEW_STATE_FOCUSED, 1363 R.attr.state_enabled, VIEW_STATE_ENABLED, 1364 R.attr.state_pressed, VIEW_STATE_PRESSED, 1365 R.attr.state_activated, VIEW_STATE_ACTIVATED, 1366 R.attr.state_accelerated, VIEW_STATE_ACCELERATED, 1367 R.attr.state_hovered, VIEW_STATE_HOVERED, 1368 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT, 1369 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED, 1370 }; 1371 1372 static { 1373 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) { 1374 throw new IllegalStateException( 1375 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array"); 1376 } 1377 int[] orderedIds = new int[VIEW_STATE_IDS.length]; 1378 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) { 1379 int viewState = R.styleable.ViewDrawableStates[i]; 1380 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) { 1381 if (VIEW_STATE_IDS[j] == viewState) { 1382 orderedIds[i * 2] = viewState; 1383 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1]; 1384 } 1385 } 1386 } 1387 final int NUM_BITS = VIEW_STATE_IDS.length / 2; 1388 VIEW_STATE_SETS = new int[1 << NUM_BITS][]; 1389 for (int i = 0; i < VIEW_STATE_SETS.length; i++) { 1390 int numBits = Integer.bitCount(i); 1391 int[] set = new int[numBits]; 1392 int pos = 0; 1393 for (int j = 0; j < orderedIds.length; j += 2) { 1394 if ((i & orderedIds[j+1]) != 0) { 1395 set[pos++] = orderedIds[j]; 1396 } 1397 } 1398 VIEW_STATE_SETS[i] = set; 1399 } 1400 1401 EMPTY_STATE_SET = VIEW_STATE_SETS[0]; 1402 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED]; 1403 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED]; 1404 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1405 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED]; 1406 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED]; 1407 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1408 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED]; 1409 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1410 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED]; 1411 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1412 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1413 | VIEW_STATE_FOCUSED]; 1414 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED]; 1415 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1416 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED]; 1417 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1418 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED]; 1419 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1420 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1421 | VIEW_STATE_ENABLED]; 1422 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1423 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED]; 1424 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1425 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1426 | VIEW_STATE_ENABLED]; 1427 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1428 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1429 | VIEW_STATE_ENABLED]; 1430 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1431 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1432 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED]; 1433 1434 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED]; 1435 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1436 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED]; 1437 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1438 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED]; 1439 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1440 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1441 | VIEW_STATE_PRESSED]; 1442 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1443 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1444 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1445 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1446 | VIEW_STATE_PRESSED]; 1447 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1448 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1449 | VIEW_STATE_PRESSED]; 1450 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1451 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1452 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED]; 1453 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[ 1454 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1455 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1456 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED 1457 | VIEW_STATE_PRESSED]; 1458 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1459 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED 1460 | VIEW_STATE_PRESSED]; 1461 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1462 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1463 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1464 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1465 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED 1466 | VIEW_STATE_PRESSED]; 1467 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1468 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED 1469 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1470 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[ 1471 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED 1472 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED]; 1473 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[ 1474 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED 1475 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED 1476 | VIEW_STATE_PRESSED]; 1477 } 1478 1479 /** 1480 * Accessibility event types that are dispatched for text population. 1481 */ 1482 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1483 AccessibilityEvent.TYPE_VIEW_CLICKED 1484 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1485 | AccessibilityEvent.TYPE_VIEW_SELECTED 1486 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1487 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1488 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1489 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT; 1490 1491 /** 1492 * Temporary Rect currently for use in setBackground(). This will probably 1493 * be extended in the future to hold our own class with more than just 1494 * a Rect. :) 1495 */ 1496 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1497 1498 /** 1499 * Map used to store views' tags. 1500 */ 1501 private SparseArray<Object> mKeyedTags; 1502 1503 /** 1504 * The next available accessiiblity id. 1505 */ 1506 private static int sNextAccessibilityViewId; 1507 1508 /** 1509 * The animation currently associated with this view. 1510 * @hide 1511 */ 1512 protected Animation mCurrentAnimation = null; 1513 1514 /** 1515 * Width as measured during measure pass. 1516 * {@hide} 1517 */ 1518 @ViewDebug.ExportedProperty(category = "measurement") 1519 int mMeasuredWidth; 1520 1521 /** 1522 * Height as measured during measure pass. 1523 * {@hide} 1524 */ 1525 @ViewDebug.ExportedProperty(category = "measurement") 1526 int mMeasuredHeight; 1527 1528 /** 1529 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1530 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1531 * its display list. This flag, used only when hw accelerated, allows us to clear the 1532 * flag while retaining this information until it's needed (at getDisplayList() time and 1533 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1534 * 1535 * {@hide} 1536 */ 1537 boolean mRecreateDisplayList = false; 1538 1539 /** 1540 * The view's identifier. 1541 * {@hide} 1542 * 1543 * @see #setId(int) 1544 * @see #getId() 1545 */ 1546 @ViewDebug.ExportedProperty(resolveId = true) 1547 int mID = NO_ID; 1548 1549 /** 1550 * The stable ID of this view for accessibility porposes. 1551 */ 1552 int mAccessibilityViewId = NO_ID; 1553 1554 /** 1555 * The view's tag. 1556 * {@hide} 1557 * 1558 * @see #setTag(Object) 1559 * @see #getTag() 1560 */ 1561 protected Object mTag; 1562 1563 // for mPrivateFlags: 1564 /** {@hide} */ 1565 static final int WANTS_FOCUS = 0x00000001; 1566 /** {@hide} */ 1567 static final int FOCUSED = 0x00000002; 1568 /** {@hide} */ 1569 static final int SELECTED = 0x00000004; 1570 /** {@hide} */ 1571 static final int IS_ROOT_NAMESPACE = 0x00000008; 1572 /** {@hide} */ 1573 static final int HAS_BOUNDS = 0x00000010; 1574 /** {@hide} */ 1575 static final int DRAWN = 0x00000020; 1576 /** 1577 * When this flag is set, this view is running an animation on behalf of its 1578 * children and should therefore not cancel invalidate requests, even if they 1579 * lie outside of this view's bounds. 1580 * 1581 * {@hide} 1582 */ 1583 static final int DRAW_ANIMATION = 0x00000040; 1584 /** {@hide} */ 1585 static final int SKIP_DRAW = 0x00000080; 1586 /** {@hide} */ 1587 static final int ONLY_DRAWS_BACKGROUND = 0x00000100; 1588 /** {@hide} */ 1589 static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1590 /** {@hide} */ 1591 static final int DRAWABLE_STATE_DIRTY = 0x00000400; 1592 /** {@hide} */ 1593 static final int MEASURED_DIMENSION_SET = 0x00000800; 1594 /** {@hide} */ 1595 static final int FORCE_LAYOUT = 0x00001000; 1596 /** {@hide} */ 1597 static final int LAYOUT_REQUIRED = 0x00002000; 1598 1599 private static final int PRESSED = 0x00004000; 1600 1601 /** {@hide} */ 1602 static final int DRAWING_CACHE_VALID = 0x00008000; 1603 /** 1604 * Flag used to indicate that this view should be drawn once more (and only once 1605 * more) after its animation has completed. 1606 * {@hide} 1607 */ 1608 static final int ANIMATION_STARTED = 0x00010000; 1609 1610 private static final int SAVE_STATE_CALLED = 0x00020000; 1611 1612 /** 1613 * Indicates that the View returned true when onSetAlpha() was called and that 1614 * the alpha must be restored. 1615 * {@hide} 1616 */ 1617 static final int ALPHA_SET = 0x00040000; 1618 1619 /** 1620 * Set by {@link #setScrollContainer(boolean)}. 1621 */ 1622 static final int SCROLL_CONTAINER = 0x00080000; 1623 1624 /** 1625 * Set by {@link #setScrollContainer(boolean)}. 1626 */ 1627 static final int SCROLL_CONTAINER_ADDED = 0x00100000; 1628 1629 /** 1630 * View flag indicating whether this view was invalidated (fully or partially.) 1631 * 1632 * @hide 1633 */ 1634 static final int DIRTY = 0x00200000; 1635 1636 /** 1637 * View flag indicating whether this view was invalidated by an opaque 1638 * invalidate request. 1639 * 1640 * @hide 1641 */ 1642 static final int DIRTY_OPAQUE = 0x00400000; 1643 1644 /** 1645 * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}. 1646 * 1647 * @hide 1648 */ 1649 static final int DIRTY_MASK = 0x00600000; 1650 1651 /** 1652 * Indicates whether the background is opaque. 1653 * 1654 * @hide 1655 */ 1656 static final int OPAQUE_BACKGROUND = 0x00800000; 1657 1658 /** 1659 * Indicates whether the scrollbars are opaque. 1660 * 1661 * @hide 1662 */ 1663 static final int OPAQUE_SCROLLBARS = 0x01000000; 1664 1665 /** 1666 * Indicates whether the view is opaque. 1667 * 1668 * @hide 1669 */ 1670 static final int OPAQUE_MASK = 0x01800000; 1671 1672 /** 1673 * Indicates a prepressed state; 1674 * the short time between ACTION_DOWN and recognizing 1675 * a 'real' press. Prepressed is used to recognize quick taps 1676 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1677 * 1678 * @hide 1679 */ 1680 private static final int PREPRESSED = 0x02000000; 1681 1682 /** 1683 * Indicates whether the view is temporarily detached. 1684 * 1685 * @hide 1686 */ 1687 static final int CANCEL_NEXT_UP_EVENT = 0x04000000; 1688 1689 /** 1690 * Indicates that we should awaken scroll bars once attached 1691 * 1692 * @hide 1693 */ 1694 private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1695 1696 /** 1697 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1698 * @hide 1699 */ 1700 private static final int HOVERED = 0x10000000; 1701 1702 /** 1703 * Indicates that pivotX or pivotY were explicitly set and we should not assume the center 1704 * for transform operations 1705 * 1706 * @hide 1707 */ 1708 private static final int PIVOT_EXPLICITLY_SET = 0x20000000; 1709 1710 /** {@hide} */ 1711 static final int ACTIVATED = 0x40000000; 1712 1713 /** 1714 * Indicates that this view was specifically invalidated, not just dirtied because some 1715 * child view was invalidated. The flag is used to determine when we need to recreate 1716 * a view's display list (as opposed to just returning a reference to its existing 1717 * display list). 1718 * 1719 * @hide 1720 */ 1721 static final int INVALIDATED = 0x80000000; 1722 1723 /* Masks for mPrivateFlags2 */ 1724 1725 /** 1726 * Indicates that this view has reported that it can accept the current drag's content. 1727 * Cleared when the drag operation concludes. 1728 * @hide 1729 */ 1730 static final int DRAG_CAN_ACCEPT = 0x00000001; 1731 1732 /** 1733 * Indicates that this view is currently directly under the drag location in a 1734 * drag-and-drop operation involving content that it can accept. Cleared when 1735 * the drag exits the view, or when the drag operation concludes. 1736 * @hide 1737 */ 1738 static final int DRAG_HOVERED = 0x00000002; 1739 1740 /** 1741 * Indicates whether the view layout direction has been resolved and drawn to the 1742 * right-to-left direction. 1743 * 1744 * @hide 1745 */ 1746 static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004; 1747 1748 /** 1749 * Indicates whether the view layout direction has been resolved. 1750 * 1751 * @hide 1752 */ 1753 static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008; 1754 1755 1756 /* End of masks for mPrivateFlags2 */ 1757 1758 static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED; 1759 1760 /** 1761 * Always allow a user to over-scroll this view, provided it is a 1762 * view that can scroll. 1763 * 1764 * @see #getOverScrollMode() 1765 * @see #setOverScrollMode(int) 1766 */ 1767 public static final int OVER_SCROLL_ALWAYS = 0; 1768 1769 /** 1770 * Allow a user to over-scroll this view only if the content is large 1771 * enough to meaningfully scroll, provided it is a view that can scroll. 1772 * 1773 * @see #getOverScrollMode() 1774 * @see #setOverScrollMode(int) 1775 */ 1776 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 1777 1778 /** 1779 * Never allow a user to over-scroll this view. 1780 * 1781 * @see #getOverScrollMode() 1782 * @see #setOverScrollMode(int) 1783 */ 1784 public static final int OVER_SCROLL_NEVER = 2; 1785 1786 /** 1787 * View has requested the system UI (status bar) to be visible (the default). 1788 * 1789 * @see #setSystemUiVisibility(int) 1790 */ 1791 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 1792 1793 /** 1794 * View has requested the system UI to enter an unobtrusive "low profile" mode. 1795 * 1796 * This is for use in games, book readers, video players, or any other "immersive" application 1797 * where the usual system chrome is deemed too distracting. 1798 * 1799 * In low profile mode, the status bar and/or navigation icons may dim. 1800 * 1801 * @see #setSystemUiVisibility(int) 1802 */ 1803 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 1804 1805 /** 1806 * View has requested that the system navigation be temporarily hidden. 1807 * 1808 * This is an even less obtrusive state than that called for by 1809 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 1810 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 1811 * those to disappear. This is useful (in conjunction with the 1812 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 1813 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 1814 * window flags) for displaying content using every last pixel on the display. 1815 * 1816 * There is a limitation: because navigation controls are so important, the least user 1817 * interaction will cause them to reappear immediately. 1818 * 1819 * @see #setSystemUiVisibility(int) 1820 */ 1821 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 1822 1823 /** 1824 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 1825 */ 1826 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 1827 1828 /** 1829 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 1830 */ 1831 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 1832 1833 /** 1834 * @hide 1835 * 1836 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1837 * out of the public fields to keep the undefined bits out of the developer's way. 1838 * 1839 * Flag to make the status bar not expandable. Unless you also 1840 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 1841 */ 1842 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 1843 1844 /** 1845 * @hide 1846 * 1847 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1848 * out of the public fields to keep the undefined bits out of the developer's way. 1849 * 1850 * Flag to hide notification icons and scrolling ticker text. 1851 */ 1852 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 1853 1854 /** 1855 * @hide 1856 * 1857 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1858 * out of the public fields to keep the undefined bits out of the developer's way. 1859 * 1860 * Flag to disable incoming notification alerts. This will not block 1861 * icons, but it will block sound, vibrating and other visual or aural notifications. 1862 */ 1863 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 1864 1865 /** 1866 * @hide 1867 * 1868 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1869 * out of the public fields to keep the undefined bits out of the developer's way. 1870 * 1871 * Flag to hide only the scrolling ticker. Note that 1872 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 1873 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 1874 */ 1875 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 1876 1877 /** 1878 * @hide 1879 * 1880 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1881 * out of the public fields to keep the undefined bits out of the developer's way. 1882 * 1883 * Flag to hide the center system info area. 1884 */ 1885 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 1886 1887 /** 1888 * @hide 1889 * 1890 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1891 * out of the public fields to keep the undefined bits out of the developer's way. 1892 * 1893 * Flag to hide only the navigation buttons. Don't use this 1894 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 1895 * 1896 * THIS DOES NOT DISABLE THE BACK BUTTON 1897 */ 1898 public static final int STATUS_BAR_DISABLE_NAVIGATION = 0x00200000; 1899 1900 /** 1901 * @hide 1902 * 1903 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1904 * out of the public fields to keep the undefined bits out of the developer's way. 1905 * 1906 * Flag to hide only the back button. Don't use this 1907 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 1908 */ 1909 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 1910 1911 /** 1912 * @hide 1913 * 1914 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 1915 * out of the public fields to keep the undefined bits out of the developer's way. 1916 * 1917 * Flag to hide only the clock. You might use this if your activity has 1918 * its own clock making the status bar's clock redundant. 1919 */ 1920 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 1921 1922 /** 1923 * @hide 1924 */ 1925 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF; 1926 1927 /** 1928 * These are the system UI flags that can be cleared by events outside 1929 * of an application. Currently this is just the ability to tap on the 1930 * screen while hiding the navigation bar to have it return. 1931 * @hide 1932 */ 1933 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 1934 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION; 1935 1936 /** 1937 * Find views that render the specified text. 1938 * 1939 * @see #findViewsWithText(ArrayList, CharSequence, int) 1940 */ 1941 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 1942 1943 /** 1944 * Find find views that contain the specified content description. 1945 * 1946 * @see #findViewsWithText(ArrayList, CharSequence, int) 1947 */ 1948 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 1949 1950 /** 1951 * Controls the over-scroll mode for this view. 1952 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 1953 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 1954 * and {@link #OVER_SCROLL_NEVER}. 1955 */ 1956 private int mOverScrollMode; 1957 1958 /** 1959 * The parent this view is attached to. 1960 * {@hide} 1961 * 1962 * @see #getParent() 1963 */ 1964 protected ViewParent mParent; 1965 1966 /** 1967 * {@hide} 1968 */ 1969 AttachInfo mAttachInfo; 1970 1971 /** 1972 * {@hide} 1973 */ 1974 @ViewDebug.ExportedProperty(flagMapping = { 1975 @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT, 1976 name = "FORCE_LAYOUT"), 1977 @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED, 1978 name = "LAYOUT_REQUIRED"), 1979 @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID, 1980 name = "DRAWING_CACHE_INVALID", outputIf = false), 1981 @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true), 1982 @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false), 1983 @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 1984 @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY") 1985 }) 1986 int mPrivateFlags; 1987 int mPrivateFlags2; 1988 1989 /** 1990 * This view's request for the visibility of the status bar. 1991 * @hide 1992 */ 1993 @ViewDebug.ExportedProperty(flagMapping = { 1994 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 1995 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 1996 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 1997 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 1998 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 1999 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 2000 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 2001 equals = SYSTEM_UI_FLAG_VISIBLE, 2002 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 2003 }) 2004 int mSystemUiVisibility; 2005 2006 /** 2007 * Count of how many windows this view has been attached to. 2008 */ 2009 int mWindowAttachCount; 2010 2011 /** 2012 * The layout parameters associated with this view and used by the parent 2013 * {@link android.view.ViewGroup} to determine how this view should be 2014 * laid out. 2015 * {@hide} 2016 */ 2017 protected ViewGroup.LayoutParams mLayoutParams; 2018 2019 /** 2020 * The view flags hold various views states. 2021 * {@hide} 2022 */ 2023 @ViewDebug.ExportedProperty 2024 int mViewFlags; 2025 2026 static class TransformationInfo { 2027 /** 2028 * The transform matrix for the View. This transform is calculated internally 2029 * based on the rotation, scaleX, and scaleY properties. The identity matrix 2030 * is used by default. Do *not* use this variable directly; instead call 2031 * getMatrix(), which will automatically recalculate the matrix if necessary 2032 * to get the correct matrix based on the latest rotation and scale properties. 2033 */ 2034 private final Matrix mMatrix = new Matrix(); 2035 2036 /** 2037 * The transform matrix for the View. This transform is calculated internally 2038 * based on the rotation, scaleX, and scaleY properties. The identity matrix 2039 * is used by default. Do *not* use this variable directly; instead call 2040 * getInverseMatrix(), which will automatically recalculate the matrix if necessary 2041 * to get the correct matrix based on the latest rotation and scale properties. 2042 */ 2043 private Matrix mInverseMatrix; 2044 2045 /** 2046 * An internal variable that tracks whether we need to recalculate the 2047 * transform matrix, based on whether the rotation or scaleX/Y properties 2048 * have changed since the matrix was last calculated. 2049 */ 2050 boolean mMatrixDirty = false; 2051 2052 /** 2053 * An internal variable that tracks whether we need to recalculate the 2054 * transform matrix, based on whether the rotation or scaleX/Y properties 2055 * have changed since the matrix was last calculated. 2056 */ 2057 private boolean mInverseMatrixDirty = true; 2058 2059 /** 2060 * A variable that tracks whether we need to recalculate the 2061 * transform matrix, based on whether the rotation or scaleX/Y properties 2062 * have changed since the matrix was last calculated. This variable 2063 * is only valid after a call to updateMatrix() or to a function that 2064 * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix(). 2065 */ 2066 private boolean mMatrixIsIdentity = true; 2067 2068 /** 2069 * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set. 2070 */ 2071 private Camera mCamera = null; 2072 2073 /** 2074 * This matrix is used when computing the matrix for 3D rotations. 2075 */ 2076 private Matrix matrix3D = null; 2077 2078 /** 2079 * These prev values are used to recalculate a centered pivot point when necessary. The 2080 * pivot point is only used in matrix operations (when rotation, scale, or translation are 2081 * set), so thes values are only used then as well. 2082 */ 2083 private int mPrevWidth = -1; 2084 private int mPrevHeight = -1; 2085 2086 /** 2087 * The degrees rotation around the vertical axis through the pivot point. 2088 */ 2089 @ViewDebug.ExportedProperty 2090 float mRotationY = 0f; 2091 2092 /** 2093 * The degrees rotation around the horizontal axis through the pivot point. 2094 */ 2095 @ViewDebug.ExportedProperty 2096 float mRotationX = 0f; 2097 2098 /** 2099 * The degrees rotation around the pivot point. 2100 */ 2101 @ViewDebug.ExportedProperty 2102 float mRotation = 0f; 2103 2104 /** 2105 * The amount of translation of the object away from its left property (post-layout). 2106 */ 2107 @ViewDebug.ExportedProperty 2108 float mTranslationX = 0f; 2109 2110 /** 2111 * The amount of translation of the object away from its top property (post-layout). 2112 */ 2113 @ViewDebug.ExportedProperty 2114 float mTranslationY = 0f; 2115 2116 /** 2117 * The amount of scale in the x direction around the pivot point. A 2118 * value of 1 means no scaling is applied. 2119 */ 2120 @ViewDebug.ExportedProperty 2121 float mScaleX = 1f; 2122 2123 /** 2124 * The amount of scale in the y direction around the pivot point. A 2125 * value of 1 means no scaling is applied. 2126 */ 2127 @ViewDebug.ExportedProperty 2128 float mScaleY = 1f; 2129 2130 /** 2131 * The amount of scale in the x direction around the pivot point. A 2132 * value of 1 means no scaling is applied. 2133 */ 2134 @ViewDebug.ExportedProperty 2135 float mPivotX = 0f; 2136 2137 /** 2138 * The amount of scale in the y direction around the pivot point. A 2139 * value of 1 means no scaling is applied. 2140 */ 2141 @ViewDebug.ExportedProperty 2142 float mPivotY = 0f; 2143 2144 /** 2145 * The opacity of the View. This is a value from 0 to 1, where 0 means 2146 * completely transparent and 1 means completely opaque. 2147 */ 2148 @ViewDebug.ExportedProperty 2149 float mAlpha = 1f; 2150 } 2151 2152 TransformationInfo mTransformationInfo; 2153 2154 private boolean mLastIsOpaque; 2155 2156 /** 2157 * Convenience value to check for float values that are close enough to zero to be considered 2158 * zero. 2159 */ 2160 private static final float NONZERO_EPSILON = .001f; 2161 2162 /** 2163 * The distance in pixels from the left edge of this view's parent 2164 * to the left edge of this view. 2165 * {@hide} 2166 */ 2167 @ViewDebug.ExportedProperty(category = "layout") 2168 protected int mLeft; 2169 /** 2170 * The distance in pixels from the left edge of this view's parent 2171 * to the right edge of this view. 2172 * {@hide} 2173 */ 2174 @ViewDebug.ExportedProperty(category = "layout") 2175 protected int mRight; 2176 /** 2177 * The distance in pixels from the top edge of this view's parent 2178 * to the top edge of this view. 2179 * {@hide} 2180 */ 2181 @ViewDebug.ExportedProperty(category = "layout") 2182 protected int mTop; 2183 /** 2184 * The distance in pixels from the top edge of this view's parent 2185 * to the bottom edge of this view. 2186 * {@hide} 2187 */ 2188 @ViewDebug.ExportedProperty(category = "layout") 2189 protected int mBottom; 2190 2191 /** 2192 * The offset, in pixels, by which the content of this view is scrolled 2193 * horizontally. 2194 * {@hide} 2195 */ 2196 @ViewDebug.ExportedProperty(category = "scrolling") 2197 protected int mScrollX; 2198 /** 2199 * The offset, in pixels, by which the content of this view is scrolled 2200 * vertically. 2201 * {@hide} 2202 */ 2203 @ViewDebug.ExportedProperty(category = "scrolling") 2204 protected int mScrollY; 2205 2206 /** 2207 * The left padding in pixels, that is the distance in pixels between the 2208 * left edge of this view and the left edge of its content. 2209 * {@hide} 2210 */ 2211 @ViewDebug.ExportedProperty(category = "padding") 2212 protected int mPaddingLeft; 2213 /** 2214 * The right padding in pixels, that is the distance in pixels between the 2215 * right edge of this view and the right edge of its content. 2216 * {@hide} 2217 */ 2218 @ViewDebug.ExportedProperty(category = "padding") 2219 protected int mPaddingRight; 2220 /** 2221 * The top padding in pixels, that is the distance in pixels between the 2222 * top edge of this view and the top edge of its content. 2223 * {@hide} 2224 */ 2225 @ViewDebug.ExportedProperty(category = "padding") 2226 protected int mPaddingTop; 2227 /** 2228 * The bottom padding in pixels, that is the distance in pixels between the 2229 * bottom edge of this view and the bottom edge of its content. 2230 * {@hide} 2231 */ 2232 @ViewDebug.ExportedProperty(category = "padding") 2233 protected int mPaddingBottom; 2234 2235 /** 2236 * Briefly describes the view and is primarily used for accessibility support. 2237 */ 2238 private CharSequence mContentDescription; 2239 2240 /** 2241 * Cache the paddingRight set by the user to append to the scrollbar's size. 2242 * 2243 * @hide 2244 */ 2245 @ViewDebug.ExportedProperty(category = "padding") 2246 protected int mUserPaddingRight; 2247 2248 /** 2249 * Cache the paddingBottom set by the user to append to the scrollbar's size. 2250 * 2251 * @hide 2252 */ 2253 @ViewDebug.ExportedProperty(category = "padding") 2254 protected int mUserPaddingBottom; 2255 2256 /** 2257 * Cache the paddingLeft set by the user to append to the scrollbar's size. 2258 * 2259 * @hide 2260 */ 2261 @ViewDebug.ExportedProperty(category = "padding") 2262 protected int mUserPaddingLeft; 2263 2264 /** 2265 * Cache if the user padding is relative. 2266 * 2267 */ 2268 @ViewDebug.ExportedProperty(category = "padding") 2269 boolean mUserPaddingRelative; 2270 2271 /** 2272 * Cache the paddingStart set by the user to append to the scrollbar's size. 2273 * 2274 */ 2275 @ViewDebug.ExportedProperty(category = "padding") 2276 int mUserPaddingStart; 2277 2278 /** 2279 * Cache the paddingEnd set by the user to append to the scrollbar's size. 2280 * 2281 */ 2282 @ViewDebug.ExportedProperty(category = "padding") 2283 int mUserPaddingEnd; 2284 2285 /** 2286 * @hide 2287 */ 2288 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 2289 /** 2290 * @hide 2291 */ 2292 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 2293 2294 private Drawable mBGDrawable; 2295 2296 private int mBackgroundResource; 2297 private boolean mBackgroundSizeChanged; 2298 2299 /** 2300 * Listener used to dispatch focus change events. 2301 * This field should be made private, so it is hidden from the SDK. 2302 * {@hide} 2303 */ 2304 protected OnFocusChangeListener mOnFocusChangeListener; 2305 2306 /** 2307 * Listeners for layout change events. 2308 */ 2309 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 2310 2311 /** 2312 * Listeners for attach events. 2313 */ 2314 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 2315 2316 /** 2317 * Listener used to dispatch click events. 2318 * This field should be made private, so it is hidden from the SDK. 2319 * {@hide} 2320 */ 2321 protected OnClickListener mOnClickListener; 2322 2323 /** 2324 * Listener used to dispatch long click events. 2325 * This field should be made private, so it is hidden from the SDK. 2326 * {@hide} 2327 */ 2328 protected OnLongClickListener mOnLongClickListener; 2329 2330 /** 2331 * Listener used to build the context menu. 2332 * This field should be made private, so it is hidden from the SDK. 2333 * {@hide} 2334 */ 2335 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 2336 2337 private OnKeyListener mOnKeyListener; 2338 2339 private OnTouchListener mOnTouchListener; 2340 2341 private OnHoverListener mOnHoverListener; 2342 2343 private OnGenericMotionListener mOnGenericMotionListener; 2344 2345 private OnDragListener mOnDragListener; 2346 2347 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 2348 2349 /** 2350 * The application environment this view lives in. 2351 * This field should be made private, so it is hidden from the SDK. 2352 * {@hide} 2353 */ 2354 protected Context mContext; 2355 2356 private final Resources mResources; 2357 2358 private ScrollabilityCache mScrollCache; 2359 2360 private int[] mDrawableState = null; 2361 2362 /** 2363 * Set to true when drawing cache is enabled and cannot be created. 2364 * 2365 * @hide 2366 */ 2367 public boolean mCachingFailed; 2368 2369 private Bitmap mDrawingCache; 2370 private Bitmap mUnscaledDrawingCache; 2371 private HardwareLayer mHardwareLayer; 2372 DisplayList mDisplayList; 2373 2374 /** 2375 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 2376 * the user may specify which view to go to next. 2377 */ 2378 private int mNextFocusLeftId = View.NO_ID; 2379 2380 /** 2381 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 2382 * the user may specify which view to go to next. 2383 */ 2384 private int mNextFocusRightId = View.NO_ID; 2385 2386 /** 2387 * When this view has focus and the next focus is {@link #FOCUS_UP}, 2388 * the user may specify which view to go to next. 2389 */ 2390 private int mNextFocusUpId = View.NO_ID; 2391 2392 /** 2393 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 2394 * the user may specify which view to go to next. 2395 */ 2396 private int mNextFocusDownId = View.NO_ID; 2397 2398 /** 2399 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 2400 * the user may specify which view to go to next. 2401 */ 2402 int mNextFocusForwardId = View.NO_ID; 2403 2404 private CheckForLongPress mPendingCheckForLongPress; 2405 private CheckForTap mPendingCheckForTap = null; 2406 private PerformClick mPerformClick; 2407 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 2408 2409 private UnsetPressedState mUnsetPressedState; 2410 2411 /** 2412 * Whether the long press's action has been invoked. The tap's action is invoked on the 2413 * up event while a long press is invoked as soon as the long press duration is reached, so 2414 * a long press could be performed before the tap is checked, in which case the tap's action 2415 * should not be invoked. 2416 */ 2417 private boolean mHasPerformedLongPress; 2418 2419 /** 2420 * The minimum height of the view. We'll try our best to have the height 2421 * of this view to at least this amount. 2422 */ 2423 @ViewDebug.ExportedProperty(category = "measurement") 2424 private int mMinHeight; 2425 2426 /** 2427 * The minimum width of the view. We'll try our best to have the width 2428 * of this view to at least this amount. 2429 */ 2430 @ViewDebug.ExportedProperty(category = "measurement") 2431 private int mMinWidth; 2432 2433 /** 2434 * The delegate to handle touch events that are physically in this view 2435 * but should be handled by another view. 2436 */ 2437 private TouchDelegate mTouchDelegate = null; 2438 2439 /** 2440 * Solid color to use as a background when creating the drawing cache. Enables 2441 * the cache to use 16 bit bitmaps instead of 32 bit. 2442 */ 2443 private int mDrawingCacheBackgroundColor = 0; 2444 2445 /** 2446 * Special tree observer used when mAttachInfo is null. 2447 */ 2448 private ViewTreeObserver mFloatingTreeObserver; 2449 2450 /** 2451 * Cache the touch slop from the context that created the view. 2452 */ 2453 private int mTouchSlop; 2454 2455 /** 2456 * Object that handles automatic animation of view properties. 2457 */ 2458 private ViewPropertyAnimator mAnimator = null; 2459 2460 /** 2461 * Flag indicating that a drag can cross window boundaries. When 2462 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called 2463 * with this flag set, all visible applications will be able to participate 2464 * in the drag operation and receive the dragged content. 2465 * 2466 * @hide 2467 */ 2468 public static final int DRAG_FLAG_GLOBAL = 1; 2469 2470 /** 2471 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 2472 */ 2473 private float mVerticalScrollFactor; 2474 2475 /** 2476 * Position of the vertical scroll bar. 2477 */ 2478 private int mVerticalScrollbarPosition; 2479 2480 /** 2481 * Position the scroll bar at the default position as determined by the system. 2482 */ 2483 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 2484 2485 /** 2486 * Position the scroll bar along the left edge. 2487 */ 2488 public static final int SCROLLBAR_POSITION_LEFT = 1; 2489 2490 /** 2491 * Position the scroll bar along the right edge. 2492 */ 2493 public static final int SCROLLBAR_POSITION_RIGHT = 2; 2494 2495 /** 2496 * Indicates that the view does not have a layer. 2497 * 2498 * @see #getLayerType() 2499 * @see #setLayerType(int, android.graphics.Paint) 2500 * @see #LAYER_TYPE_SOFTWARE 2501 * @see #LAYER_TYPE_HARDWARE 2502 */ 2503 public static final int LAYER_TYPE_NONE = 0; 2504 2505 /** 2506 * <p>Indicates that the view has a software layer. A software layer is backed 2507 * by a bitmap and causes the view to be rendered using Android's software 2508 * rendering pipeline, even if hardware acceleration is enabled.</p> 2509 * 2510 * <p>Software layers have various usages:</p> 2511 * <p>When the application is not using hardware acceleration, a software layer 2512 * is useful to apply a specific color filter and/or blending mode and/or 2513 * translucency to a view and all its children.</p> 2514 * <p>When the application is using hardware acceleration, a software layer 2515 * is useful to render drawing primitives not supported by the hardware 2516 * accelerated pipeline. It can also be used to cache a complex view tree 2517 * into a texture and reduce the complexity of drawing operations. For instance, 2518 * when animating a complex view tree with a translation, a software layer can 2519 * be used to render the view tree only once.</p> 2520 * <p>Software layers should be avoided when the affected view tree updates 2521 * often. Every update will require to re-render the software layer, which can 2522 * potentially be slow (particularly when hardware acceleration is turned on 2523 * since the layer will have to be uploaded into a hardware texture after every 2524 * update.)</p> 2525 * 2526 * @see #getLayerType() 2527 * @see #setLayerType(int, android.graphics.Paint) 2528 * @see #LAYER_TYPE_NONE 2529 * @see #LAYER_TYPE_HARDWARE 2530 */ 2531 public static final int LAYER_TYPE_SOFTWARE = 1; 2532 2533 /** 2534 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 2535 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 2536 * OpenGL hardware) and causes the view to be rendered using Android's hardware 2537 * rendering pipeline, but only if hardware acceleration is turned on for the 2538 * view hierarchy. When hardware acceleration is turned off, hardware layers 2539 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 2540 * 2541 * <p>A hardware layer is useful to apply a specific color filter and/or 2542 * blending mode and/or translucency to a view and all its children.</p> 2543 * <p>A hardware layer can be used to cache a complex view tree into a 2544 * texture and reduce the complexity of drawing operations. For instance, 2545 * when animating a complex view tree with a translation, a hardware layer can 2546 * be used to render the view tree only once.</p> 2547 * <p>A hardware layer can also be used to increase the rendering quality when 2548 * rotation transformations are applied on a view. It can also be used to 2549 * prevent potential clipping issues when applying 3D transforms on a view.</p> 2550 * 2551 * @see #getLayerType() 2552 * @see #setLayerType(int, android.graphics.Paint) 2553 * @see #LAYER_TYPE_NONE 2554 * @see #LAYER_TYPE_SOFTWARE 2555 */ 2556 public static final int LAYER_TYPE_HARDWARE = 2; 2557 2558 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 2559 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 2560 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 2561 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 2562 }) 2563 int mLayerType = LAYER_TYPE_NONE; 2564 Paint mLayerPaint; 2565 Rect mLocalDirtyRect; 2566 2567 /** 2568 * Set to true when the view is sending hover accessibility events because it 2569 * is the innermost hovered view. 2570 */ 2571 private boolean mSendingHoverAccessibilityEvents; 2572 2573 /** 2574 * Delegate for injecting accessiblity functionality. 2575 */ 2576 AccessibilityDelegate mAccessibilityDelegate; 2577 2578 /** 2579 * Text direction is inherited thru {@link ViewGroup} 2580 * @hide 2581 */ 2582 public static final int TEXT_DIRECTION_INHERIT = 0; 2583 2584 /** 2585 * Text direction is using "first strong algorithm". The first strong directional character 2586 * determines the paragraph direction. If there is no strong directional character, the 2587 * paragraph direction is the view's resolved ayout direction. 2588 * 2589 * @hide 2590 */ 2591 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 2592 2593 /** 2594 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 2595 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 2596 * If there are neither, the paragraph direction is the view's resolved layout direction. 2597 * 2598 * @hide 2599 */ 2600 public static final int TEXT_DIRECTION_ANY_RTL = 2; 2601 2602 /** 2603 * Text direction is forced to LTR. 2604 * 2605 * @hide 2606 */ 2607 public static final int TEXT_DIRECTION_LTR = 3; 2608 2609 /** 2610 * Text direction is forced to RTL. 2611 * 2612 * @hide 2613 */ 2614 public static final int TEXT_DIRECTION_RTL = 4; 2615 2616 /** 2617 * Default text direction is inherited 2618 * 2619 * @hide 2620 */ 2621 protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT; 2622 2623 /** 2624 * The text direction that has been defined by {@link #setTextDirection(int)}. 2625 * 2626 * {@hide} 2627 */ 2628 @ViewDebug.ExportedProperty(category = "text", mapping = { 2629 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 2630 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 2631 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 2632 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 2633 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL") 2634 }) 2635 private int mTextDirection = DEFAULT_TEXT_DIRECTION; 2636 2637 /** 2638 * The resolved text direction. This needs resolution if the value is 2639 * TEXT_DIRECTION_INHERIT. The resolution matches mTextDirection if that is 2640 * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent 2641 * chain of the view. 2642 * 2643 * {@hide} 2644 */ 2645 @ViewDebug.ExportedProperty(category = "text", mapping = { 2646 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 2647 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 2648 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 2649 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 2650 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL") 2651 }) 2652 private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT; 2653 2654 /** 2655 * Consistency verifier for debugging purposes. 2656 * @hide 2657 */ 2658 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 2659 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 2660 new InputEventConsistencyVerifier(this, 0) : null; 2661 2662 /** 2663 * Simple constructor to use when creating a view from code. 2664 * 2665 * @param context The Context the view is running in, through which it can 2666 * access the current theme, resources, etc. 2667 */ 2668 public View(Context context) { 2669 mContext = context; 2670 mResources = context != null ? context.getResources() : null; 2671 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT; 2672 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 2673 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 2674 mUserPaddingStart = -1; 2675 mUserPaddingEnd = -1; 2676 mUserPaddingRelative = false; 2677 } 2678 2679 /** 2680 * Constructor that is called when inflating a view from XML. This is called 2681 * when a view is being constructed from an XML file, supplying attributes 2682 * that were specified in the XML file. This version uses a default style of 2683 * 0, so the only attribute values applied are those in the Context's Theme 2684 * and the given AttributeSet. 2685 * 2686 * <p> 2687 * The method onFinishInflate() will be called after all children have been 2688 * added. 2689 * 2690 * @param context The Context the view is running in, through which it can 2691 * access the current theme, resources, etc. 2692 * @param attrs The attributes of the XML tag that is inflating the view. 2693 * @see #View(Context, AttributeSet, int) 2694 */ 2695 public View(Context context, AttributeSet attrs) { 2696 this(context, attrs, 0); 2697 } 2698 2699 /** 2700 * Perform inflation from XML and apply a class-specific base style. This 2701 * constructor of View allows subclasses to use their own base style when 2702 * they are inflating. For example, a Button class's constructor would call 2703 * this version of the super class constructor and supply 2704 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows 2705 * the theme's button style to modify all of the base view attributes (in 2706 * particular its background) as well as the Button class's attributes. 2707 * 2708 * @param context The Context the view is running in, through which it can 2709 * access the current theme, resources, etc. 2710 * @param attrs The attributes of the XML tag that is inflating the view. 2711 * @param defStyle The default style to apply to this view. If 0, no style 2712 * will be applied (beyond what is included in the theme). This may 2713 * either be an attribute resource, whose value will be retrieved 2714 * from the current theme, or an explicit style resource. 2715 * @see #View(Context, AttributeSet) 2716 */ 2717 public View(Context context, AttributeSet attrs, int defStyle) { 2718 this(context); 2719 2720 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, 2721 defStyle, 0); 2722 2723 Drawable background = null; 2724 2725 int leftPadding = -1; 2726 int topPadding = -1; 2727 int rightPadding = -1; 2728 int bottomPadding = -1; 2729 int startPadding = -1; 2730 int endPadding = -1; 2731 2732 int padding = -1; 2733 2734 int viewFlagValues = 0; 2735 int viewFlagMasks = 0; 2736 2737 boolean setScrollContainer = false; 2738 2739 int x = 0; 2740 int y = 0; 2741 2742 float tx = 0; 2743 float ty = 0; 2744 float rotation = 0; 2745 float rotationX = 0; 2746 float rotationY = 0; 2747 float sx = 1f; 2748 float sy = 1f; 2749 boolean transformSet = false; 2750 2751 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 2752 2753 int overScrollMode = mOverScrollMode; 2754 final int N = a.getIndexCount(); 2755 for (int i = 0; i < N; i++) { 2756 int attr = a.getIndex(i); 2757 switch (attr) { 2758 case com.android.internal.R.styleable.View_background: 2759 background = a.getDrawable(attr); 2760 break; 2761 case com.android.internal.R.styleable.View_padding: 2762 padding = a.getDimensionPixelSize(attr, -1); 2763 break; 2764 case com.android.internal.R.styleable.View_paddingLeft: 2765 leftPadding = a.getDimensionPixelSize(attr, -1); 2766 break; 2767 case com.android.internal.R.styleable.View_paddingTop: 2768 topPadding = a.getDimensionPixelSize(attr, -1); 2769 break; 2770 case com.android.internal.R.styleable.View_paddingRight: 2771 rightPadding = a.getDimensionPixelSize(attr, -1); 2772 break; 2773 case com.android.internal.R.styleable.View_paddingBottom: 2774 bottomPadding = a.getDimensionPixelSize(attr, -1); 2775 break; 2776 case com.android.internal.R.styleable.View_paddingStart: 2777 startPadding = a.getDimensionPixelSize(attr, -1); 2778 break; 2779 case com.android.internal.R.styleable.View_paddingEnd: 2780 endPadding = a.getDimensionPixelSize(attr, -1); 2781 break; 2782 case com.android.internal.R.styleable.View_scrollX: 2783 x = a.getDimensionPixelOffset(attr, 0); 2784 break; 2785 case com.android.internal.R.styleable.View_scrollY: 2786 y = a.getDimensionPixelOffset(attr, 0); 2787 break; 2788 case com.android.internal.R.styleable.View_alpha: 2789 setAlpha(a.getFloat(attr, 1f)); 2790 break; 2791 case com.android.internal.R.styleable.View_transformPivotX: 2792 setPivotX(a.getDimensionPixelOffset(attr, 0)); 2793 break; 2794 case com.android.internal.R.styleable.View_transformPivotY: 2795 setPivotY(a.getDimensionPixelOffset(attr, 0)); 2796 break; 2797 case com.android.internal.R.styleable.View_translationX: 2798 tx = a.getDimensionPixelOffset(attr, 0); 2799 transformSet = true; 2800 break; 2801 case com.android.internal.R.styleable.View_translationY: 2802 ty = a.getDimensionPixelOffset(attr, 0); 2803 transformSet = true; 2804 break; 2805 case com.android.internal.R.styleable.View_rotation: 2806 rotation = a.getFloat(attr, 0); 2807 transformSet = true; 2808 break; 2809 case com.android.internal.R.styleable.View_rotationX: 2810 rotationX = a.getFloat(attr, 0); 2811 transformSet = true; 2812 break; 2813 case com.android.internal.R.styleable.View_rotationY: 2814 rotationY = a.getFloat(attr, 0); 2815 transformSet = true; 2816 break; 2817 case com.android.internal.R.styleable.View_scaleX: 2818 sx = a.getFloat(attr, 1f); 2819 transformSet = true; 2820 break; 2821 case com.android.internal.R.styleable.View_scaleY: 2822 sy = a.getFloat(attr, 1f); 2823 transformSet = true; 2824 break; 2825 case com.android.internal.R.styleable.View_id: 2826 mID = a.getResourceId(attr, NO_ID); 2827 break; 2828 case com.android.internal.R.styleable.View_tag: 2829 mTag = a.getText(attr); 2830 break; 2831 case com.android.internal.R.styleable.View_fitsSystemWindows: 2832 if (a.getBoolean(attr, false)) { 2833 viewFlagValues |= FITS_SYSTEM_WINDOWS; 2834 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 2835 } 2836 break; 2837 case com.android.internal.R.styleable.View_focusable: 2838 if (a.getBoolean(attr, false)) { 2839 viewFlagValues |= FOCUSABLE; 2840 viewFlagMasks |= FOCUSABLE_MASK; 2841 } 2842 break; 2843 case com.android.internal.R.styleable.View_focusableInTouchMode: 2844 if (a.getBoolean(attr, false)) { 2845 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 2846 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 2847 } 2848 break; 2849 case com.android.internal.R.styleable.View_clickable: 2850 if (a.getBoolean(attr, false)) { 2851 viewFlagValues |= CLICKABLE; 2852 viewFlagMasks |= CLICKABLE; 2853 } 2854 break; 2855 case com.android.internal.R.styleable.View_longClickable: 2856 if (a.getBoolean(attr, false)) { 2857 viewFlagValues |= LONG_CLICKABLE; 2858 viewFlagMasks |= LONG_CLICKABLE; 2859 } 2860 break; 2861 case com.android.internal.R.styleable.View_saveEnabled: 2862 if (!a.getBoolean(attr, true)) { 2863 viewFlagValues |= SAVE_DISABLED; 2864 viewFlagMasks |= SAVE_DISABLED_MASK; 2865 } 2866 break; 2867 case com.android.internal.R.styleable.View_duplicateParentState: 2868 if (a.getBoolean(attr, false)) { 2869 viewFlagValues |= DUPLICATE_PARENT_STATE; 2870 viewFlagMasks |= DUPLICATE_PARENT_STATE; 2871 } 2872 break; 2873 case com.android.internal.R.styleable.View_visibility: 2874 final int visibility = a.getInt(attr, 0); 2875 if (visibility != 0) { 2876 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 2877 viewFlagMasks |= VISIBILITY_MASK; 2878 } 2879 break; 2880 case com.android.internal.R.styleable.View_layoutDirection: 2881 // Clear any HORIZONTAL_DIRECTION flag already set 2882 viewFlagValues &= ~LAYOUT_DIRECTION_MASK; 2883 // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute 2884 final int layoutDirection = a.getInt(attr, -1); 2885 if (layoutDirection != -1) { 2886 viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection]; 2887 } else { 2888 // Set to default (LAYOUT_DIRECTION_INHERIT) 2889 viewFlagValues |= LAYOUT_DIRECTION_DEFAULT; 2890 } 2891 viewFlagMasks |= LAYOUT_DIRECTION_MASK; 2892 break; 2893 case com.android.internal.R.styleable.View_drawingCacheQuality: 2894 final int cacheQuality = a.getInt(attr, 0); 2895 if (cacheQuality != 0) { 2896 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 2897 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 2898 } 2899 break; 2900 case com.android.internal.R.styleable.View_contentDescription: 2901 mContentDescription = a.getString(attr); 2902 break; 2903 case com.android.internal.R.styleable.View_soundEffectsEnabled: 2904 if (!a.getBoolean(attr, true)) { 2905 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 2906 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 2907 } 2908 break; 2909 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 2910 if (!a.getBoolean(attr, true)) { 2911 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 2912 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 2913 } 2914 break; 2915 case R.styleable.View_scrollbars: 2916 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 2917 if (scrollbars != SCROLLBARS_NONE) { 2918 viewFlagValues |= scrollbars; 2919 viewFlagMasks |= SCROLLBARS_MASK; 2920 initializeScrollbars(a); 2921 } 2922 break; 2923 //noinspection deprecation 2924 case R.styleable.View_fadingEdge: 2925 if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) { 2926 // Ignore the attribute starting with ICS 2927 break; 2928 } 2929 // With builds < ICS, fall through and apply fading edges 2930 case R.styleable.View_requiresFadingEdge: 2931 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 2932 if (fadingEdge != FADING_EDGE_NONE) { 2933 viewFlagValues |= fadingEdge; 2934 viewFlagMasks |= FADING_EDGE_MASK; 2935 initializeFadingEdge(a); 2936 } 2937 break; 2938 case R.styleable.View_scrollbarStyle: 2939 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 2940 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 2941 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 2942 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 2943 } 2944 break; 2945 case R.styleable.View_isScrollContainer: 2946 setScrollContainer = true; 2947 if (a.getBoolean(attr, false)) { 2948 setScrollContainer(true); 2949 } 2950 break; 2951 case com.android.internal.R.styleable.View_keepScreenOn: 2952 if (a.getBoolean(attr, false)) { 2953 viewFlagValues |= KEEP_SCREEN_ON; 2954 viewFlagMasks |= KEEP_SCREEN_ON; 2955 } 2956 break; 2957 case R.styleable.View_filterTouchesWhenObscured: 2958 if (a.getBoolean(attr, false)) { 2959 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 2960 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 2961 } 2962 break; 2963 case R.styleable.View_nextFocusLeft: 2964 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 2965 break; 2966 case R.styleable.View_nextFocusRight: 2967 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 2968 break; 2969 case R.styleable.View_nextFocusUp: 2970 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 2971 break; 2972 case R.styleable.View_nextFocusDown: 2973 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 2974 break; 2975 case R.styleable.View_nextFocusForward: 2976 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 2977 break; 2978 case R.styleable.View_minWidth: 2979 mMinWidth = a.getDimensionPixelSize(attr, 0); 2980 break; 2981 case R.styleable.View_minHeight: 2982 mMinHeight = a.getDimensionPixelSize(attr, 0); 2983 break; 2984 case R.styleable.View_onClick: 2985 if (context.isRestricted()) { 2986 throw new IllegalStateException("The android:onClick attribute cannot " 2987 + "be used within a restricted context"); 2988 } 2989 2990 final String handlerName = a.getString(attr); 2991 if (handlerName != null) { 2992 setOnClickListener(new OnClickListener() { 2993 private Method mHandler; 2994 2995 public void onClick(View v) { 2996 if (mHandler == null) { 2997 try { 2998 mHandler = getContext().getClass().getMethod(handlerName, 2999 View.class); 3000 } catch (NoSuchMethodException e) { 3001 int id = getId(); 3002 String idText = id == NO_ID ? "" : " with id '" 3003 + getContext().getResources().getResourceEntryName( 3004 id) + "'"; 3005 throw new IllegalStateException("Could not find a method " + 3006 handlerName + "(View) in the activity " 3007 + getContext().getClass() + " for onClick handler" 3008 + " on view " + View.this.getClass() + idText, e); 3009 } 3010 } 3011 3012 try { 3013 mHandler.invoke(getContext(), View.this); 3014 } catch (IllegalAccessException e) { 3015 throw new IllegalStateException("Could not execute non " 3016 + "public method of the activity", e); 3017 } catch (InvocationTargetException e) { 3018 throw new IllegalStateException("Could not execute " 3019 + "method of the activity", e); 3020 } 3021 } 3022 }); 3023 } 3024 break; 3025 case R.styleable.View_overScrollMode: 3026 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 3027 break; 3028 case R.styleable.View_verticalScrollbarPosition: 3029 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 3030 break; 3031 case R.styleable.View_layerType: 3032 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 3033 break; 3034 case R.styleable.View_textDirection: 3035 mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION); 3036 break; 3037 } 3038 } 3039 3040 a.recycle(); 3041 3042 setOverScrollMode(overScrollMode); 3043 3044 if (background != null) { 3045 setBackgroundDrawable(background); 3046 } 3047 3048 mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0); 3049 3050 // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved 3051 // layout direction). Those cached values will be used later during padding resolution. 3052 mUserPaddingStart = startPadding; 3053 mUserPaddingEnd = endPadding; 3054 3055 if (padding >= 0) { 3056 leftPadding = padding; 3057 topPadding = padding; 3058 rightPadding = padding; 3059 bottomPadding = padding; 3060 } 3061 3062 // If the user specified the padding (either with android:padding or 3063 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise 3064 // use the default padding or the padding from the background drawable 3065 // (stored at this point in mPadding*) 3066 setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft, 3067 topPadding >= 0 ? topPadding : mPaddingTop, 3068 rightPadding >= 0 ? rightPadding : mPaddingRight, 3069 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 3070 3071 if (viewFlagMasks != 0) { 3072 setFlags(viewFlagValues, viewFlagMasks); 3073 } 3074 3075 // Needs to be called after mViewFlags is set 3076 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 3077 recomputePadding(); 3078 } 3079 3080 if (x != 0 || y != 0) { 3081 scrollTo(x, y); 3082 } 3083 3084 if (transformSet) { 3085 setTranslationX(tx); 3086 setTranslationY(ty); 3087 setRotation(rotation); 3088 setRotationX(rotationX); 3089 setRotationY(rotationY); 3090 setScaleX(sx); 3091 setScaleY(sy); 3092 } 3093 3094 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 3095 setScrollContainer(true); 3096 } 3097 3098 computeOpaqueFlags(); 3099 } 3100 3101 /** 3102 * Non-public constructor for use in testing 3103 */ 3104 View() { 3105 mResources = null; 3106 } 3107 3108 /** 3109 * <p> 3110 * Initializes the fading edges from a given set of styled attributes. This 3111 * method should be called by subclasses that need fading edges and when an 3112 * instance of these subclasses is created programmatically rather than 3113 * being inflated from XML. This method is automatically called when the XML 3114 * is inflated. 3115 * </p> 3116 * 3117 * @param a the styled attributes set to initialize the fading edges from 3118 */ 3119 protected void initializeFadingEdge(TypedArray a) { 3120 initScrollCache(); 3121 3122 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 3123 R.styleable.View_fadingEdgeLength, 3124 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 3125 } 3126 3127 /** 3128 * Returns the size of the vertical faded edges used to indicate that more 3129 * content in this view is visible. 3130 * 3131 * @return The size in pixels of the vertical faded edge or 0 if vertical 3132 * faded edges are not enabled for this view. 3133 * @attr ref android.R.styleable#View_fadingEdgeLength 3134 */ 3135 public int getVerticalFadingEdgeLength() { 3136 if (isVerticalFadingEdgeEnabled()) { 3137 ScrollabilityCache cache = mScrollCache; 3138 if (cache != null) { 3139 return cache.fadingEdgeLength; 3140 } 3141 } 3142 return 0; 3143 } 3144 3145 /** 3146 * Set the size of the faded edge used to indicate that more content in this 3147 * view is available. Will not change whether the fading edge is enabled; use 3148 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 3149 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 3150 * for the vertical or horizontal fading edges. 3151 * 3152 * @param length The size in pixels of the faded edge used to indicate that more 3153 * content in this view is visible. 3154 */ 3155 public void setFadingEdgeLength(int length) { 3156 initScrollCache(); 3157 mScrollCache.fadingEdgeLength = length; 3158 } 3159 3160 /** 3161 * Returns the size of the horizontal faded edges used to indicate that more 3162 * content in this view is visible. 3163 * 3164 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 3165 * faded edges are not enabled for this view. 3166 * @attr ref android.R.styleable#View_fadingEdgeLength 3167 */ 3168 public int getHorizontalFadingEdgeLength() { 3169 if (isHorizontalFadingEdgeEnabled()) { 3170 ScrollabilityCache cache = mScrollCache; 3171 if (cache != null) { 3172 return cache.fadingEdgeLength; 3173 } 3174 } 3175 return 0; 3176 } 3177 3178 /** 3179 * Returns the width of the vertical scrollbar. 3180 * 3181 * @return The width in pixels of the vertical scrollbar or 0 if there 3182 * is no vertical scrollbar. 3183 */ 3184 public int getVerticalScrollbarWidth() { 3185 ScrollabilityCache cache = mScrollCache; 3186 if (cache != null) { 3187 ScrollBarDrawable scrollBar = cache.scrollBar; 3188 if (scrollBar != null) { 3189 int size = scrollBar.getSize(true); 3190 if (size <= 0) { 3191 size = cache.scrollBarSize; 3192 } 3193 return size; 3194 } 3195 return 0; 3196 } 3197 return 0; 3198 } 3199 3200 /** 3201 * Returns the height of the horizontal scrollbar. 3202 * 3203 * @return The height in pixels of the horizontal scrollbar or 0 if 3204 * there is no horizontal scrollbar. 3205 */ 3206 protected int getHorizontalScrollbarHeight() { 3207 ScrollabilityCache cache = mScrollCache; 3208 if (cache != null) { 3209 ScrollBarDrawable scrollBar = cache.scrollBar; 3210 if (scrollBar != null) { 3211 int size = scrollBar.getSize(false); 3212 if (size <= 0) { 3213 size = cache.scrollBarSize; 3214 } 3215 return size; 3216 } 3217 return 0; 3218 } 3219 return 0; 3220 } 3221 3222 /** 3223 * <p> 3224 * Initializes the scrollbars from a given set of styled attributes. This 3225 * method should be called by subclasses that need scrollbars and when an 3226 * instance of these subclasses is created programmatically rather than 3227 * being inflated from XML. This method is automatically called when the XML 3228 * is inflated. 3229 * </p> 3230 * 3231 * @param a the styled attributes set to initialize the scrollbars from 3232 */ 3233 protected void initializeScrollbars(TypedArray a) { 3234 initScrollCache(); 3235 3236 final ScrollabilityCache scrollabilityCache = mScrollCache; 3237 3238 if (scrollabilityCache.scrollBar == null) { 3239 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 3240 } 3241 3242 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 3243 3244 if (!fadeScrollbars) { 3245 scrollabilityCache.state = ScrollabilityCache.ON; 3246 } 3247 scrollabilityCache.fadeScrollBars = fadeScrollbars; 3248 3249 3250 scrollabilityCache.scrollBarFadeDuration = a.getInt( 3251 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 3252 .getScrollBarFadeDuration()); 3253 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 3254 R.styleable.View_scrollbarDefaultDelayBeforeFade, 3255 ViewConfiguration.getScrollDefaultDelay()); 3256 3257 3258 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 3259 com.android.internal.R.styleable.View_scrollbarSize, 3260 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 3261 3262 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 3263 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 3264 3265 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 3266 if (thumb != null) { 3267 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 3268 } 3269 3270 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 3271 false); 3272 if (alwaysDraw) { 3273 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 3274 } 3275 3276 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 3277 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 3278 3279 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 3280 if (thumb != null) { 3281 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 3282 } 3283 3284 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 3285 false); 3286 if (alwaysDraw) { 3287 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 3288 } 3289 3290 // Re-apply user/background padding so that scrollbar(s) get added 3291 resolvePadding(); 3292 } 3293 3294 /** 3295 * <p> 3296 * Initalizes the scrollability cache if necessary. 3297 * </p> 3298 */ 3299 private void initScrollCache() { 3300 if (mScrollCache == null) { 3301 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 3302 } 3303 } 3304 3305 /** 3306 * Set the position of the vertical scroll bar. Should be one of 3307 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 3308 * {@link #SCROLLBAR_POSITION_RIGHT}. 3309 * 3310 * @param position Where the vertical scroll bar should be positioned. 3311 */ 3312 public void setVerticalScrollbarPosition(int position) { 3313 if (mVerticalScrollbarPosition != position) { 3314 mVerticalScrollbarPosition = position; 3315 computeOpaqueFlags(); 3316 resolvePadding(); 3317 } 3318 } 3319 3320 /** 3321 * @return The position where the vertical scroll bar will show, if applicable. 3322 * @see #setVerticalScrollbarPosition(int) 3323 */ 3324 public int getVerticalScrollbarPosition() { 3325 return mVerticalScrollbarPosition; 3326 } 3327 3328 /** 3329 * Register a callback to be invoked when focus of this view changed. 3330 * 3331 * @param l The callback that will run. 3332 */ 3333 public void setOnFocusChangeListener(OnFocusChangeListener l) { 3334 mOnFocusChangeListener = l; 3335 } 3336 3337 /** 3338 * Add a listener that will be called when the bounds of the view change due to 3339 * layout processing. 3340 * 3341 * @param listener The listener that will be called when layout bounds change. 3342 */ 3343 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 3344 if (mOnLayoutChangeListeners == null) { 3345 mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 3346 } 3347 mOnLayoutChangeListeners.add(listener); 3348 } 3349 3350 /** 3351 * Remove a listener for layout changes. 3352 * 3353 * @param listener The listener for layout bounds change. 3354 */ 3355 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 3356 if (mOnLayoutChangeListeners == null) { 3357 return; 3358 } 3359 mOnLayoutChangeListeners.remove(listener); 3360 } 3361 3362 /** 3363 * Add a listener for attach state changes. 3364 * 3365 * This listener will be called whenever this view is attached or detached 3366 * from a window. Remove the listener using 3367 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 3368 * 3369 * @param listener Listener to attach 3370 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 3371 */ 3372 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 3373 if (mOnAttachStateChangeListeners == null) { 3374 mOnAttachStateChangeListeners = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 3375 } 3376 mOnAttachStateChangeListeners.add(listener); 3377 } 3378 3379 /** 3380 * Remove a listener for attach state changes. The listener will receive no further 3381 * notification of window attach/detach events. 3382 * 3383 * @param listener Listener to remove 3384 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 3385 */ 3386 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 3387 if (mOnAttachStateChangeListeners == null) { 3388 return; 3389 } 3390 mOnAttachStateChangeListeners.remove(listener); 3391 } 3392 3393 /** 3394 * Returns the focus-change callback registered for this view. 3395 * 3396 * @return The callback, or null if one is not registered. 3397 */ 3398 public OnFocusChangeListener getOnFocusChangeListener() { 3399 return mOnFocusChangeListener; 3400 } 3401 3402 /** 3403 * Register a callback to be invoked when this view is clicked. If this view is not 3404 * clickable, it becomes clickable. 3405 * 3406 * @param l The callback that will run 3407 * 3408 * @see #setClickable(boolean) 3409 */ 3410 public void setOnClickListener(OnClickListener l) { 3411 if (!isClickable()) { 3412 setClickable(true); 3413 } 3414 mOnClickListener = l; 3415 } 3416 3417 /** 3418 * Register a callback to be invoked when this view is clicked and held. If this view is not 3419 * long clickable, it becomes long clickable. 3420 * 3421 * @param l The callback that will run 3422 * 3423 * @see #setLongClickable(boolean) 3424 */ 3425 public void setOnLongClickListener(OnLongClickListener l) { 3426 if (!isLongClickable()) { 3427 setLongClickable(true); 3428 } 3429 mOnLongClickListener = l; 3430 } 3431 3432 /** 3433 * Register a callback to be invoked when the context menu for this view is 3434 * being built. If this view is not long clickable, it becomes long clickable. 3435 * 3436 * @param l The callback that will run 3437 * 3438 */ 3439 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 3440 if (!isLongClickable()) { 3441 setLongClickable(true); 3442 } 3443 mOnCreateContextMenuListener = l; 3444 } 3445 3446 /** 3447 * Call this view's OnClickListener, if it is defined. 3448 * 3449 * @return True there was an assigned OnClickListener that was called, false 3450 * otherwise is returned. 3451 */ 3452 public boolean performClick() { 3453 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 3454 3455 if (mOnClickListener != null) { 3456 playSoundEffect(SoundEffectConstants.CLICK); 3457 mOnClickListener.onClick(this); 3458 return true; 3459 } 3460 3461 return false; 3462 } 3463 3464 /** 3465 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the 3466 * OnLongClickListener did not consume the event. 3467 * 3468 * @return True if one of the above receivers consumed the event, false otherwise. 3469 */ 3470 public boolean performLongClick() { 3471 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 3472 3473 boolean handled = false; 3474 if (mOnLongClickListener != null) { 3475 handled = mOnLongClickListener.onLongClick(View.this); 3476 } 3477 if (!handled) { 3478 handled = showContextMenu(); 3479 } 3480 if (handled) { 3481 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 3482 } 3483 return handled; 3484 } 3485 3486 /** 3487 * Performs button-related actions during a touch down event. 3488 * 3489 * @param event The event. 3490 * @return True if the down was consumed. 3491 * 3492 * @hide 3493 */ 3494 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 3495 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 3496 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) { 3497 return true; 3498 } 3499 } 3500 return false; 3501 } 3502 3503 /** 3504 * Bring up the context menu for this view. 3505 * 3506 * @return Whether a context menu was displayed. 3507 */ 3508 public boolean showContextMenu() { 3509 return getParent().showContextMenuForChild(this); 3510 } 3511 3512 /** 3513 * Bring up the context menu for this view, referring to the item under the specified point. 3514 * 3515 * @param x The referenced x coordinate. 3516 * @param y The referenced y coordinate. 3517 * @param metaState The keyboard modifiers that were pressed. 3518 * @return Whether a context menu was displayed. 3519 * 3520 * @hide 3521 */ 3522 public boolean showContextMenu(float x, float y, int metaState) { 3523 return showContextMenu(); 3524 } 3525 3526 /** 3527 * Start an action mode. 3528 * 3529 * @param callback Callback that will control the lifecycle of the action mode 3530 * @return The new action mode if it is started, null otherwise 3531 * 3532 * @see ActionMode 3533 */ 3534 public ActionMode startActionMode(ActionMode.Callback callback) { 3535 return getParent().startActionModeForChild(this, callback); 3536 } 3537 3538 /** 3539 * Register a callback to be invoked when a key is pressed in this view. 3540 * @param l the key listener to attach to this view 3541 */ 3542 public void setOnKeyListener(OnKeyListener l) { 3543 mOnKeyListener = l; 3544 } 3545 3546 /** 3547 * Register a callback to be invoked when a touch event is sent to this view. 3548 * @param l the touch listener to attach to this view 3549 */ 3550 public void setOnTouchListener(OnTouchListener l) { 3551 mOnTouchListener = l; 3552 } 3553 3554 /** 3555 * Register a callback to be invoked when a generic motion event is sent to this view. 3556 * @param l the generic motion listener to attach to this view 3557 */ 3558 public void setOnGenericMotionListener(OnGenericMotionListener l) { 3559 mOnGenericMotionListener = l; 3560 } 3561 3562 /** 3563 * Register a callback to be invoked when a hover event is sent to this view. 3564 * @param l the hover listener to attach to this view 3565 */ 3566 public void setOnHoverListener(OnHoverListener l) { 3567 mOnHoverListener = l; 3568 } 3569 3570 /** 3571 * Register a drag event listener callback object for this View. The parameter is 3572 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 3573 * View, the system calls the 3574 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 3575 * @param l An implementation of {@link android.view.View.OnDragListener}. 3576 */ 3577 public void setOnDragListener(OnDragListener l) { 3578 mOnDragListener = l; 3579 } 3580 3581 /** 3582 * Give this view focus. This will cause 3583 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 3584 * 3585 * Note: this does not check whether this {@link View} should get focus, it just 3586 * gives it focus no matter what. It should only be called internally by framework 3587 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 3588 * 3589 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 3590 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 3591 * focus moved when requestFocus() is called. It may not always 3592 * apply, in which case use the default View.FOCUS_DOWN. 3593 * @param previouslyFocusedRect The rectangle of the view that had focus 3594 * prior in this View's coordinate system. 3595 */ 3596 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { 3597 if (DBG) { 3598 System.out.println(this + " requestFocus()"); 3599 } 3600 3601 if ((mPrivateFlags & FOCUSED) == 0) { 3602 mPrivateFlags |= FOCUSED; 3603 3604 if (mParent != null) { 3605 mParent.requestChildFocus(this, this); 3606 } 3607 3608 onFocusChanged(true, direction, previouslyFocusedRect); 3609 refreshDrawableState(); 3610 } 3611 } 3612 3613 /** 3614 * Request that a rectangle of this view be visible on the screen, 3615 * scrolling if necessary just enough. 3616 * 3617 * <p>A View should call this if it maintains some notion of which part 3618 * of its content is interesting. For example, a text editing view 3619 * should call this when its cursor moves. 3620 * 3621 * @param rectangle The rectangle. 3622 * @return Whether any parent scrolled. 3623 */ 3624 public boolean requestRectangleOnScreen(Rect rectangle) { 3625 return requestRectangleOnScreen(rectangle, false); 3626 } 3627 3628 /** 3629 * Request that a rectangle of this view be visible on the screen, 3630 * scrolling if necessary just enough. 3631 * 3632 * <p>A View should call this if it maintains some notion of which part 3633 * of its content is interesting. For example, a text editing view 3634 * should call this when its cursor moves. 3635 * 3636 * <p>When <code>immediate</code> is set to true, scrolling will not be 3637 * animated. 3638 * 3639 * @param rectangle The rectangle. 3640 * @param immediate True to forbid animated scrolling, false otherwise 3641 * @return Whether any parent scrolled. 3642 */ 3643 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 3644 View child = this; 3645 ViewParent parent = mParent; 3646 boolean scrolled = false; 3647 while (parent != null) { 3648 scrolled |= parent.requestChildRectangleOnScreen(child, 3649 rectangle, immediate); 3650 3651 // offset rect so next call has the rectangle in the 3652 // coordinate system of its direct child. 3653 rectangle.offset(child.getLeft(), child.getTop()); 3654 rectangle.offset(-child.getScrollX(), -child.getScrollY()); 3655 3656 if (!(parent instanceof View)) { 3657 break; 3658 } 3659 3660 child = (View) parent; 3661 parent = child.getParent(); 3662 } 3663 return scrolled; 3664 } 3665 3666 /** 3667 * Called when this view wants to give up focus. This will cause 3668 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 3669 */ 3670 public void clearFocus() { 3671 if (DBG) { 3672 System.out.println(this + " clearFocus()"); 3673 } 3674 3675 if ((mPrivateFlags & FOCUSED) != 0) { 3676 mPrivateFlags &= ~FOCUSED; 3677 3678 if (mParent != null) { 3679 mParent.clearChildFocus(this); 3680 } 3681 3682 onFocusChanged(false, 0, null); 3683 refreshDrawableState(); 3684 } 3685 } 3686 3687 /** 3688 * Called to clear the focus of a view that is about to be removed. 3689 * Doesn't call clearChildFocus, which prevents this view from taking 3690 * focus again before it has been removed from the parent 3691 */ 3692 void clearFocusForRemoval() { 3693 if ((mPrivateFlags & FOCUSED) != 0) { 3694 mPrivateFlags &= ~FOCUSED; 3695 3696 onFocusChanged(false, 0, null); 3697 refreshDrawableState(); 3698 } 3699 } 3700 3701 /** 3702 * Called internally by the view system when a new view is getting focus. 3703 * This is what clears the old focus. 3704 */ 3705 void unFocus() { 3706 if (DBG) { 3707 System.out.println(this + " unFocus()"); 3708 } 3709 3710 if ((mPrivateFlags & FOCUSED) != 0) { 3711 mPrivateFlags &= ~FOCUSED; 3712 3713 onFocusChanged(false, 0, null); 3714 refreshDrawableState(); 3715 } 3716 } 3717 3718 /** 3719 * Returns true if this view has focus iteself, or is the ancestor of the 3720 * view that has focus. 3721 * 3722 * @return True if this view has or contains focus, false otherwise. 3723 */ 3724 @ViewDebug.ExportedProperty(category = "focus") 3725 public boolean hasFocus() { 3726 return (mPrivateFlags & FOCUSED) != 0; 3727 } 3728 3729 /** 3730 * Returns true if this view is focusable or if it contains a reachable View 3731 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 3732 * is a View whose parents do not block descendants focus. 3733 * 3734 * Only {@link #VISIBLE} views are considered focusable. 3735 * 3736 * @return True if the view is focusable or if the view contains a focusable 3737 * View, false otherwise. 3738 * 3739 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 3740 */ 3741 public boolean hasFocusable() { 3742 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 3743 } 3744 3745 /** 3746 * Called by the view system when the focus state of this view changes. 3747 * When the focus change event is caused by directional navigation, direction 3748 * and previouslyFocusedRect provide insight into where the focus is coming from. 3749 * When overriding, be sure to call up through to the super class so that 3750 * the standard focus handling will occur. 3751 * 3752 * @param gainFocus True if the View has focus; false otherwise. 3753 * @param direction The direction focus has moved when requestFocus() 3754 * is called to give this view focus. Values are 3755 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 3756 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 3757 * It may not always apply, in which case use the default. 3758 * @param previouslyFocusedRect The rectangle, in this view's coordinate 3759 * system, of the previously focused view. If applicable, this will be 3760 * passed in as finer grained information about where the focus is coming 3761 * from (in addition to direction). Will be <code>null</code> otherwise. 3762 */ 3763 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 3764 if (gainFocus) { 3765 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 3766 } 3767 3768 InputMethodManager imm = InputMethodManager.peekInstance(); 3769 if (!gainFocus) { 3770 if (isPressed()) { 3771 setPressed(false); 3772 } 3773 if (imm != null && mAttachInfo != null 3774 && mAttachInfo.mHasWindowFocus) { 3775 imm.focusOut(this); 3776 } 3777 onFocusLost(); 3778 } else if (imm != null && mAttachInfo != null 3779 && mAttachInfo.mHasWindowFocus) { 3780 imm.focusIn(this); 3781 } 3782 3783 invalidate(true); 3784 if (mOnFocusChangeListener != null) { 3785 mOnFocusChangeListener.onFocusChange(this, gainFocus); 3786 } 3787 3788 if (mAttachInfo != null) { 3789 mAttachInfo.mKeyDispatchState.reset(this); 3790 } 3791 } 3792 3793 /** 3794 * Sends an accessibility event of the given type. If accessiiblity is 3795 * not enabled this method has no effect. The default implementation calls 3796 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 3797 * to populate information about the event source (this View), then calls 3798 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 3799 * populate the text content of the event source including its descendants, 3800 * and last calls 3801 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 3802 * on its parent to resuest sending of the event to interested parties. 3803 * <p> 3804 * If an {@link AccessibilityDelegate} has been specified via calling 3805 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 3806 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 3807 * responsible for handling this call. 3808 * </p> 3809 * 3810 * @param eventType The type of the event to send. 3811 * 3812 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 3813 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 3814 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 3815 * @see AccessibilityDelegate 3816 */ 3817 public void sendAccessibilityEvent(int eventType) { 3818 if (mAccessibilityDelegate != null) { 3819 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 3820 } else { 3821 sendAccessibilityEventInternal(eventType); 3822 } 3823 } 3824 3825 /** 3826 * @see #sendAccessibilityEvent(int) 3827 * 3828 * Note: Called from the default {@link AccessibilityDelegate}. 3829 */ 3830 void sendAccessibilityEventInternal(int eventType) { 3831 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 3832 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 3833 } 3834 } 3835 3836 /** 3837 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 3838 * takes as an argument an empty {@link AccessibilityEvent} and does not 3839 * perform a check whether accessibility is enabled. 3840 * <p> 3841 * If an {@link AccessibilityDelegate} has been specified via calling 3842 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 3843 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 3844 * is responsible for handling this call. 3845 * </p> 3846 * 3847 * @param event The event to send. 3848 * 3849 * @see #sendAccessibilityEvent(int) 3850 */ 3851 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 3852 if (mAccessibilityDelegate != null) { 3853 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 3854 } else { 3855 sendAccessibilityEventUncheckedInternal(event); 3856 } 3857 } 3858 3859 /** 3860 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 3861 * 3862 * Note: Called from the default {@link AccessibilityDelegate}. 3863 */ 3864 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 3865 if (!isShown()) { 3866 return; 3867 } 3868 onInitializeAccessibilityEvent(event); 3869 // Only a subset of accessibility events populates text content. 3870 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 3871 dispatchPopulateAccessibilityEvent(event); 3872 } 3873 // In the beginning we called #isShown(), so we know that getParent() is not null. 3874 getParent().requestSendAccessibilityEvent(this, event); 3875 } 3876 3877 /** 3878 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 3879 * to its children for adding their text content to the event. Note that the 3880 * event text is populated in a separate dispatch path since we add to the 3881 * event not only the text of the source but also the text of all its descendants. 3882 * A typical implementation will call 3883 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 3884 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 3885 * on each child. Override this method if custom population of the event text 3886 * content is required. 3887 * <p> 3888 * If an {@link AccessibilityDelegate} has been specified via calling 3889 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 3890 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 3891 * is responsible for handling this call. 3892 * </p> 3893 * <p> 3894 * <em>Note:</em> Accessibility events of certain types are not dispatched for 3895 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 3896 * </p> 3897 * 3898 * @param event The event. 3899 * 3900 * @return True if the event population was completed. 3901 */ 3902 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 3903 if (mAccessibilityDelegate != null) { 3904 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 3905 } else { 3906 return dispatchPopulateAccessibilityEventInternal(event); 3907 } 3908 } 3909 3910 /** 3911 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 3912 * 3913 * Note: Called from the default {@link AccessibilityDelegate}. 3914 */ 3915 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 3916 onPopulateAccessibilityEvent(event); 3917 return false; 3918 } 3919 3920 /** 3921 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 3922 * giving a chance to this View to populate the accessibility event with its 3923 * text content. While the implementation is free to modify other event 3924 * attributes this should be performed in 3925 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 3926 * <p> 3927 * Example: Adding formatted date string to an accessibility event in addition 3928 * to the text added by the super implementation. 3929 * </p><p><pre><code> 3930 * public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 3931 * super.onPopulateAccessibilityEvent(event); 3932 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 3933 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 3934 * mCurrentDate.getTimeInMillis(), flags); 3935 * event.getText().add(selectedDateUtterance); 3936 * } 3937 * </code></pre></p> 3938 * <p> 3939 * If an {@link AccessibilityDelegate} has been specified via calling 3940 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 3941 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 3942 * is responsible for handling this call. 3943 * </p> 3944 * 3945 * @param event The accessibility event which to populate. 3946 * 3947 * @see #sendAccessibilityEvent(int) 3948 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 3949 */ 3950 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 3951 if (mAccessibilityDelegate != null) { 3952 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 3953 } else { 3954 onPopulateAccessibilityEventInternal(event); 3955 } 3956 } 3957 3958 /** 3959 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 3960 * 3961 * Note: Called from the default {@link AccessibilityDelegate}. 3962 */ 3963 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 3964 3965 } 3966 3967 /** 3968 * Initializes an {@link AccessibilityEvent} with information about 3969 * this View which is the event source. In other words, the source of 3970 * an accessibility event is the view whose state change triggered firing 3971 * the event. 3972 * <p> 3973 * Example: Setting the password property of an event in addition 3974 * to properties set by the super implementation. 3975 * </p><p><pre><code> 3976 * public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 3977 * super.onInitializeAccessibilityEvent(event); 3978 * event.setPassword(true); 3979 * } 3980 * </code></pre></p> 3981 * <p> 3982 * If an {@link AccessibilityDelegate} has been specified via calling 3983 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 3984 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 3985 * is responsible for handling this call. 3986 * </p> 3987 * 3988 * @param event The event to initialize. 3989 * 3990 * @see #sendAccessibilityEvent(int) 3991 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 3992 */ 3993 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 3994 if (mAccessibilityDelegate != null) { 3995 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 3996 } else { 3997 onInitializeAccessibilityEventInternal(event); 3998 } 3999 } 4000 4001 /** 4002 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 4003 * 4004 * Note: Called from the default {@link AccessibilityDelegate}. 4005 */ 4006 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 4007 event.setSource(this); 4008 event.setClassName(getClass().getName()); 4009 event.setPackageName(getContext().getPackageName()); 4010 event.setEnabled(isEnabled()); 4011 event.setContentDescription(mContentDescription); 4012 4013 final int eventType = event.getEventType(); 4014 switch (eventType) { 4015 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 4016 if (mAttachInfo != null) { 4017 ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList; 4018 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, 4019 FOCUSABLES_ALL); 4020 event.setItemCount(focusablesTempList.size()); 4021 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 4022 focusablesTempList.clear(); 4023 } 4024 } break; 4025 case AccessibilityEvent.TYPE_VIEW_SCROLLED: { 4026 event.setScrollX(mScrollX); 4027 event.setScrollY(mScrollY); 4028 event.setItemCount(getHeight()); 4029 } break; 4030 } 4031 } 4032 4033 /** 4034 * Returns an {@link AccessibilityNodeInfo} representing this view from the 4035 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 4036 * This method is responsible for obtaining an accessibility node info from a 4037 * pool of reusable instances and calling 4038 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 4039 * initialize the former. 4040 * <p> 4041 * Note: The client is responsible for recycling the obtained instance by calling 4042 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 4043 * </p> 4044 * @return A populated {@link AccessibilityNodeInfo}. 4045 * 4046 * @see AccessibilityNodeInfo 4047 */ 4048 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 4049 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 4050 onInitializeAccessibilityNodeInfo(info); 4051 return info; 4052 } 4053 4054 /** 4055 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 4056 * The base implementation sets: 4057 * <ul> 4058 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 4059 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 4060 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 4061 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 4062 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 4063 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 4064 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 4065 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 4066 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 4067 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 4068 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 4069 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 4070 * </ul> 4071 * <p> 4072 * Subclasses should override this method, call the super implementation, 4073 * and set additional attributes. 4074 * </p> 4075 * <p> 4076 * If an {@link AccessibilityDelegate} has been specified via calling 4077 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 4078 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 4079 * is responsible for handling this call. 4080 * </p> 4081 * 4082 * @param info The instance to initialize. 4083 */ 4084 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 4085 if (mAccessibilityDelegate != null) { 4086 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 4087 } else { 4088 onInitializeAccessibilityNodeInfoInternal(info); 4089 } 4090 } 4091 4092 /** 4093 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 4094 * 4095 * Note: Called from the default {@link AccessibilityDelegate}. 4096 */ 4097 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 4098 Rect bounds = mAttachInfo.mTmpInvalRect; 4099 getDrawingRect(bounds); 4100 info.setBoundsInParent(bounds); 4101 4102 int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation; 4103 getLocationOnScreen(locationOnScreen); 4104 bounds.offsetTo(0, 0); 4105 bounds.offset(locationOnScreen[0], locationOnScreen[1]); 4106 info.setBoundsInScreen(bounds); 4107 4108 ViewParent parent = getParent(); 4109 if (parent instanceof View) { 4110 View parentView = (View) parent; 4111 info.setParent(parentView); 4112 } 4113 4114 info.setPackageName(mContext.getPackageName()); 4115 info.setClassName(getClass().getName()); 4116 info.setContentDescription(getContentDescription()); 4117 4118 info.setEnabled(isEnabled()); 4119 info.setClickable(isClickable()); 4120 info.setFocusable(isFocusable()); 4121 info.setFocused(isFocused()); 4122 info.setSelected(isSelected()); 4123 info.setLongClickable(isLongClickable()); 4124 4125 // TODO: These make sense only if we are in an AdapterView but all 4126 // views can be selected. Maybe from accessiiblity perspective 4127 // we should report as selectable view in an AdapterView. 4128 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 4129 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 4130 4131 if (isFocusable()) { 4132 if (isFocused()) { 4133 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 4134 } else { 4135 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 4136 } 4137 } 4138 } 4139 4140 /** 4141 * Sets a delegate for implementing accessibility support via compositon as 4142 * opposed to inheritance. The delegate's primary use is for implementing 4143 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}. 4144 * 4145 * @param delegate The delegate instance. 4146 * 4147 * @see AccessibilityDelegate 4148 */ 4149 public void setAccessibilityDelegate(AccessibilityDelegate delegate) { 4150 mAccessibilityDelegate = delegate; 4151 } 4152 4153 /** 4154 * Gets the unique identifier of this view on the screen for accessibility purposes. 4155 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 4156 * 4157 * @return The view accessibility id. 4158 * 4159 * @hide 4160 */ 4161 public int getAccessibilityViewId() { 4162 if (mAccessibilityViewId == NO_ID) { 4163 mAccessibilityViewId = sNextAccessibilityViewId++; 4164 } 4165 return mAccessibilityViewId; 4166 } 4167 4168 /** 4169 * Gets the unique identifier of the window in which this View reseides. 4170 * 4171 * @return The window accessibility id. 4172 * 4173 * @hide 4174 */ 4175 public int getAccessibilityWindowId() { 4176 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID; 4177 } 4178 4179 /** 4180 * Gets the {@link View} description. It briefly describes the view and is 4181 * primarily used for accessibility support. Set this property to enable 4182 * better accessibility support for your application. This is especially 4183 * true for views that do not have textual representation (For example, 4184 * ImageButton). 4185 * 4186 * @return The content descriptiopn. 4187 * 4188 * @attr ref android.R.styleable#View_contentDescription 4189 */ 4190 public CharSequence getContentDescription() { 4191 return mContentDescription; 4192 } 4193 4194 /** 4195 * Sets the {@link View} description. It briefly describes the view and is 4196 * primarily used for accessibility support. Set this property to enable 4197 * better accessibility support for your application. This is especially 4198 * true for views that do not have textual representation (For example, 4199 * ImageButton). 4200 * 4201 * @param contentDescription The content description. 4202 * 4203 * @attr ref android.R.styleable#View_contentDescription 4204 */ 4205 public void setContentDescription(CharSequence contentDescription) { 4206 mContentDescription = contentDescription; 4207 } 4208 4209 /** 4210 * Invoked whenever this view loses focus, either by losing window focus or by losing 4211 * focus within its window. This method can be used to clear any state tied to the 4212 * focus. For instance, if a button is held pressed with the trackball and the window 4213 * loses focus, this method can be used to cancel the press. 4214 * 4215 * Subclasses of View overriding this method should always call super.onFocusLost(). 4216 * 4217 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 4218 * @see #onWindowFocusChanged(boolean) 4219 * 4220 * @hide pending API council approval 4221 */ 4222 protected void onFocusLost() { 4223 resetPressedState(); 4224 } 4225 4226 private void resetPressedState() { 4227 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 4228 return; 4229 } 4230 4231 if (isPressed()) { 4232 setPressed(false); 4233 4234 if (!mHasPerformedLongPress) { 4235 removeLongPressCallback(); 4236 } 4237 } 4238 } 4239 4240 /** 4241 * Returns true if this view has focus 4242 * 4243 * @return True if this view has focus, false otherwise. 4244 */ 4245 @ViewDebug.ExportedProperty(category = "focus") 4246 public boolean isFocused() { 4247 return (mPrivateFlags & FOCUSED) != 0; 4248 } 4249 4250 /** 4251 * Find the view in the hierarchy rooted at this view that currently has 4252 * focus. 4253 * 4254 * @return The view that currently has focus, or null if no focused view can 4255 * be found. 4256 */ 4257 public View findFocus() { 4258 return (mPrivateFlags & FOCUSED) != 0 ? this : null; 4259 } 4260 4261 /** 4262 * Change whether this view is one of the set of scrollable containers in 4263 * its window. This will be used to determine whether the window can 4264 * resize or must pan when a soft input area is open -- scrollable 4265 * containers allow the window to use resize mode since the container 4266 * will appropriately shrink. 4267 */ 4268 public void setScrollContainer(boolean isScrollContainer) { 4269 if (isScrollContainer) { 4270 if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) { 4271 mAttachInfo.mScrollContainers.add(this); 4272 mPrivateFlags |= SCROLL_CONTAINER_ADDED; 4273 } 4274 mPrivateFlags |= SCROLL_CONTAINER; 4275 } else { 4276 if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { 4277 mAttachInfo.mScrollContainers.remove(this); 4278 } 4279 mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED); 4280 } 4281 } 4282 4283 /** 4284 * Returns the quality of the drawing cache. 4285 * 4286 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 4287 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 4288 * 4289 * @see #setDrawingCacheQuality(int) 4290 * @see #setDrawingCacheEnabled(boolean) 4291 * @see #isDrawingCacheEnabled() 4292 * 4293 * @attr ref android.R.styleable#View_drawingCacheQuality 4294 */ 4295 public int getDrawingCacheQuality() { 4296 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 4297 } 4298 4299 /** 4300 * Set the drawing cache quality of this view. This value is used only when the 4301 * drawing cache is enabled 4302 * 4303 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 4304 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 4305 * 4306 * @see #getDrawingCacheQuality() 4307 * @see #setDrawingCacheEnabled(boolean) 4308 * @see #isDrawingCacheEnabled() 4309 * 4310 * @attr ref android.R.styleable#View_drawingCacheQuality 4311 */ 4312 public void setDrawingCacheQuality(int quality) { 4313 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 4314 } 4315 4316 /** 4317 * Returns whether the screen should remain on, corresponding to the current 4318 * value of {@link #KEEP_SCREEN_ON}. 4319 * 4320 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 4321 * 4322 * @see #setKeepScreenOn(boolean) 4323 * 4324 * @attr ref android.R.styleable#View_keepScreenOn 4325 */ 4326 public boolean getKeepScreenOn() { 4327 return (mViewFlags & KEEP_SCREEN_ON) != 0; 4328 } 4329 4330 /** 4331 * Controls whether the screen should remain on, modifying the 4332 * value of {@link #KEEP_SCREEN_ON}. 4333 * 4334 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 4335 * 4336 * @see #getKeepScreenOn() 4337 * 4338 * @attr ref android.R.styleable#View_keepScreenOn 4339 */ 4340 public void setKeepScreenOn(boolean keepScreenOn) { 4341 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 4342 } 4343 4344 /** 4345 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 4346 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 4347 * 4348 * @attr ref android.R.styleable#View_nextFocusLeft 4349 */ 4350 public int getNextFocusLeftId() { 4351 return mNextFocusLeftId; 4352 } 4353 4354 /** 4355 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 4356 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 4357 * decide automatically. 4358 * 4359 * @attr ref android.R.styleable#View_nextFocusLeft 4360 */ 4361 public void setNextFocusLeftId(int nextFocusLeftId) { 4362 mNextFocusLeftId = nextFocusLeftId; 4363 } 4364 4365 /** 4366 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 4367 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 4368 * 4369 * @attr ref android.R.styleable#View_nextFocusRight 4370 */ 4371 public int getNextFocusRightId() { 4372 return mNextFocusRightId; 4373 } 4374 4375 /** 4376 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 4377 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 4378 * decide automatically. 4379 * 4380 * @attr ref android.R.styleable#View_nextFocusRight 4381 */ 4382 public void setNextFocusRightId(int nextFocusRightId) { 4383 mNextFocusRightId = nextFocusRightId; 4384 } 4385 4386 /** 4387 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 4388 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 4389 * 4390 * @attr ref android.R.styleable#View_nextFocusUp 4391 */ 4392 public int getNextFocusUpId() { 4393 return mNextFocusUpId; 4394 } 4395 4396 /** 4397 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 4398 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 4399 * decide automatically. 4400 * 4401 * @attr ref android.R.styleable#View_nextFocusUp 4402 */ 4403 public void setNextFocusUpId(int nextFocusUpId) { 4404 mNextFocusUpId = nextFocusUpId; 4405 } 4406 4407 /** 4408 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 4409 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 4410 * 4411 * @attr ref android.R.styleable#View_nextFocusDown 4412 */ 4413 public int getNextFocusDownId() { 4414 return mNextFocusDownId; 4415 } 4416 4417 /** 4418 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 4419 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 4420 * decide automatically. 4421 * 4422 * @attr ref android.R.styleable#View_nextFocusDown 4423 */ 4424 public void setNextFocusDownId(int nextFocusDownId) { 4425 mNextFocusDownId = nextFocusDownId; 4426 } 4427 4428 /** 4429 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 4430 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 4431 * 4432 * @attr ref android.R.styleable#View_nextFocusForward 4433 */ 4434 public int getNextFocusForwardId() { 4435 return mNextFocusForwardId; 4436 } 4437 4438 /** 4439 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 4440 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 4441 * decide automatically. 4442 * 4443 * @attr ref android.R.styleable#View_nextFocusForward 4444 */ 4445 public void setNextFocusForwardId(int nextFocusForwardId) { 4446 mNextFocusForwardId = nextFocusForwardId; 4447 } 4448 4449 /** 4450 * Returns the visibility of this view and all of its ancestors 4451 * 4452 * @return True if this view and all of its ancestors are {@link #VISIBLE} 4453 */ 4454 public boolean isShown() { 4455 View current = this; 4456 //noinspection ConstantConditions 4457 do { 4458 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 4459 return false; 4460 } 4461 ViewParent parent = current.mParent; 4462 if (parent == null) { 4463 return false; // We are not attached to the view root 4464 } 4465 if (!(parent instanceof View)) { 4466 return true; 4467 } 4468 current = (View) parent; 4469 } while (current != null); 4470 4471 return false; 4472 } 4473 4474 /** 4475 * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag 4476 * is set 4477 * 4478 * @param insets Insets for system windows 4479 * 4480 * @return True if this view applied the insets, false otherwise 4481 */ 4482 protected boolean fitSystemWindows(Rect insets) { 4483 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 4484 mPaddingLeft = insets.left; 4485 mPaddingTop = insets.top; 4486 mPaddingRight = insets.right; 4487 mPaddingBottom = insets.bottom; 4488 requestLayout(); 4489 return true; 4490 } 4491 return false; 4492 } 4493 4494 /** 4495 * Set whether or not this view should account for system screen decorations 4496 * such as the status bar and inset its content. This allows this view to be 4497 * positioned in absolute screen coordinates and remain visible to the user. 4498 * 4499 * <p>This should only be used by top-level window decor views. 4500 * 4501 * @param fitSystemWindows true to inset content for system screen decorations, false for 4502 * default behavior. 4503 * 4504 * @attr ref android.R.styleable#View_fitsSystemWindows 4505 */ 4506 public void setFitsSystemWindows(boolean fitSystemWindows) { 4507 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 4508 } 4509 4510 /** 4511 * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view 4512 * will account for system screen decorations such as the status bar and inset its 4513 * content. This allows the view to be positioned in absolute screen coordinates 4514 * and remain visible to the user. 4515 * 4516 * @return true if this view will adjust its content bounds for system screen decorations. 4517 * 4518 * @attr ref android.R.styleable#View_fitsSystemWindows 4519 */ 4520 public boolean fitsSystemWindows() { 4521 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 4522 } 4523 4524 /** 4525 * Returns the visibility status for this view. 4526 * 4527 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 4528 * @attr ref android.R.styleable#View_visibility 4529 */ 4530 @ViewDebug.ExportedProperty(mapping = { 4531 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 4532 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 4533 @ViewDebug.IntToString(from = GONE, to = "GONE") 4534 }) 4535 public int getVisibility() { 4536 return mViewFlags & VISIBILITY_MASK; 4537 } 4538 4539 /** 4540 * Set the enabled state of this view. 4541 * 4542 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 4543 * @attr ref android.R.styleable#View_visibility 4544 */ 4545 @RemotableViewMethod 4546 public void setVisibility(int visibility) { 4547 setFlags(visibility, VISIBILITY_MASK); 4548 if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false); 4549 } 4550 4551 /** 4552 * Returns the enabled status for this view. The interpretation of the 4553 * enabled state varies by subclass. 4554 * 4555 * @return True if this view is enabled, false otherwise. 4556 */ 4557 @ViewDebug.ExportedProperty 4558 public boolean isEnabled() { 4559 return (mViewFlags & ENABLED_MASK) == ENABLED; 4560 } 4561 4562 /** 4563 * Set the enabled state of this view. The interpretation of the enabled 4564 * state varies by subclass. 4565 * 4566 * @param enabled True if this view is enabled, false otherwise. 4567 */ 4568 @RemotableViewMethod 4569 public void setEnabled(boolean enabled) { 4570 if (enabled == isEnabled()) return; 4571 4572 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 4573 4574 /* 4575 * The View most likely has to change its appearance, so refresh 4576 * the drawable state. 4577 */ 4578 refreshDrawableState(); 4579 4580 // Invalidate too, since the default behavior for views is to be 4581 // be drawn at 50% alpha rather than to change the drawable. 4582 invalidate(true); 4583 } 4584 4585 /** 4586 * Set whether this view can receive the focus. 4587 * 4588 * Setting this to false will also ensure that this view is not focusable 4589 * in touch mode. 4590 * 4591 * @param focusable If true, this view can receive the focus. 4592 * 4593 * @see #setFocusableInTouchMode(boolean) 4594 * @attr ref android.R.styleable#View_focusable 4595 */ 4596 public void setFocusable(boolean focusable) { 4597 if (!focusable) { 4598 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 4599 } 4600 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 4601 } 4602 4603 /** 4604 * Set whether this view can receive focus while in touch mode. 4605 * 4606 * Setting this to true will also ensure that this view is focusable. 4607 * 4608 * @param focusableInTouchMode If true, this view can receive the focus while 4609 * in touch mode. 4610 * 4611 * @see #setFocusable(boolean) 4612 * @attr ref android.R.styleable#View_focusableInTouchMode 4613 */ 4614 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 4615 // Focusable in touch mode should always be set before the focusable flag 4616 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 4617 // which, in touch mode, will not successfully request focus on this view 4618 // because the focusable in touch mode flag is not set 4619 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 4620 if (focusableInTouchMode) { 4621 setFlags(FOCUSABLE, FOCUSABLE_MASK); 4622 } 4623 } 4624 4625 /** 4626 * Set whether this view should have sound effects enabled for events such as 4627 * clicking and touching. 4628 * 4629 * <p>You may wish to disable sound effects for a view if you already play sounds, 4630 * for instance, a dial key that plays dtmf tones. 4631 * 4632 * @param soundEffectsEnabled whether sound effects are enabled for this view. 4633 * @see #isSoundEffectsEnabled() 4634 * @see #playSoundEffect(int) 4635 * @attr ref android.R.styleable#View_soundEffectsEnabled 4636 */ 4637 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 4638 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 4639 } 4640 4641 /** 4642 * @return whether this view should have sound effects enabled for events such as 4643 * clicking and touching. 4644 * 4645 * @see #setSoundEffectsEnabled(boolean) 4646 * @see #playSoundEffect(int) 4647 * @attr ref android.R.styleable#View_soundEffectsEnabled 4648 */ 4649 @ViewDebug.ExportedProperty 4650 public boolean isSoundEffectsEnabled() { 4651 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 4652 } 4653 4654 /** 4655 * Set whether this view should have haptic feedback for events such as 4656 * long presses. 4657 * 4658 * <p>You may wish to disable haptic feedback if your view already controls 4659 * its own haptic feedback. 4660 * 4661 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 4662 * @see #isHapticFeedbackEnabled() 4663 * @see #performHapticFeedback(int) 4664 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 4665 */ 4666 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 4667 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 4668 } 4669 4670 /** 4671 * @return whether this view should have haptic feedback enabled for events 4672 * long presses. 4673 * 4674 * @see #setHapticFeedbackEnabled(boolean) 4675 * @see #performHapticFeedback(int) 4676 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 4677 */ 4678 @ViewDebug.ExportedProperty 4679 public boolean isHapticFeedbackEnabled() { 4680 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 4681 } 4682 4683 /** 4684 * Returns the layout direction for this view. 4685 * 4686 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 4687 * {@link #LAYOUT_DIRECTION_RTL}, 4688 * {@link #LAYOUT_DIRECTION_INHERIT} or 4689 * {@link #LAYOUT_DIRECTION_LOCALE}. 4690 * @attr ref android.R.styleable#View_layoutDirection 4691 * 4692 * @hide 4693 */ 4694 @ViewDebug.ExportedProperty(category = "layout", mapping = { 4695 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 4696 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 4697 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 4698 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 4699 }) 4700 public int getLayoutDirection() { 4701 return mViewFlags & LAYOUT_DIRECTION_MASK; 4702 } 4703 4704 /** 4705 * Set the layout direction for this view. This will propagate a reset of layout direction 4706 * resolution to the view's children and resolve layout direction for this view. 4707 * 4708 * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR}, 4709 * {@link #LAYOUT_DIRECTION_RTL}, 4710 * {@link #LAYOUT_DIRECTION_INHERIT} or 4711 * {@link #LAYOUT_DIRECTION_LOCALE}. 4712 * 4713 * @attr ref android.R.styleable#View_layoutDirection 4714 * 4715 * @hide 4716 */ 4717 @RemotableViewMethod 4718 public void setLayoutDirection(int layoutDirection) { 4719 if (getLayoutDirection() != layoutDirection) { 4720 resetResolvedLayoutDirection(); 4721 // Setting the flag will also request a layout. 4722 setFlags(layoutDirection, LAYOUT_DIRECTION_MASK); 4723 } 4724 } 4725 4726 /** 4727 * Returns the resolved layout direction for this view. 4728 * 4729 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 4730 * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL. 4731 * 4732 * @hide 4733 */ 4734 @ViewDebug.ExportedProperty(category = "layout", mapping = { 4735 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 4736 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 4737 }) 4738 public int getResolvedLayoutDirection() { 4739 resolveLayoutDirectionIfNeeded(); 4740 return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ? 4741 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 4742 } 4743 4744 /** 4745 * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from 4746 * layout attribute and/or the inherited value from the parent.</p> 4747 * 4748 * @return true if the layout is right-to-left. 4749 * 4750 * @hide 4751 */ 4752 @ViewDebug.ExportedProperty(category = "layout") 4753 public boolean isLayoutRtl() { 4754 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL); 4755 } 4756 4757 /** 4758 * If this view doesn't do any drawing on its own, set this flag to 4759 * allow further optimizations. By default, this flag is not set on 4760 * View, but could be set on some View subclasses such as ViewGroup. 4761 * 4762 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 4763 * you should clear this flag. 4764 * 4765 * @param willNotDraw whether or not this View draw on its own 4766 */ 4767 public void setWillNotDraw(boolean willNotDraw) { 4768 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 4769 } 4770 4771 /** 4772 * Returns whether or not this View draws on its own. 4773 * 4774 * @return true if this view has nothing to draw, false otherwise 4775 */ 4776 @ViewDebug.ExportedProperty(category = "drawing") 4777 public boolean willNotDraw() { 4778 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 4779 } 4780 4781 /** 4782 * When a View's drawing cache is enabled, drawing is redirected to an 4783 * offscreen bitmap. Some views, like an ImageView, must be able to 4784 * bypass this mechanism if they already draw a single bitmap, to avoid 4785 * unnecessary usage of the memory. 4786 * 4787 * @param willNotCacheDrawing true if this view does not cache its 4788 * drawing, false otherwise 4789 */ 4790 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 4791 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 4792 } 4793 4794 /** 4795 * Returns whether or not this View can cache its drawing or not. 4796 * 4797 * @return true if this view does not cache its drawing, false otherwise 4798 */ 4799 @ViewDebug.ExportedProperty(category = "drawing") 4800 public boolean willNotCacheDrawing() { 4801 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 4802 } 4803 4804 /** 4805 * Indicates whether this view reacts to click events or not. 4806 * 4807 * @return true if the view is clickable, false otherwise 4808 * 4809 * @see #setClickable(boolean) 4810 * @attr ref android.R.styleable#View_clickable 4811 */ 4812 @ViewDebug.ExportedProperty 4813 public boolean isClickable() { 4814 return (mViewFlags & CLICKABLE) == CLICKABLE; 4815 } 4816 4817 /** 4818 * Enables or disables click events for this view. When a view 4819 * is clickable it will change its state to "pressed" on every click. 4820 * Subclasses should set the view clickable to visually react to 4821 * user's clicks. 4822 * 4823 * @param clickable true to make the view clickable, false otherwise 4824 * 4825 * @see #isClickable() 4826 * @attr ref android.R.styleable#View_clickable 4827 */ 4828 public void setClickable(boolean clickable) { 4829 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 4830 } 4831 4832 /** 4833 * Indicates whether this view reacts to long click events or not. 4834 * 4835 * @return true if the view is long clickable, false otherwise 4836 * 4837 * @see #setLongClickable(boolean) 4838 * @attr ref android.R.styleable#View_longClickable 4839 */ 4840 public boolean isLongClickable() { 4841 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 4842 } 4843 4844 /** 4845 * Enables or disables long click events for this view. When a view is long 4846 * clickable it reacts to the user holding down the button for a longer 4847 * duration than a tap. This event can either launch the listener or a 4848 * context menu. 4849 * 4850 * @param longClickable true to make the view long clickable, false otherwise 4851 * @see #isLongClickable() 4852 * @attr ref android.R.styleable#View_longClickable 4853 */ 4854 public void setLongClickable(boolean longClickable) { 4855 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 4856 } 4857 4858 /** 4859 * Sets the pressed state for this view. 4860 * 4861 * @see #isClickable() 4862 * @see #setClickable(boolean) 4863 * 4864 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 4865 * the View's internal state from a previously set "pressed" state. 4866 */ 4867 public void setPressed(boolean pressed) { 4868 if (pressed) { 4869 mPrivateFlags |= PRESSED; 4870 } else { 4871 mPrivateFlags &= ~PRESSED; 4872 } 4873 refreshDrawableState(); 4874 dispatchSetPressed(pressed); 4875 } 4876 4877 /** 4878 * Dispatch setPressed to all of this View's children. 4879 * 4880 * @see #setPressed(boolean) 4881 * 4882 * @param pressed The new pressed state 4883 */ 4884 protected void dispatchSetPressed(boolean pressed) { 4885 } 4886 4887 /** 4888 * Indicates whether the view is currently in pressed state. Unless 4889 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 4890 * the pressed state. 4891 * 4892 * @see #setPressed(boolean) 4893 * @see #isClickable() 4894 * @see #setClickable(boolean) 4895 * 4896 * @return true if the view is currently pressed, false otherwise 4897 */ 4898 public boolean isPressed() { 4899 return (mPrivateFlags & PRESSED) == PRESSED; 4900 } 4901 4902 /** 4903 * Indicates whether this view will save its state (that is, 4904 * whether its {@link #onSaveInstanceState} method will be called). 4905 * 4906 * @return Returns true if the view state saving is enabled, else false. 4907 * 4908 * @see #setSaveEnabled(boolean) 4909 * @attr ref android.R.styleable#View_saveEnabled 4910 */ 4911 public boolean isSaveEnabled() { 4912 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 4913 } 4914 4915 /** 4916 * Controls whether the saving of this view's state is 4917 * enabled (that is, whether its {@link #onSaveInstanceState} method 4918 * will be called). Note that even if freezing is enabled, the 4919 * view still must have an id assigned to it (via {@link #setId(int)}) 4920 * for its state to be saved. This flag can only disable the 4921 * saving of this view; any child views may still have their state saved. 4922 * 4923 * @param enabled Set to false to <em>disable</em> state saving, or true 4924 * (the default) to allow it. 4925 * 4926 * @see #isSaveEnabled() 4927 * @see #setId(int) 4928 * @see #onSaveInstanceState() 4929 * @attr ref android.R.styleable#View_saveEnabled 4930 */ 4931 public void setSaveEnabled(boolean enabled) { 4932 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 4933 } 4934 4935 /** 4936 * Gets whether the framework should discard touches when the view's 4937 * window is obscured by another visible window. 4938 * Refer to the {@link View} security documentation for more details. 4939 * 4940 * @return True if touch filtering is enabled. 4941 * 4942 * @see #setFilterTouchesWhenObscured(boolean) 4943 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 4944 */ 4945 @ViewDebug.ExportedProperty 4946 public boolean getFilterTouchesWhenObscured() { 4947 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 4948 } 4949 4950 /** 4951 * Sets whether the framework should discard touches when the view's 4952 * window is obscured by another visible window. 4953 * Refer to the {@link View} security documentation for more details. 4954 * 4955 * @param enabled True if touch filtering should be enabled. 4956 * 4957 * @see #getFilterTouchesWhenObscured 4958 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 4959 */ 4960 public void setFilterTouchesWhenObscured(boolean enabled) { 4961 setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED, 4962 FILTER_TOUCHES_WHEN_OBSCURED); 4963 } 4964 4965 /** 4966 * Indicates whether the entire hierarchy under this view will save its 4967 * state when a state saving traversal occurs from its parent. The default 4968 * is true; if false, these views will not be saved unless 4969 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 4970 * 4971 * @return Returns true if the view state saving from parent is enabled, else false. 4972 * 4973 * @see #setSaveFromParentEnabled(boolean) 4974 */ 4975 public boolean isSaveFromParentEnabled() { 4976 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 4977 } 4978 4979 /** 4980 * Controls whether the entire hierarchy under this view will save its 4981 * state when a state saving traversal occurs from its parent. The default 4982 * is true; if false, these views will not be saved unless 4983 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 4984 * 4985 * @param enabled Set to false to <em>disable</em> state saving, or true 4986 * (the default) to allow it. 4987 * 4988 * @see #isSaveFromParentEnabled() 4989 * @see #setId(int) 4990 * @see #onSaveInstanceState() 4991 */ 4992 public void setSaveFromParentEnabled(boolean enabled) { 4993 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 4994 } 4995 4996 4997 /** 4998 * Returns whether this View is able to take focus. 4999 * 5000 * @return True if this view can take focus, or false otherwise. 5001 * @attr ref android.R.styleable#View_focusable 5002 */ 5003 @ViewDebug.ExportedProperty(category = "focus") 5004 public final boolean isFocusable() { 5005 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 5006 } 5007 5008 /** 5009 * When a view is focusable, it may not want to take focus when in touch mode. 5010 * For example, a button would like focus when the user is navigating via a D-pad 5011 * so that the user can click on it, but once the user starts touching the screen, 5012 * the button shouldn't take focus 5013 * @return Whether the view is focusable in touch mode. 5014 * @attr ref android.R.styleable#View_focusableInTouchMode 5015 */ 5016 @ViewDebug.ExportedProperty 5017 public final boolean isFocusableInTouchMode() { 5018 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 5019 } 5020 5021 /** 5022 * Find the nearest view in the specified direction that can take focus. 5023 * This does not actually give focus to that view. 5024 * 5025 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 5026 * 5027 * @return The nearest focusable in the specified direction, or null if none 5028 * can be found. 5029 */ 5030 public View focusSearch(int direction) { 5031 if (mParent != null) { 5032 return mParent.focusSearch(this, direction); 5033 } else { 5034 return null; 5035 } 5036 } 5037 5038 /** 5039 * This method is the last chance for the focused view and its ancestors to 5040 * respond to an arrow key. This is called when the focused view did not 5041 * consume the key internally, nor could the view system find a new view in 5042 * the requested direction to give focus to. 5043 * 5044 * @param focused The currently focused view. 5045 * @param direction The direction focus wants to move. One of FOCUS_UP, 5046 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 5047 * @return True if the this view consumed this unhandled move. 5048 */ 5049 public boolean dispatchUnhandledMove(View focused, int direction) { 5050 return false; 5051 } 5052 5053 /** 5054 * If a user manually specified the next view id for a particular direction, 5055 * use the root to look up the view. 5056 * @param root The root view of the hierarchy containing this view. 5057 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 5058 * or FOCUS_BACKWARD. 5059 * @return The user specified next view, or null if there is none. 5060 */ 5061 View findUserSetNextFocus(View root, int direction) { 5062 switch (direction) { 5063 case FOCUS_LEFT: 5064 if (mNextFocusLeftId == View.NO_ID) return null; 5065 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 5066 case FOCUS_RIGHT: 5067 if (mNextFocusRightId == View.NO_ID) return null; 5068 return findViewInsideOutShouldExist(root, mNextFocusRightId); 5069 case FOCUS_UP: 5070 if (mNextFocusUpId == View.NO_ID) return null; 5071 return findViewInsideOutShouldExist(root, mNextFocusUpId); 5072 case FOCUS_DOWN: 5073 if (mNextFocusDownId == View.NO_ID) return null; 5074 return findViewInsideOutShouldExist(root, mNextFocusDownId); 5075 case FOCUS_FORWARD: 5076 if (mNextFocusForwardId == View.NO_ID) return null; 5077 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 5078 case FOCUS_BACKWARD: { 5079 final int id = mID; 5080 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 5081 @Override 5082 public boolean apply(View t) { 5083 return t.mNextFocusForwardId == id; 5084 } 5085 }); 5086 } 5087 } 5088 return null; 5089 } 5090 5091 private View findViewInsideOutShouldExist(View root, final int childViewId) { 5092 View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() { 5093 @Override 5094 public boolean apply(View t) { 5095 return t.mID == childViewId; 5096 } 5097 }); 5098 5099 if (result == null) { 5100 Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified " 5101 + "by user for id " + childViewId); 5102 } 5103 return result; 5104 } 5105 5106 /** 5107 * Find and return all focusable views that are descendants of this view, 5108 * possibly including this view if it is focusable itself. 5109 * 5110 * @param direction The direction of the focus 5111 * @return A list of focusable views 5112 */ 5113 public ArrayList<View> getFocusables(int direction) { 5114 ArrayList<View> result = new ArrayList<View>(24); 5115 addFocusables(result, direction); 5116 return result; 5117 } 5118 5119 /** 5120 * Add any focusable views that are descendants of this view (possibly 5121 * including this view if it is focusable itself) to views. If we are in touch mode, 5122 * only add views that are also focusable in touch mode. 5123 * 5124 * @param views Focusable views found so far 5125 * @param direction The direction of the focus 5126 */ 5127 public void addFocusables(ArrayList<View> views, int direction) { 5128 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); 5129 } 5130 5131 /** 5132 * Adds any focusable views that are descendants of this view (possibly 5133 * including this view if it is focusable itself) to views. This method 5134 * adds all focusable views regardless if we are in touch mode or 5135 * only views focusable in touch mode if we are in touch mode depending on 5136 * the focusable mode paramater. 5137 * 5138 * @param views Focusable views found so far or null if all we are interested is 5139 * the number of focusables. 5140 * @param direction The direction of the focus. 5141 * @param focusableMode The type of focusables to be added. 5142 * 5143 * @see #FOCUSABLES_ALL 5144 * @see #FOCUSABLES_TOUCH_MODE 5145 */ 5146 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { 5147 if (!isFocusable()) { 5148 return; 5149 } 5150 5151 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE && 5152 isInTouchMode() && !isFocusableInTouchMode()) { 5153 return; 5154 } 5155 5156 if (views != null) { 5157 views.add(this); 5158 } 5159 } 5160 5161 /** 5162 * Finds the Views that contain given text. The containment is case insensitive. 5163 * The search is performed by either the text that the View renders or the content 5164 * description that describes the view for accessibility purposes and the view does 5165 * not render or both. Clients can specify how the search is to be performed via 5166 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 5167 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 5168 * 5169 * @param outViews The output list of matching Views. 5170 * @param searched The text to match against. 5171 * 5172 * @see #FIND_VIEWS_WITH_TEXT 5173 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 5174 * @see #setContentDescription(CharSequence) 5175 */ 5176 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) { 5177 if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 && !TextUtils.isEmpty(searched) 5178 && !TextUtils.isEmpty(mContentDescription)) { 5179 String searchedLowerCase = searched.toString().toLowerCase(); 5180 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 5181 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 5182 outViews.add(this); 5183 } 5184 } 5185 } 5186 5187 /** 5188 * Find and return all touchable views that are descendants of this view, 5189 * possibly including this view if it is touchable itself. 5190 * 5191 * @return A list of touchable views 5192 */ 5193 public ArrayList<View> getTouchables() { 5194 ArrayList<View> result = new ArrayList<View>(); 5195 addTouchables(result); 5196 return result; 5197 } 5198 5199 /** 5200 * Add any touchable views that are descendants of this view (possibly 5201 * including this view if it is touchable itself) to views. 5202 * 5203 * @param views Touchable views found so far 5204 */ 5205 public void addTouchables(ArrayList<View> views) { 5206 final int viewFlags = mViewFlags; 5207 5208 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 5209 && (viewFlags & ENABLED_MASK) == ENABLED) { 5210 views.add(this); 5211 } 5212 } 5213 5214 /** 5215 * Call this to try to give focus to a specific view or to one of its 5216 * descendants. 5217 * 5218 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 5219 * false), or if it is focusable and it is not focusable in touch mode 5220 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 5221 * 5222 * See also {@link #focusSearch(int)}, which is what you call to say that you 5223 * have focus, and you want your parent to look for the next one. 5224 * 5225 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 5226 * {@link #FOCUS_DOWN} and <code>null</code>. 5227 * 5228 * @return Whether this view or one of its descendants actually took focus. 5229 */ 5230 public final boolean requestFocus() { 5231 return requestFocus(View.FOCUS_DOWN); 5232 } 5233 5234 5235 /** 5236 * Call this to try to give focus to a specific view or to one of its 5237 * descendants and give it a hint about what direction focus is heading. 5238 * 5239 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 5240 * false), or if it is focusable and it is not focusable in touch mode 5241 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 5242 * 5243 * See also {@link #focusSearch(int)}, which is what you call to say that you 5244 * have focus, and you want your parent to look for the next one. 5245 * 5246 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 5247 * <code>null</code> set for the previously focused rectangle. 5248 * 5249 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 5250 * @return Whether this view or one of its descendants actually took focus. 5251 */ 5252 public final boolean requestFocus(int direction) { 5253 return requestFocus(direction, null); 5254 } 5255 5256 /** 5257 * Call this to try to give focus to a specific view or to one of its descendants 5258 * and give it hints about the direction and a specific rectangle that the focus 5259 * is coming from. The rectangle can help give larger views a finer grained hint 5260 * about where focus is coming from, and therefore, where to show selection, or 5261 * forward focus change internally. 5262 * 5263 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 5264 * false), or if it is focusable and it is not focusable in touch mode 5265 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 5266 * 5267 * A View will not take focus if it is not visible. 5268 * 5269 * A View will not take focus if one of its parents has 5270 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 5271 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 5272 * 5273 * See also {@link #focusSearch(int)}, which is what you call to say that you 5274 * have focus, and you want your parent to look for the next one. 5275 * 5276 * You may wish to override this method if your custom {@link View} has an internal 5277 * {@link View} that it wishes to forward the request to. 5278 * 5279 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 5280 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 5281 * to give a finer grained hint about where focus is coming from. May be null 5282 * if there is no hint. 5283 * @return Whether this view or one of its descendants actually took focus. 5284 */ 5285 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 5286 // need to be focusable 5287 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 5288 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 5289 return false; 5290 } 5291 5292 // need to be focusable in touch mode if in touch mode 5293 if (isInTouchMode() && 5294 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 5295 return false; 5296 } 5297 5298 // need to not have any parents blocking us 5299 if (hasAncestorThatBlocksDescendantFocus()) { 5300 return false; 5301 } 5302 5303 handleFocusGainInternal(direction, previouslyFocusedRect); 5304 return true; 5305 } 5306 5307 /** Gets the ViewAncestor, or null if not attached. */ 5308 /*package*/ ViewRootImpl getViewRootImpl() { 5309 View root = getRootView(); 5310 return root != null ? (ViewRootImpl)root.getParent() : null; 5311 } 5312 5313 /** 5314 * Call this to try to give focus to a specific view or to one of its descendants. This is a 5315 * special variant of {@link #requestFocus() } that will allow views that are not focuable in 5316 * touch mode to request focus when they are touched. 5317 * 5318 * @return Whether this view or one of its descendants actually took focus. 5319 * 5320 * @see #isInTouchMode() 5321 * 5322 */ 5323 public final boolean requestFocusFromTouch() { 5324 // Leave touch mode if we need to 5325 if (isInTouchMode()) { 5326 ViewRootImpl viewRoot = getViewRootImpl(); 5327 if (viewRoot != null) { 5328 viewRoot.ensureTouchMode(false); 5329 } 5330 } 5331 return requestFocus(View.FOCUS_DOWN); 5332 } 5333 5334 /** 5335 * @return Whether any ancestor of this view blocks descendant focus. 5336 */ 5337 private boolean hasAncestorThatBlocksDescendantFocus() { 5338 ViewParent ancestor = mParent; 5339 while (ancestor instanceof ViewGroup) { 5340 final ViewGroup vgAncestor = (ViewGroup) ancestor; 5341 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { 5342 return true; 5343 } else { 5344 ancestor = vgAncestor.getParent(); 5345 } 5346 } 5347 return false; 5348 } 5349 5350 /** 5351 * @hide 5352 */ 5353 public void dispatchStartTemporaryDetach() { 5354 onStartTemporaryDetach(); 5355 } 5356 5357 /** 5358 * This is called when a container is going to temporarily detach a child, with 5359 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 5360 * It will either be followed by {@link #onFinishTemporaryDetach()} or 5361 * {@link #onDetachedFromWindow()} when the container is done. 5362 */ 5363 public void onStartTemporaryDetach() { 5364 removeUnsetPressCallback(); 5365 mPrivateFlags |= CANCEL_NEXT_UP_EVENT; 5366 } 5367 5368 /** 5369 * @hide 5370 */ 5371 public void dispatchFinishTemporaryDetach() { 5372 onFinishTemporaryDetach(); 5373 } 5374 5375 /** 5376 * Called after {@link #onStartTemporaryDetach} when the container is done 5377 * changing the view. 5378 */ 5379 public void onFinishTemporaryDetach() { 5380 } 5381 5382 /** 5383 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 5384 * for this view's window. Returns null if the view is not currently attached 5385 * to the window. Normally you will not need to use this directly, but 5386 * just use the standard high-level event callbacks like 5387 * {@link #onKeyDown(int, KeyEvent)}. 5388 */ 5389 public KeyEvent.DispatcherState getKeyDispatcherState() { 5390 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 5391 } 5392 5393 /** 5394 * Dispatch a key event before it is processed by any input method 5395 * associated with the view hierarchy. This can be used to intercept 5396 * key events in special situations before the IME consumes them; a 5397 * typical example would be handling the BACK key to update the application's 5398 * UI instead of allowing the IME to see it and close itself. 5399 * 5400 * @param event The key event to be dispatched. 5401 * @return True if the event was handled, false otherwise. 5402 */ 5403 public boolean dispatchKeyEventPreIme(KeyEvent event) { 5404 return onKeyPreIme(event.getKeyCode(), event); 5405 } 5406 5407 /** 5408 * Dispatch a key event to the next view on the focus path. This path runs 5409 * from the top of the view tree down to the currently focused view. If this 5410 * view has focus, it will dispatch to itself. Otherwise it will dispatch 5411 * the next node down the focus path. This method also fires any key 5412 * listeners. 5413 * 5414 * @param event The key event to be dispatched. 5415 * @return True if the event was handled, false otherwise. 5416 */ 5417 public boolean dispatchKeyEvent(KeyEvent event) { 5418 if (mInputEventConsistencyVerifier != null) { 5419 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 5420 } 5421 5422 // Give any attached key listener a first crack at the event. 5423 //noinspection SimplifiableIfStatement 5424 if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 5425 && mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 5426 return true; 5427 } 5428 5429 if (event.dispatch(this, mAttachInfo != null 5430 ? mAttachInfo.mKeyDispatchState : null, this)) { 5431 return true; 5432 } 5433 5434 if (mInputEventConsistencyVerifier != null) { 5435 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 5436 } 5437 return false; 5438 } 5439 5440 /** 5441 * Dispatches a key shortcut event. 5442 * 5443 * @param event The key event to be dispatched. 5444 * @return True if the event was handled by the view, false otherwise. 5445 */ 5446 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 5447 return onKeyShortcut(event.getKeyCode(), event); 5448 } 5449 5450 /** 5451 * Pass the touch screen motion event down to the target view, or this 5452 * view if it is the target. 5453 * 5454 * @param event The motion event to be dispatched. 5455 * @return True if the event was handled by the view, false otherwise. 5456 */ 5457 public boolean dispatchTouchEvent(MotionEvent event) { 5458 if (mInputEventConsistencyVerifier != null) { 5459 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 5460 } 5461 5462 if (onFilterTouchEventForSecurity(event)) { 5463 //noinspection SimplifiableIfStatement 5464 if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && 5465 mOnTouchListener.onTouch(this, event)) { 5466 return true; 5467 } 5468 5469 if (onTouchEvent(event)) { 5470 return true; 5471 } 5472 } 5473 5474 if (mInputEventConsistencyVerifier != null) { 5475 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 5476 } 5477 return false; 5478 } 5479 5480 /** 5481 * Filter the touch event to apply security policies. 5482 * 5483 * @param event The motion event to be filtered. 5484 * @return True if the event should be dispatched, false if the event should be dropped. 5485 * 5486 * @see #getFilterTouchesWhenObscured 5487 */ 5488 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 5489 //noinspection RedundantIfStatement 5490 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 5491 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 5492 // Window is obscured, drop this touch. 5493 return false; 5494 } 5495 return true; 5496 } 5497 5498 /** 5499 * Pass a trackball motion event down to the focused view. 5500 * 5501 * @param event The motion event to be dispatched. 5502 * @return True if the event was handled by the view, false otherwise. 5503 */ 5504 public boolean dispatchTrackballEvent(MotionEvent event) { 5505 if (mInputEventConsistencyVerifier != null) { 5506 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 5507 } 5508 5509 return onTrackballEvent(event); 5510 } 5511 5512 /** 5513 * Dispatch a generic motion event. 5514 * <p> 5515 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 5516 * are delivered to the view under the pointer. All other generic motion events are 5517 * delivered to the focused view. Hover events are handled specially and are delivered 5518 * to {@link #onHoverEvent(MotionEvent)}. 5519 * </p> 5520 * 5521 * @param event The motion event to be dispatched. 5522 * @return True if the event was handled by the view, false otherwise. 5523 */ 5524 public boolean dispatchGenericMotionEvent(MotionEvent event) { 5525 if (mInputEventConsistencyVerifier != null) { 5526 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 5527 } 5528 5529 final int source = event.getSource(); 5530 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 5531 final int action = event.getAction(); 5532 if (action == MotionEvent.ACTION_HOVER_ENTER 5533 || action == MotionEvent.ACTION_HOVER_MOVE 5534 || action == MotionEvent.ACTION_HOVER_EXIT) { 5535 if (dispatchHoverEvent(event)) { 5536 return true; 5537 } 5538 } else if (dispatchGenericPointerEvent(event)) { 5539 return true; 5540 } 5541 } else if (dispatchGenericFocusedEvent(event)) { 5542 return true; 5543 } 5544 5545 if (dispatchGenericMotionEventInternal(event)) { 5546 return true; 5547 } 5548 5549 if (mInputEventConsistencyVerifier != null) { 5550 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 5551 } 5552 return false; 5553 } 5554 5555 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 5556 //noinspection SimplifiableIfStatement 5557 if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 5558 && mOnGenericMotionListener.onGenericMotion(this, event)) { 5559 return true; 5560 } 5561 5562 if (onGenericMotionEvent(event)) { 5563 return true; 5564 } 5565 5566 if (mInputEventConsistencyVerifier != null) { 5567 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 5568 } 5569 return false; 5570 } 5571 5572 /** 5573 * Dispatch a hover event. 5574 * <p> 5575 * Do not call this method directly. 5576 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 5577 * </p> 5578 * 5579 * @param event The motion event to be dispatched. 5580 * @return True if the event was handled by the view, false otherwise. 5581 */ 5582 protected boolean dispatchHoverEvent(MotionEvent event) { 5583 //noinspection SimplifiableIfStatement 5584 if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 5585 && mOnHoverListener.onHover(this, event)) { 5586 return true; 5587 } 5588 5589 return onHoverEvent(event); 5590 } 5591 5592 /** 5593 * Returns true if the view has a child to which it has recently sent 5594 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 5595 * it does not have a hovered child, then it must be the innermost hovered view. 5596 * @hide 5597 */ 5598 protected boolean hasHoveredChild() { 5599 return false; 5600 } 5601 5602 /** 5603 * Dispatch a generic motion event to the view under the first pointer. 5604 * <p> 5605 * Do not call this method directly. 5606 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 5607 * </p> 5608 * 5609 * @param event The motion event to be dispatched. 5610 * @return True if the event was handled by the view, false otherwise. 5611 */ 5612 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 5613 return false; 5614 } 5615 5616 /** 5617 * Dispatch a generic motion event to the currently focused view. 5618 * <p> 5619 * Do not call this method directly. 5620 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 5621 * </p> 5622 * 5623 * @param event The motion event to be dispatched. 5624 * @return True if the event was handled by the view, false otherwise. 5625 */ 5626 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 5627 return false; 5628 } 5629 5630 /** 5631 * Dispatch a pointer event. 5632 * <p> 5633 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 5634 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 5635 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 5636 * and should not be expected to handle other pointing device features. 5637 * </p> 5638 * 5639 * @param event The motion event to be dispatched. 5640 * @return True if the event was handled by the view, false otherwise. 5641 * @hide 5642 */ 5643 public final boolean dispatchPointerEvent(MotionEvent event) { 5644 if (event.isTouchEvent()) { 5645 return dispatchTouchEvent(event); 5646 } else { 5647 return dispatchGenericMotionEvent(event); 5648 } 5649 } 5650 5651 /** 5652 * Called when the window containing this view gains or loses window focus. 5653 * ViewGroups should override to route to their children. 5654 * 5655 * @param hasFocus True if the window containing this view now has focus, 5656 * false otherwise. 5657 */ 5658 public void dispatchWindowFocusChanged(boolean hasFocus) { 5659 onWindowFocusChanged(hasFocus); 5660 } 5661 5662 /** 5663 * Called when the window containing this view gains or loses focus. Note 5664 * that this is separate from view focus: to receive key events, both 5665 * your view and its window must have focus. If a window is displayed 5666 * on top of yours that takes input focus, then your own window will lose 5667 * focus but the view focus will remain unchanged. 5668 * 5669 * @param hasWindowFocus True if the window containing this view now has 5670 * focus, false otherwise. 5671 */ 5672 public void onWindowFocusChanged(boolean hasWindowFocus) { 5673 InputMethodManager imm = InputMethodManager.peekInstance(); 5674 if (!hasWindowFocus) { 5675 if (isPressed()) { 5676 setPressed(false); 5677 } 5678 if (imm != null && (mPrivateFlags & FOCUSED) != 0) { 5679 imm.focusOut(this); 5680 } 5681 removeLongPressCallback(); 5682 removeTapCallback(); 5683 onFocusLost(); 5684 } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { 5685 imm.focusIn(this); 5686 } 5687 refreshDrawableState(); 5688 } 5689 5690 /** 5691 * Returns true if this view is in a window that currently has window focus. 5692 * Note that this is not the same as the view itself having focus. 5693 * 5694 * @return True if this view is in a window that currently has window focus. 5695 */ 5696 public boolean hasWindowFocus() { 5697 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 5698 } 5699 5700 /** 5701 * Dispatch a view visibility change down the view hierarchy. 5702 * ViewGroups should override to route to their children. 5703 * @param changedView The view whose visibility changed. Could be 'this' or 5704 * an ancestor view. 5705 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 5706 * {@link #INVISIBLE} or {@link #GONE}. 5707 */ 5708 protected void dispatchVisibilityChanged(View changedView, int visibility) { 5709 onVisibilityChanged(changedView, visibility); 5710 } 5711 5712 /** 5713 * Called when the visibility of the view or an ancestor of the view is changed. 5714 * @param changedView The view whose visibility changed. Could be 'this' or 5715 * an ancestor view. 5716 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 5717 * {@link #INVISIBLE} or {@link #GONE}. 5718 */ 5719 protected void onVisibilityChanged(View changedView, int visibility) { 5720 if (visibility == VISIBLE) { 5721 if (mAttachInfo != null) { 5722 initialAwakenScrollBars(); 5723 } else { 5724 mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH; 5725 } 5726 } 5727 } 5728 5729 /** 5730 * Dispatch a hint about whether this view is displayed. For instance, when 5731 * a View moves out of the screen, it might receives a display hint indicating 5732 * the view is not displayed. Applications should not <em>rely</em> on this hint 5733 * as there is no guarantee that they will receive one. 5734 * 5735 * @param hint A hint about whether or not this view is displayed: 5736 * {@link #VISIBLE} or {@link #INVISIBLE}. 5737 */ 5738 public void dispatchDisplayHint(int hint) { 5739 onDisplayHint(hint); 5740 } 5741 5742 /** 5743 * Gives this view a hint about whether is displayed or not. For instance, when 5744 * a View moves out of the screen, it might receives a display hint indicating 5745 * the view is not displayed. Applications should not <em>rely</em> on this hint 5746 * as there is no guarantee that they will receive one. 5747 * 5748 * @param hint A hint about whether or not this view is displayed: 5749 * {@link #VISIBLE} or {@link #INVISIBLE}. 5750 */ 5751 protected void onDisplayHint(int hint) { 5752 } 5753 5754 /** 5755 * Dispatch a window visibility change down the view hierarchy. 5756 * ViewGroups should override to route to their children. 5757 * 5758 * @param visibility The new visibility of the window. 5759 * 5760 * @see #onWindowVisibilityChanged(int) 5761 */ 5762 public void dispatchWindowVisibilityChanged(int visibility) { 5763 onWindowVisibilityChanged(visibility); 5764 } 5765 5766 /** 5767 * Called when the window containing has change its visibility 5768 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 5769 * that this tells you whether or not your window is being made visible 5770 * to the window manager; this does <em>not</em> tell you whether or not 5771 * your window is obscured by other windows on the screen, even if it 5772 * is itself visible. 5773 * 5774 * @param visibility The new visibility of the window. 5775 */ 5776 protected void onWindowVisibilityChanged(int visibility) { 5777 if (visibility == VISIBLE) { 5778 initialAwakenScrollBars(); 5779 } 5780 } 5781 5782 /** 5783 * Returns the current visibility of the window this view is attached to 5784 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 5785 * 5786 * @return Returns the current visibility of the view's window. 5787 */ 5788 public int getWindowVisibility() { 5789 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 5790 } 5791 5792 /** 5793 * Retrieve the overall visible display size in which the window this view is 5794 * attached to has been positioned in. This takes into account screen 5795 * decorations above the window, for both cases where the window itself 5796 * is being position inside of them or the window is being placed under 5797 * then and covered insets are used for the window to position its content 5798 * inside. In effect, this tells you the available area where content can 5799 * be placed and remain visible to users. 5800 * 5801 * <p>This function requires an IPC back to the window manager to retrieve 5802 * the requested information, so should not be used in performance critical 5803 * code like drawing. 5804 * 5805 * @param outRect Filled in with the visible display frame. If the view 5806 * is not attached to a window, this is simply the raw display size. 5807 */ 5808 public void getWindowVisibleDisplayFrame(Rect outRect) { 5809 if (mAttachInfo != null) { 5810 try { 5811 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 5812 } catch (RemoteException e) { 5813 return; 5814 } 5815 // XXX This is really broken, and probably all needs to be done 5816 // in the window manager, and we need to know more about whether 5817 // we want the area behind or in front of the IME. 5818 final Rect insets = mAttachInfo.mVisibleInsets; 5819 outRect.left += insets.left; 5820 outRect.top += insets.top; 5821 outRect.right -= insets.right; 5822 outRect.bottom -= insets.bottom; 5823 return; 5824 } 5825 Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); 5826 d.getRectSize(outRect); 5827 } 5828 5829 /** 5830 * Dispatch a notification about a resource configuration change down 5831 * the view hierarchy. 5832 * ViewGroups should override to route to their children. 5833 * 5834 * @param newConfig The new resource configuration. 5835 * 5836 * @see #onConfigurationChanged(android.content.res.Configuration) 5837 */ 5838 public void dispatchConfigurationChanged(Configuration newConfig) { 5839 onConfigurationChanged(newConfig); 5840 } 5841 5842 /** 5843 * Called when the current configuration of the resources being used 5844 * by the application have changed. You can use this to decide when 5845 * to reload resources that can changed based on orientation and other 5846 * configuration characterstics. You only need to use this if you are 5847 * not relying on the normal {@link android.app.Activity} mechanism of 5848 * recreating the activity instance upon a configuration change. 5849 * 5850 * @param newConfig The new resource configuration. 5851 */ 5852 protected void onConfigurationChanged(Configuration newConfig) { 5853 } 5854 5855 /** 5856 * Private function to aggregate all per-view attributes in to the view 5857 * root. 5858 */ 5859 void dispatchCollectViewAttributes(int visibility) { 5860 performCollectViewAttributes(visibility); 5861 } 5862 5863 void performCollectViewAttributes(int visibility) { 5864 if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) { 5865 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 5866 mAttachInfo.mKeepScreenOn = true; 5867 } 5868 mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility; 5869 if (mOnSystemUiVisibilityChangeListener != null) { 5870 mAttachInfo.mHasSystemUiListeners = true; 5871 } 5872 } 5873 } 5874 5875 void needGlobalAttributesUpdate(boolean force) { 5876 final AttachInfo ai = mAttachInfo; 5877 if (ai != null) { 5878 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 5879 || ai.mHasSystemUiListeners) { 5880 ai.mRecomputeGlobalAttributes = true; 5881 } 5882 } 5883 } 5884 5885 /** 5886 * Returns whether the device is currently in touch mode. Touch mode is entered 5887 * once the user begins interacting with the device by touch, and affects various 5888 * things like whether focus is always visible to the user. 5889 * 5890 * @return Whether the device is in touch mode. 5891 */ 5892 @ViewDebug.ExportedProperty 5893 public boolean isInTouchMode() { 5894 if (mAttachInfo != null) { 5895 return mAttachInfo.mInTouchMode; 5896 } else { 5897 return ViewRootImpl.isInTouchMode(); 5898 } 5899 } 5900 5901 /** 5902 * Returns the context the view is running in, through which it can 5903 * access the current theme, resources, etc. 5904 * 5905 * @return The view's Context. 5906 */ 5907 @ViewDebug.CapturedViewProperty 5908 public final Context getContext() { 5909 return mContext; 5910 } 5911 5912 /** 5913 * Handle a key event before it is processed by any input method 5914 * associated with the view hierarchy. This can be used to intercept 5915 * key events in special situations before the IME consumes them; a 5916 * typical example would be handling the BACK key to update the application's 5917 * UI instead of allowing the IME to see it and close itself. 5918 * 5919 * @param keyCode The value in event.getKeyCode(). 5920 * @param event Description of the key event. 5921 * @return If you handled the event, return true. If you want to allow the 5922 * event to be handled by the next receiver, return false. 5923 */ 5924 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 5925 return false; 5926 } 5927 5928 /** 5929 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 5930 * KeyEvent.Callback.onKeyDown()}: perform press of the view 5931 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 5932 * is released, if the view is enabled and clickable. 5933 * 5934 * @param keyCode A key code that represents the button pressed, from 5935 * {@link android.view.KeyEvent}. 5936 * @param event The KeyEvent object that defines the button action. 5937 */ 5938 public boolean onKeyDown(int keyCode, KeyEvent event) { 5939 boolean result = false; 5940 5941 switch (keyCode) { 5942 case KeyEvent.KEYCODE_DPAD_CENTER: 5943 case KeyEvent.KEYCODE_ENTER: { 5944 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 5945 return true; 5946 } 5947 // Long clickable items don't necessarily have to be clickable 5948 if (((mViewFlags & CLICKABLE) == CLICKABLE || 5949 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && 5950 (event.getRepeatCount() == 0)) { 5951 setPressed(true); 5952 checkForLongClick(0); 5953 return true; 5954 } 5955 break; 5956 } 5957 } 5958 return result; 5959 } 5960 5961 /** 5962 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 5963 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 5964 * the event). 5965 */ 5966 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 5967 return false; 5968 } 5969 5970 /** 5971 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 5972 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 5973 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or 5974 * {@link KeyEvent#KEYCODE_ENTER} is released. 5975 * 5976 * @param keyCode A key code that represents the button pressed, from 5977 * {@link android.view.KeyEvent}. 5978 * @param event The KeyEvent object that defines the button action. 5979 */ 5980 public boolean onKeyUp(int keyCode, KeyEvent event) { 5981 boolean result = false; 5982 5983 switch (keyCode) { 5984 case KeyEvent.KEYCODE_DPAD_CENTER: 5985 case KeyEvent.KEYCODE_ENTER: { 5986 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 5987 return true; 5988 } 5989 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 5990 setPressed(false); 5991 5992 if (!mHasPerformedLongPress) { 5993 // This is a tap, so remove the longpress check 5994 removeLongPressCallback(); 5995 5996 result = performClick(); 5997 } 5998 } 5999 break; 6000 } 6001 } 6002 return result; 6003 } 6004 6005 /** 6006 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 6007 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 6008 * the event). 6009 * 6010 * @param keyCode A key code that represents the button pressed, from 6011 * {@link android.view.KeyEvent}. 6012 * @param repeatCount The number of times the action was made. 6013 * @param event The KeyEvent object that defines the button action. 6014 */ 6015 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 6016 return false; 6017 } 6018 6019 /** 6020 * Called on the focused view when a key shortcut event is not handled. 6021 * Override this method to implement local key shortcuts for the View. 6022 * Key shortcuts can also be implemented by setting the 6023 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 6024 * 6025 * @param keyCode The value in event.getKeyCode(). 6026 * @param event Description of the key event. 6027 * @return If you handled the event, return true. If you want to allow the 6028 * event to be handled by the next receiver, return false. 6029 */ 6030 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 6031 return false; 6032 } 6033 6034 /** 6035 * Check whether the called view is a text editor, in which case it 6036 * would make sense to automatically display a soft input window for 6037 * it. Subclasses should override this if they implement 6038 * {@link #onCreateInputConnection(EditorInfo)} to return true if 6039 * a call on that method would return a non-null InputConnection, and 6040 * they are really a first-class editor that the user would normally 6041 * start typing on when the go into a window containing your view. 6042 * 6043 * <p>The default implementation always returns false. This does 6044 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 6045 * will not be called or the user can not otherwise perform edits on your 6046 * view; it is just a hint to the system that this is not the primary 6047 * purpose of this view. 6048 * 6049 * @return Returns true if this view is a text editor, else false. 6050 */ 6051 public boolean onCheckIsTextEditor() { 6052 return false; 6053 } 6054 6055 /** 6056 * Create a new InputConnection for an InputMethod to interact 6057 * with the view. The default implementation returns null, since it doesn't 6058 * support input methods. You can override this to implement such support. 6059 * This is only needed for views that take focus and text input. 6060 * 6061 * <p>When implementing this, you probably also want to implement 6062 * {@link #onCheckIsTextEditor()} to indicate you will return a 6063 * non-null InputConnection. 6064 * 6065 * @param outAttrs Fill in with attribute information about the connection. 6066 */ 6067 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 6068 return null; 6069 } 6070 6071 /** 6072 * Called by the {@link android.view.inputmethod.InputMethodManager} 6073 * when a view who is not the current 6074 * input connection target is trying to make a call on the manager. The 6075 * default implementation returns false; you can override this to return 6076 * true for certain views if you are performing InputConnection proxying 6077 * to them. 6078 * @param view The View that is making the InputMethodManager call. 6079 * @return Return true to allow the call, false to reject. 6080 */ 6081 public boolean checkInputConnectionProxy(View view) { 6082 return false; 6083 } 6084 6085 /** 6086 * Show the context menu for this view. It is not safe to hold on to the 6087 * menu after returning from this method. 6088 * 6089 * You should normally not overload this method. Overload 6090 * {@link #onCreateContextMenu(ContextMenu)} or define an 6091 * {@link OnCreateContextMenuListener} to add items to the context menu. 6092 * 6093 * @param menu The context menu to populate 6094 */ 6095 public void createContextMenu(ContextMenu menu) { 6096 ContextMenuInfo menuInfo = getContextMenuInfo(); 6097 6098 // Sets the current menu info so all items added to menu will have 6099 // my extra info set. 6100 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 6101 6102 onCreateContextMenu(menu); 6103 if (mOnCreateContextMenuListener != null) { 6104 mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 6105 } 6106 6107 // Clear the extra information so subsequent items that aren't mine don't 6108 // have my extra info. 6109 ((MenuBuilder)menu).setCurrentMenuInfo(null); 6110 6111 if (mParent != null) { 6112 mParent.createContextMenu(menu); 6113 } 6114 } 6115 6116 /** 6117 * Views should implement this if they have extra information to associate 6118 * with the context menu. The return result is supplied as a parameter to 6119 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 6120 * callback. 6121 * 6122 * @return Extra information about the item for which the context menu 6123 * should be shown. This information will vary across different 6124 * subclasses of View. 6125 */ 6126 protected ContextMenuInfo getContextMenuInfo() { 6127 return null; 6128 } 6129 6130 /** 6131 * Views should implement this if the view itself is going to add items to 6132 * the context menu. 6133 * 6134 * @param menu the context menu to populate 6135 */ 6136 protected void onCreateContextMenu(ContextMenu menu) { 6137 } 6138 6139 /** 6140 * Implement this method to handle trackball motion events. The 6141 * <em>relative</em> movement of the trackball since the last event 6142 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 6143 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 6144 * that a movement of 1 corresponds to the user pressing one DPAD key (so 6145 * they will often be fractional values, representing the more fine-grained 6146 * movement information available from a trackball). 6147 * 6148 * @param event The motion event. 6149 * @return True if the event was handled, false otherwise. 6150 */ 6151 public boolean onTrackballEvent(MotionEvent event) { 6152 return false; 6153 } 6154 6155 /** 6156 * Implement this method to handle generic motion events. 6157 * <p> 6158 * Generic motion events describe joystick movements, mouse hovers, track pad 6159 * touches, scroll wheel movements and other input events. The 6160 * {@link MotionEvent#getSource() source} of the motion event specifies 6161 * the class of input that was received. Implementations of this method 6162 * must examine the bits in the source before processing the event. 6163 * The following code example shows how this is done. 6164 * </p><p> 6165 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 6166 * are delivered to the view under the pointer. All other generic motion events are 6167 * delivered to the focused view. 6168 * </p> 6169 * <code> 6170 * public boolean onGenericMotionEvent(MotionEvent event) { 6171 * if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { 6172 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 6173 * // process the joystick movement... 6174 * return true; 6175 * } 6176 * } 6177 * if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 6178 * switch (event.getAction()) { 6179 * case MotionEvent.ACTION_HOVER_MOVE: 6180 * // process the mouse hover movement... 6181 * return true; 6182 * case MotionEvent.ACTION_SCROLL: 6183 * // process the scroll wheel movement... 6184 * return true; 6185 * } 6186 * } 6187 * return super.onGenericMotionEvent(event); 6188 * } 6189 * </code> 6190 * 6191 * @param event The generic motion event being processed. 6192 * @return True if the event was handled, false otherwise. 6193 */ 6194 public boolean onGenericMotionEvent(MotionEvent event) { 6195 return false; 6196 } 6197 6198 /** 6199 * Implement this method to handle hover events. 6200 * <p> 6201 * This method is called whenever a pointer is hovering into, over, or out of the 6202 * bounds of a view and the view is not currently being touched. 6203 * Hover events are represented as pointer events with action 6204 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 6205 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 6206 * </p> 6207 * <ul> 6208 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 6209 * when the pointer enters the bounds of the view.</li> 6210 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 6211 * when the pointer has already entered the bounds of the view and has moved.</li> 6212 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 6213 * when the pointer has exited the bounds of the view or when the pointer is 6214 * about to go down due to a button click, tap, or similar user action that 6215 * causes the view to be touched.</li> 6216 * </ul> 6217 * <p> 6218 * The view should implement this method to return true to indicate that it is 6219 * handling the hover event, such as by changing its drawable state. 6220 * </p><p> 6221 * The default implementation calls {@link #setHovered} to update the hovered state 6222 * of the view when a hover enter or hover exit event is received, if the view 6223 * is enabled and is clickable. The default implementation also sends hover 6224 * accessibility events. 6225 * </p> 6226 * 6227 * @param event The motion event that describes the hover. 6228 * @return True if the view handled the hover event. 6229 * 6230 * @see #isHovered 6231 * @see #setHovered 6232 * @see #onHoverChanged 6233 */ 6234 public boolean onHoverEvent(MotionEvent event) { 6235 // The root view may receive hover (or touch) events that are outside the bounds of 6236 // the window. This code ensures that we only send accessibility events for 6237 // hovers that are actually within the bounds of the root view. 6238 final int action = event.getAction(); 6239 if (!mSendingHoverAccessibilityEvents) { 6240 if ((action == MotionEvent.ACTION_HOVER_ENTER 6241 || action == MotionEvent.ACTION_HOVER_MOVE) 6242 && !hasHoveredChild() 6243 && pointInView(event.getX(), event.getY())) { 6244 mSendingHoverAccessibilityEvents = true; 6245 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 6246 } 6247 } else { 6248 if (action == MotionEvent.ACTION_HOVER_EXIT 6249 || (action == MotionEvent.ACTION_HOVER_MOVE 6250 && !pointInView(event.getX(), event.getY()))) { 6251 mSendingHoverAccessibilityEvents = false; 6252 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 6253 } 6254 } 6255 6256 if (isHoverable()) { 6257 switch (action) { 6258 case MotionEvent.ACTION_HOVER_ENTER: 6259 setHovered(true); 6260 break; 6261 case MotionEvent.ACTION_HOVER_EXIT: 6262 setHovered(false); 6263 break; 6264 } 6265 6266 // Dispatch the event to onGenericMotionEvent before returning true. 6267 // This is to provide compatibility with existing applications that 6268 // handled HOVER_MOVE events in onGenericMotionEvent and that would 6269 // break because of the new default handling for hoverable views 6270 // in onHoverEvent. 6271 // Note that onGenericMotionEvent will be called by default when 6272 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 6273 dispatchGenericMotionEventInternal(event); 6274 return true; 6275 } 6276 return false; 6277 } 6278 6279 /** 6280 * Returns true if the view should handle {@link #onHoverEvent} 6281 * by calling {@link #setHovered} to change its hovered state. 6282 * 6283 * @return True if the view is hoverable. 6284 */ 6285 private boolean isHoverable() { 6286 final int viewFlags = mViewFlags; 6287 //noinspection SimplifiableIfStatement 6288 if ((viewFlags & ENABLED_MASK) == DISABLED) { 6289 return false; 6290 } 6291 6292 return (viewFlags & CLICKABLE) == CLICKABLE 6293 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 6294 } 6295 6296 /** 6297 * Returns true if the view is currently hovered. 6298 * 6299 * @return True if the view is currently hovered. 6300 * 6301 * @see #setHovered 6302 * @see #onHoverChanged 6303 */ 6304 @ViewDebug.ExportedProperty 6305 public boolean isHovered() { 6306 return (mPrivateFlags & HOVERED) != 0; 6307 } 6308 6309 /** 6310 * Sets whether the view is currently hovered. 6311 * <p> 6312 * Calling this method also changes the drawable state of the view. This 6313 * enables the view to react to hover by using different drawable resources 6314 * to change its appearance. 6315 * </p><p> 6316 * The {@link #onHoverChanged} method is called when the hovered state changes. 6317 * </p> 6318 * 6319 * @param hovered True if the view is hovered. 6320 * 6321 * @see #isHovered 6322 * @see #onHoverChanged 6323 */ 6324 public void setHovered(boolean hovered) { 6325 if (hovered) { 6326 if ((mPrivateFlags & HOVERED) == 0) { 6327 mPrivateFlags |= HOVERED; 6328 refreshDrawableState(); 6329 onHoverChanged(true); 6330 } 6331 } else { 6332 if ((mPrivateFlags & HOVERED) != 0) { 6333 mPrivateFlags &= ~HOVERED; 6334 refreshDrawableState(); 6335 onHoverChanged(false); 6336 } 6337 } 6338 } 6339 6340 /** 6341 * Implement this method to handle hover state changes. 6342 * <p> 6343 * This method is called whenever the hover state changes as a result of a 6344 * call to {@link #setHovered}. 6345 * </p> 6346 * 6347 * @param hovered The current hover state, as returned by {@link #isHovered}. 6348 * 6349 * @see #isHovered 6350 * @see #setHovered 6351 */ 6352 public void onHoverChanged(boolean hovered) { 6353 } 6354 6355 /** 6356 * Implement this method to handle touch screen motion events. 6357 * 6358 * @param event The motion event. 6359 * @return True if the event was handled, false otherwise. 6360 */ 6361 public boolean onTouchEvent(MotionEvent event) { 6362 final int viewFlags = mViewFlags; 6363 6364 if ((viewFlags & ENABLED_MASK) == DISABLED) { 6365 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) { 6366 mPrivateFlags &= ~PRESSED; 6367 refreshDrawableState(); 6368 } 6369 // A disabled view that is clickable still consumes the touch 6370 // events, it just doesn't respond to them. 6371 return (((viewFlags & CLICKABLE) == CLICKABLE || 6372 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 6373 } 6374 6375 if (mTouchDelegate != null) { 6376 if (mTouchDelegate.onTouchEvent(event)) { 6377 return true; 6378 } 6379 } 6380 6381 if (((viewFlags & CLICKABLE) == CLICKABLE || 6382 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 6383 switch (event.getAction()) { 6384 case MotionEvent.ACTION_UP: 6385 boolean prepressed = (mPrivateFlags & PREPRESSED) != 0; 6386 if ((mPrivateFlags & PRESSED) != 0 || prepressed) { 6387 // take focus if we don't have it already and we should in 6388 // touch mode. 6389 boolean focusTaken = false; 6390 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 6391 focusTaken = requestFocus(); 6392 } 6393 6394 if (prepressed) { 6395 // The button is being released before we actually 6396 // showed it as pressed. Make it show the pressed 6397 // state now (before scheduling the click) to ensure 6398 // the user sees it. 6399 mPrivateFlags |= PRESSED; 6400 refreshDrawableState(); 6401 } 6402 6403 if (!mHasPerformedLongPress) { 6404 // This is a tap, so remove the longpress check 6405 removeLongPressCallback(); 6406 6407 // Only perform take click actions if we were in the pressed state 6408 if (!focusTaken) { 6409 // Use a Runnable and post this rather than calling 6410 // performClick directly. This lets other visual state 6411 // of the view update before click actions start. 6412 if (mPerformClick == null) { 6413 mPerformClick = new PerformClick(); 6414 } 6415 if (!post(mPerformClick)) { 6416 performClick(); 6417 } 6418 } 6419 } 6420 6421 if (mUnsetPressedState == null) { 6422 mUnsetPressedState = new UnsetPressedState(); 6423 } 6424 6425 if (prepressed) { 6426 postDelayed(mUnsetPressedState, 6427 ViewConfiguration.getPressedStateDuration()); 6428 } else if (!post(mUnsetPressedState)) { 6429 // If the post failed, unpress right now 6430 mUnsetPressedState.run(); 6431 } 6432 removeTapCallback(); 6433 } 6434 break; 6435 6436 case MotionEvent.ACTION_DOWN: 6437 mHasPerformedLongPress = false; 6438 6439 if (performButtonActionOnTouchDown(event)) { 6440 break; 6441 } 6442 6443 // Walk up the hierarchy to determine if we're inside a scrolling container. 6444 boolean isInScrollingContainer = isInScrollingContainer(); 6445 6446 // For views inside a scrolling container, delay the pressed feedback for 6447 // a short period in case this is a scroll. 6448 if (isInScrollingContainer) { 6449 mPrivateFlags |= PREPRESSED; 6450 if (mPendingCheckForTap == null) { 6451 mPendingCheckForTap = new CheckForTap(); 6452 } 6453 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 6454 } else { 6455 // Not inside a scrolling container, so show the feedback right away 6456 mPrivateFlags |= PRESSED; 6457 refreshDrawableState(); 6458 checkForLongClick(0); 6459 } 6460 break; 6461 6462 case MotionEvent.ACTION_CANCEL: 6463 mPrivateFlags &= ~PRESSED; 6464 refreshDrawableState(); 6465 removeTapCallback(); 6466 break; 6467 6468 case MotionEvent.ACTION_MOVE: 6469 final int x = (int) event.getX(); 6470 final int y = (int) event.getY(); 6471 6472 // Be lenient about moving outside of buttons 6473 if (!pointInView(x, y, mTouchSlop)) { 6474 // Outside button 6475 removeTapCallback(); 6476 if ((mPrivateFlags & PRESSED) != 0) { 6477 // Remove any future long press/tap checks 6478 removeLongPressCallback(); 6479 6480 // Need to switch from pressed to not pressed 6481 mPrivateFlags &= ~PRESSED; 6482 refreshDrawableState(); 6483 } 6484 } 6485 break; 6486 } 6487 return true; 6488 } 6489 6490 return false; 6491 } 6492 6493 /** 6494 * @hide 6495 */ 6496 public boolean isInScrollingContainer() { 6497 ViewParent p = getParent(); 6498 while (p != null && p instanceof ViewGroup) { 6499 if (((ViewGroup) p).shouldDelayChildPressedState()) { 6500 return true; 6501 } 6502 p = p.getParent(); 6503 } 6504 return false; 6505 } 6506 6507 /** 6508 * Remove the longpress detection timer. 6509 */ 6510 private void removeLongPressCallback() { 6511 if (mPendingCheckForLongPress != null) { 6512 removeCallbacks(mPendingCheckForLongPress); 6513 } 6514 } 6515 6516 /** 6517 * Remove the pending click action 6518 */ 6519 private void removePerformClickCallback() { 6520 if (mPerformClick != null) { 6521 removeCallbacks(mPerformClick); 6522 } 6523 } 6524 6525 /** 6526 * Remove the prepress detection timer. 6527 */ 6528 private void removeUnsetPressCallback() { 6529 if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) { 6530 setPressed(false); 6531 removeCallbacks(mUnsetPressedState); 6532 } 6533 } 6534 6535 /** 6536 * Remove the tap detection timer. 6537 */ 6538 private void removeTapCallback() { 6539 if (mPendingCheckForTap != null) { 6540 mPrivateFlags &= ~PREPRESSED; 6541 removeCallbacks(mPendingCheckForTap); 6542 } 6543 } 6544 6545 /** 6546 * Cancels a pending long press. Your subclass can use this if you 6547 * want the context menu to come up if the user presses and holds 6548 * at the same place, but you don't want it to come up if they press 6549 * and then move around enough to cause scrolling. 6550 */ 6551 public void cancelLongPress() { 6552 removeLongPressCallback(); 6553 6554 /* 6555 * The prepressed state handled by the tap callback is a display 6556 * construct, but the tap callback will post a long press callback 6557 * less its own timeout. Remove it here. 6558 */ 6559 removeTapCallback(); 6560 } 6561 6562 /** 6563 * Remove the pending callback for sending a 6564 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 6565 */ 6566 private void removeSendViewScrolledAccessibilityEventCallback() { 6567 if (mSendViewScrolledAccessibilityEvent != null) { 6568 removeCallbacks(mSendViewScrolledAccessibilityEvent); 6569 } 6570 } 6571 6572 /** 6573 * Sets the TouchDelegate for this View. 6574 */ 6575 public void setTouchDelegate(TouchDelegate delegate) { 6576 mTouchDelegate = delegate; 6577 } 6578 6579 /** 6580 * Gets the TouchDelegate for this View. 6581 */ 6582 public TouchDelegate getTouchDelegate() { 6583 return mTouchDelegate; 6584 } 6585 6586 /** 6587 * Set flags controlling behavior of this view. 6588 * 6589 * @param flags Constant indicating the value which should be set 6590 * @param mask Constant indicating the bit range that should be changed 6591 */ 6592 void setFlags(int flags, int mask) { 6593 int old = mViewFlags; 6594 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 6595 6596 int changed = mViewFlags ^ old; 6597 if (changed == 0) { 6598 return; 6599 } 6600 int privateFlags = mPrivateFlags; 6601 6602 /* Check if the FOCUSABLE bit has changed */ 6603 if (((changed & FOCUSABLE_MASK) != 0) && 6604 ((privateFlags & HAS_BOUNDS) !=0)) { 6605 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 6606 && ((privateFlags & FOCUSED) != 0)) { 6607 /* Give up focus if we are no longer focusable */ 6608 clearFocus(); 6609 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 6610 && ((privateFlags & FOCUSED) == 0)) { 6611 /* 6612 * Tell the view system that we are now available to take focus 6613 * if no one else already has it. 6614 */ 6615 if (mParent != null) mParent.focusableViewAvailable(this); 6616 } 6617 } 6618 6619 if ((flags & VISIBILITY_MASK) == VISIBLE) { 6620 if ((changed & VISIBILITY_MASK) != 0) { 6621 /* 6622 * If this view is becoming visible, invalidate it in case it changed while 6623 * it was not visible. Marking it drawn ensures that the invalidation will 6624 * go through. 6625 */ 6626 mPrivateFlags |= DRAWN; 6627 invalidate(true); 6628 6629 needGlobalAttributesUpdate(true); 6630 6631 // a view becoming visible is worth notifying the parent 6632 // about in case nothing has focus. even if this specific view 6633 // isn't focusable, it may contain something that is, so let 6634 // the root view try to give this focus if nothing else does. 6635 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 6636 mParent.focusableViewAvailable(this); 6637 } 6638 } 6639 } 6640 6641 /* Check if the GONE bit has changed */ 6642 if ((changed & GONE) != 0) { 6643 needGlobalAttributesUpdate(false); 6644 requestLayout(); 6645 6646 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 6647 if (hasFocus()) clearFocus(); 6648 destroyDrawingCache(); 6649 if (mParent instanceof View) { 6650 // GONE views noop invalidation, so invalidate the parent 6651 ((View) mParent).invalidate(true); 6652 } 6653 // Mark the view drawn to ensure that it gets invalidated properly the next 6654 // time it is visible and gets invalidated 6655 mPrivateFlags |= DRAWN; 6656 } 6657 if (mAttachInfo != null) { 6658 mAttachInfo.mViewVisibilityChanged = true; 6659 } 6660 } 6661 6662 /* Check if the VISIBLE bit has changed */ 6663 if ((changed & INVISIBLE) != 0) { 6664 needGlobalAttributesUpdate(false); 6665 /* 6666 * If this view is becoming invisible, set the DRAWN flag so that 6667 * the next invalidate() will not be skipped. 6668 */ 6669 mPrivateFlags |= DRAWN; 6670 6671 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { 6672 // root view becoming invisible shouldn't clear focus 6673 if (getRootView() != this) { 6674 clearFocus(); 6675 } 6676 } 6677 if (mAttachInfo != null) { 6678 mAttachInfo.mViewVisibilityChanged = true; 6679 } 6680 } 6681 6682 if ((changed & VISIBILITY_MASK) != 0) { 6683 if (mParent instanceof ViewGroup) { 6684 ((ViewGroup) mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK)); 6685 ((View) mParent).invalidate(true); 6686 } else if (mParent != null) { 6687 mParent.invalidateChild(this, null); 6688 } 6689 dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK)); 6690 } 6691 6692 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 6693 destroyDrawingCache(); 6694 } 6695 6696 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 6697 destroyDrawingCache(); 6698 mPrivateFlags &= ~DRAWING_CACHE_VALID; 6699 invalidateParentCaches(); 6700 } 6701 6702 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 6703 destroyDrawingCache(); 6704 mPrivateFlags &= ~DRAWING_CACHE_VALID; 6705 } 6706 6707 if ((changed & DRAW_MASK) != 0) { 6708 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 6709 if (mBGDrawable != null) { 6710 mPrivateFlags &= ~SKIP_DRAW; 6711 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 6712 } else { 6713 mPrivateFlags |= SKIP_DRAW; 6714 } 6715 } else { 6716 mPrivateFlags &= ~SKIP_DRAW; 6717 } 6718 requestLayout(); 6719 invalidate(true); 6720 } 6721 6722 if ((changed & KEEP_SCREEN_ON) != 0) { 6723 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 6724 mParent.recomputeViewAttributes(this); 6725 } 6726 } 6727 6728 if ((changed & LAYOUT_DIRECTION_MASK) != 0) { 6729 requestLayout(); 6730 } 6731 } 6732 6733 /** 6734 * Change the view's z order in the tree, so it's on top of other sibling 6735 * views 6736 */ 6737 public void bringToFront() { 6738 if (mParent != null) { 6739 mParent.bringChildToFront(this); 6740 } 6741 } 6742 6743 /** 6744 * This is called in response to an internal scroll in this view (i.e., the 6745 * view scrolled its own contents). This is typically as a result of 6746 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 6747 * called. 6748 * 6749 * @param l Current horizontal scroll origin. 6750 * @param t Current vertical scroll origin. 6751 * @param oldl Previous horizontal scroll origin. 6752 * @param oldt Previous vertical scroll origin. 6753 */ 6754 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 6755 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 6756 postSendViewScrolledAccessibilityEventCallback(); 6757 } 6758 6759 mBackgroundSizeChanged = true; 6760 6761 final AttachInfo ai = mAttachInfo; 6762 if (ai != null) { 6763 ai.mViewScrollChanged = true; 6764 } 6765 } 6766 6767 /** 6768 * Interface definition for a callback to be invoked when the layout bounds of a view 6769 * changes due to layout processing. 6770 */ 6771 public interface OnLayoutChangeListener { 6772 /** 6773 * Called when the focus state of a view has changed. 6774 * 6775 * @param v The view whose state has changed. 6776 * @param left The new value of the view's left property. 6777 * @param top The new value of the view's top property. 6778 * @param right The new value of the view's right property. 6779 * @param bottom The new value of the view's bottom property. 6780 * @param oldLeft The previous value of the view's left property. 6781 * @param oldTop The previous value of the view's top property. 6782 * @param oldRight The previous value of the view's right property. 6783 * @param oldBottom The previous value of the view's bottom property. 6784 */ 6785 void onLayoutChange(View v, int left, int top, int right, int bottom, 6786 int oldLeft, int oldTop, int oldRight, int oldBottom); 6787 } 6788 6789 /** 6790 * This is called during layout when the size of this view has changed. If 6791 * you were just added to the view hierarchy, you're called with the old 6792 * values of 0. 6793 * 6794 * @param w Current width of this view. 6795 * @param h Current height of this view. 6796 * @param oldw Old width of this view. 6797 * @param oldh Old height of this view. 6798 */ 6799 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 6800 } 6801 6802 /** 6803 * Called by draw to draw the child views. This may be overridden 6804 * by derived classes to gain control just before its children are drawn 6805 * (but after its own view has been drawn). 6806 * @param canvas the canvas on which to draw the view 6807 */ 6808 protected void dispatchDraw(Canvas canvas) { 6809 } 6810 6811 /** 6812 * Gets the parent of this view. Note that the parent is a 6813 * ViewParent and not necessarily a View. 6814 * 6815 * @return Parent of this view. 6816 */ 6817 public final ViewParent getParent() { 6818 return mParent; 6819 } 6820 6821 /** 6822 * Set the horizontal scrolled position of your view. This will cause a call to 6823 * {@link #onScrollChanged(int, int, int, int)} and the view will be 6824 * invalidated. 6825 * @param value the x position to scroll to 6826 */ 6827 public void setScrollX(int value) { 6828 scrollTo(value, mScrollY); 6829 } 6830 6831 /** 6832 * Set the vertical scrolled position of your view. This will cause a call to 6833 * {@link #onScrollChanged(int, int, int, int)} and the view will be 6834 * invalidated. 6835 * @param value the y position to scroll to 6836 */ 6837 public void setScrollY(int value) { 6838 scrollTo(mScrollX, value); 6839 } 6840 6841 /** 6842 * Return the scrolled left position of this view. This is the left edge of 6843 * the displayed part of your view. You do not need to draw any pixels 6844 * farther left, since those are outside of the frame of your view on 6845 * screen. 6846 * 6847 * @return The left edge of the displayed part of your view, in pixels. 6848 */ 6849 public final int getScrollX() { 6850 return mScrollX; 6851 } 6852 6853 /** 6854 * Return the scrolled top position of this view. This is the top edge of 6855 * the displayed part of your view. You do not need to draw any pixels above 6856 * it, since those are outside of the frame of your view on screen. 6857 * 6858 * @return The top edge of the displayed part of your view, in pixels. 6859 */ 6860 public final int getScrollY() { 6861 return mScrollY; 6862 } 6863 6864 /** 6865 * Return the width of the your view. 6866 * 6867 * @return The width of your view, in pixels. 6868 */ 6869 @ViewDebug.ExportedProperty(category = "layout") 6870 public final int getWidth() { 6871 return mRight - mLeft; 6872 } 6873 6874 /** 6875 * Return the height of your view. 6876 * 6877 * @return The height of your view, in pixels. 6878 */ 6879 @ViewDebug.ExportedProperty(category = "layout") 6880 public final int getHeight() { 6881 return mBottom - mTop; 6882 } 6883 6884 /** 6885 * Return the visible drawing bounds of your view. Fills in the output 6886 * rectangle with the values from getScrollX(), getScrollY(), 6887 * getWidth(), and getHeight(). 6888 * 6889 * @param outRect The (scrolled) drawing bounds of the view. 6890 */ 6891 public void getDrawingRect(Rect outRect) { 6892 outRect.left = mScrollX; 6893 outRect.top = mScrollY; 6894 outRect.right = mScrollX + (mRight - mLeft); 6895 outRect.bottom = mScrollY + (mBottom - mTop); 6896 } 6897 6898 /** 6899 * Like {@link #getMeasuredWidthAndState()}, but only returns the 6900 * raw width component (that is the result is masked by 6901 * {@link #MEASURED_SIZE_MASK}). 6902 * 6903 * @return The raw measured width of this view. 6904 */ 6905 public final int getMeasuredWidth() { 6906 return mMeasuredWidth & MEASURED_SIZE_MASK; 6907 } 6908 6909 /** 6910 * Return the full width measurement information for this view as computed 6911 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 6912 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 6913 * This should be used during measurement and layout calculations only. Use 6914 * {@link #getWidth()} to see how wide a view is after layout. 6915 * 6916 * @return The measured width of this view as a bit mask. 6917 */ 6918 public final int getMeasuredWidthAndState() { 6919 return mMeasuredWidth; 6920 } 6921 6922 /** 6923 * Like {@link #getMeasuredHeightAndState()}, but only returns the 6924 * raw width component (that is the result is masked by 6925 * {@link #MEASURED_SIZE_MASK}). 6926 * 6927 * @return The raw measured height of this view. 6928 */ 6929 public final int getMeasuredHeight() { 6930 return mMeasuredHeight & MEASURED_SIZE_MASK; 6931 } 6932 6933 /** 6934 * Return the full height measurement information for this view as computed 6935 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 6936 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 6937 * This should be used during measurement and layout calculations only. Use 6938 * {@link #getHeight()} to see how wide a view is after layout. 6939 * 6940 * @return The measured width of this view as a bit mask. 6941 */ 6942 public final int getMeasuredHeightAndState() { 6943 return mMeasuredHeight; 6944 } 6945 6946 /** 6947 * Return only the state bits of {@link #getMeasuredWidthAndState()} 6948 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 6949 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 6950 * and the height component is at the shifted bits 6951 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 6952 */ 6953 public final int getMeasuredState() { 6954 return (mMeasuredWidth&MEASURED_STATE_MASK) 6955 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 6956 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 6957 } 6958 6959 /** 6960 * The transform matrix of this view, which is calculated based on the current 6961 * roation, scale, and pivot properties. 6962 * 6963 * @see #getRotation() 6964 * @see #getScaleX() 6965 * @see #getScaleY() 6966 * @see #getPivotX() 6967 * @see #getPivotY() 6968 * @return The current transform matrix for the view 6969 */ 6970 public Matrix getMatrix() { 6971 if (mTransformationInfo != null) { 6972 updateMatrix(); 6973 return mTransformationInfo.mMatrix; 6974 } 6975 return Matrix.IDENTITY_MATRIX; 6976 } 6977 6978 /** 6979 * Utility function to determine if the value is far enough away from zero to be 6980 * considered non-zero. 6981 * @param value A floating point value to check for zero-ness 6982 * @return whether the passed-in value is far enough away from zero to be considered non-zero 6983 */ 6984 private static boolean nonzero(float value) { 6985 return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON); 6986 } 6987 6988 /** 6989 * Returns true if the transform matrix is the identity matrix. 6990 * Recomputes the matrix if necessary. 6991 * 6992 * @return True if the transform matrix is the identity matrix, false otherwise. 6993 */ 6994 final boolean hasIdentityMatrix() { 6995 if (mTransformationInfo != null) { 6996 updateMatrix(); 6997 return mTransformationInfo.mMatrixIsIdentity; 6998 } 6999 return true; 7000 } 7001 7002 void ensureTransformationInfo() { 7003 if (mTransformationInfo == null) { 7004 mTransformationInfo = new TransformationInfo(); 7005 } 7006 } 7007 7008 /** 7009 * Recomputes the transform matrix if necessary. 7010 */ 7011 private void updateMatrix() { 7012 final TransformationInfo info = mTransformationInfo; 7013 if (info == null) { 7014 return; 7015 } 7016 if (info.mMatrixDirty) { 7017 // transform-related properties have changed since the last time someone 7018 // asked for the matrix; recalculate it with the current values 7019 7020 // Figure out if we need to update the pivot point 7021 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 7022 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) { 7023 info.mPrevWidth = mRight - mLeft; 7024 info.mPrevHeight = mBottom - mTop; 7025 info.mPivotX = info.mPrevWidth / 2f; 7026 info.mPivotY = info.mPrevHeight / 2f; 7027 } 7028 } 7029 info.mMatrix.reset(); 7030 if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) { 7031 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY); 7032 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY); 7033 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); 7034 } else { 7035 if (info.mCamera == null) { 7036 info.mCamera = new Camera(); 7037 info.matrix3D = new Matrix(); 7038 } 7039 info.mCamera.save(); 7040 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY); 7041 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation); 7042 info.mCamera.getMatrix(info.matrix3D); 7043 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY); 7044 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX, 7045 info.mPivotY + info.mTranslationY); 7046 info.mMatrix.postConcat(info.matrix3D); 7047 info.mCamera.restore(); 7048 } 7049 info.mMatrixDirty = false; 7050 info.mMatrixIsIdentity = info.mMatrix.isIdentity(); 7051 info.mInverseMatrixDirty = true; 7052 } 7053 } 7054 7055 /** 7056 * Utility method to retrieve the inverse of the current mMatrix property. 7057 * We cache the matrix to avoid recalculating it when transform properties 7058 * have not changed. 7059 * 7060 * @return The inverse of the current matrix of this view. 7061 */ 7062 final Matrix getInverseMatrix() { 7063 final TransformationInfo info = mTransformationInfo; 7064 if (info != null) { 7065 updateMatrix(); 7066 if (info.mInverseMatrixDirty) { 7067 if (info.mInverseMatrix == null) { 7068 info.mInverseMatrix = new Matrix(); 7069 } 7070 info.mMatrix.invert(info.mInverseMatrix); 7071 info.mInverseMatrixDirty = false; 7072 } 7073 return info.mInverseMatrix; 7074 } 7075 return Matrix.IDENTITY_MATRIX; 7076 } 7077 7078 /** 7079 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 7080 * views are drawn) from the camera to this view. The camera's distance 7081 * affects 3D transformations, for instance rotations around the X and Y 7082 * axis. If the rotationX or rotationY properties are changed and this view is 7083 * large (more than half the size of the screen), it is recommended to always 7084 * use a camera distance that's greater than the height (X axis rotation) or 7085 * the width (Y axis rotation) of this view.</p> 7086 * 7087 * <p>The distance of the camera from the view plane can have an affect on the 7088 * perspective distortion of the view when it is rotated around the x or y axis. 7089 * For example, a large distance will result in a large viewing angle, and there 7090 * will not be much perspective distortion of the view as it rotates. A short 7091 * distance may cause much more perspective distortion upon rotation, and can 7092 * also result in some drawing artifacts if the rotated view ends up partially 7093 * behind the camera (which is why the recommendation is to use a distance at 7094 * least as far as the size of the view, if the view is to be rotated.)</p> 7095 * 7096 * <p>The distance is expressed in "depth pixels." The default distance depends 7097 * on the screen density. For instance, on a medium density display, the 7098 * default distance is 1280. On a high density display, the default distance 7099 * is 1920.</p> 7100 * 7101 * <p>If you want to specify a distance that leads to visually consistent 7102 * results across various densities, use the following formula:</p> 7103 * <pre> 7104 * float scale = context.getResources().getDisplayMetrics().density; 7105 * view.setCameraDistance(distance * scale); 7106 * </pre> 7107 * 7108 * <p>The density scale factor of a high density display is 1.5, 7109 * and 1920 = 1280 * 1.5.</p> 7110 * 7111 * @param distance The distance in "depth pixels", if negative the opposite 7112 * value is used 7113 * 7114 * @see #setRotationX(float) 7115 * @see #setRotationY(float) 7116 */ 7117 public void setCameraDistance(float distance) { 7118 invalidateParentCaches(); 7119 invalidate(false); 7120 7121 ensureTransformationInfo(); 7122 final float dpi = mResources.getDisplayMetrics().densityDpi; 7123 final TransformationInfo info = mTransformationInfo; 7124 if (info.mCamera == null) { 7125 info.mCamera = new Camera(); 7126 info.matrix3D = new Matrix(); 7127 } 7128 7129 info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi); 7130 info.mMatrixDirty = true; 7131 7132 invalidate(false); 7133 } 7134 7135 /** 7136 * The degrees that the view is rotated around the pivot point. 7137 * 7138 * @see #setRotation(float) 7139 * @see #getPivotX() 7140 * @see #getPivotY() 7141 * 7142 * @return The degrees of rotation. 7143 */ 7144 public float getRotation() { 7145 return mTransformationInfo != null ? mTransformationInfo.mRotation : 0; 7146 } 7147 7148 /** 7149 * Sets the degrees that the view is rotated around the pivot point. Increasing values 7150 * result in clockwise rotation. 7151 * 7152 * @param rotation The degrees of rotation. 7153 * 7154 * @see #getRotation() 7155 * @see #getPivotX() 7156 * @see #getPivotY() 7157 * @see #setRotationX(float) 7158 * @see #setRotationY(float) 7159 * 7160 * @attr ref android.R.styleable#View_rotation 7161 */ 7162 public void setRotation(float rotation) { 7163 ensureTransformationInfo(); 7164 final TransformationInfo info = mTransformationInfo; 7165 if (info.mRotation != rotation) { 7166 invalidateParentCaches(); 7167 // Double-invalidation is necessary to capture view's old and new areas 7168 invalidate(false); 7169 info.mRotation = rotation; 7170 info.mMatrixDirty = true; 7171 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7172 invalidate(false); 7173 } 7174 } 7175 7176 /** 7177 * The degrees that the view is rotated around the vertical axis through the pivot point. 7178 * 7179 * @see #getPivotX() 7180 * @see #getPivotY() 7181 * @see #setRotationY(float) 7182 * 7183 * @return The degrees of Y rotation. 7184 */ 7185 public float getRotationY() { 7186 return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0; 7187 } 7188 7189 /** 7190 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 7191 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 7192 * down the y axis. 7193 * 7194 * When rotating large views, it is recommended to adjust the camera distance 7195 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 7196 * 7197 * @param rotationY The degrees of Y rotation. 7198 * 7199 * @see #getRotationY() 7200 * @see #getPivotX() 7201 * @see #getPivotY() 7202 * @see #setRotation(float) 7203 * @see #setRotationX(float) 7204 * @see #setCameraDistance(float) 7205 * 7206 * @attr ref android.R.styleable#View_rotationY 7207 */ 7208 public void setRotationY(float rotationY) { 7209 ensureTransformationInfo(); 7210 final TransformationInfo info = mTransformationInfo; 7211 if (info.mRotationY != rotationY) { 7212 invalidateParentCaches(); 7213 // Double-invalidation is necessary to capture view's old and new areas 7214 invalidate(false); 7215 info.mRotationY = rotationY; 7216 info.mMatrixDirty = true; 7217 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7218 invalidate(false); 7219 } 7220 } 7221 7222 /** 7223 * The degrees that the view is rotated around the horizontal axis through the pivot point. 7224 * 7225 * @see #getPivotX() 7226 * @see #getPivotY() 7227 * @see #setRotationX(float) 7228 * 7229 * @return The degrees of X rotation. 7230 */ 7231 public float getRotationX() { 7232 return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0; 7233 } 7234 7235 /** 7236 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 7237 * Increasing values result in clockwise rotation from the viewpoint of looking down the 7238 * x axis. 7239 * 7240 * When rotating large views, it is recommended to adjust the camera distance 7241 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 7242 * 7243 * @param rotationX The degrees of X rotation. 7244 * 7245 * @see #getRotationX() 7246 * @see #getPivotX() 7247 * @see #getPivotY() 7248 * @see #setRotation(float) 7249 * @see #setRotationY(float) 7250 * @see #setCameraDistance(float) 7251 * 7252 * @attr ref android.R.styleable#View_rotationX 7253 */ 7254 public void setRotationX(float rotationX) { 7255 ensureTransformationInfo(); 7256 final TransformationInfo info = mTransformationInfo; 7257 if (info.mRotationX != rotationX) { 7258 invalidateParentCaches(); 7259 // Double-invalidation is necessary to capture view's old and new areas 7260 invalidate(false); 7261 info.mRotationX = rotationX; 7262 info.mMatrixDirty = true; 7263 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7264 invalidate(false); 7265 } 7266 } 7267 7268 /** 7269 * The amount that the view is scaled in x around the pivot point, as a proportion of 7270 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 7271 * 7272 * <p>By default, this is 1.0f. 7273 * 7274 * @see #getPivotX() 7275 * @see #getPivotY() 7276 * @return The scaling factor. 7277 */ 7278 public float getScaleX() { 7279 return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1; 7280 } 7281 7282 /** 7283 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 7284 * the view's unscaled width. A value of 1 means that no scaling is applied. 7285 * 7286 * @param scaleX The scaling factor. 7287 * @see #getPivotX() 7288 * @see #getPivotY() 7289 * 7290 * @attr ref android.R.styleable#View_scaleX 7291 */ 7292 public void setScaleX(float scaleX) { 7293 ensureTransformationInfo(); 7294 final TransformationInfo info = mTransformationInfo; 7295 if (info.mScaleX != scaleX) { 7296 invalidateParentCaches(); 7297 // Double-invalidation is necessary to capture view's old and new areas 7298 invalidate(false); 7299 info.mScaleX = scaleX; 7300 info.mMatrixDirty = true; 7301 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7302 invalidate(false); 7303 } 7304 } 7305 7306 /** 7307 * The amount that the view is scaled in y around the pivot point, as a proportion of 7308 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 7309 * 7310 * <p>By default, this is 1.0f. 7311 * 7312 * @see #getPivotX() 7313 * @see #getPivotY() 7314 * @return The scaling factor. 7315 */ 7316 public float getScaleY() { 7317 return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1; 7318 } 7319 7320 /** 7321 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 7322 * the view's unscaled width. A value of 1 means that no scaling is applied. 7323 * 7324 * @param scaleY The scaling factor. 7325 * @see #getPivotX() 7326 * @see #getPivotY() 7327 * 7328 * @attr ref android.R.styleable#View_scaleY 7329 */ 7330 public void setScaleY(float scaleY) { 7331 ensureTransformationInfo(); 7332 final TransformationInfo info = mTransformationInfo; 7333 if (info.mScaleY != scaleY) { 7334 invalidateParentCaches(); 7335 // Double-invalidation is necessary to capture view's old and new areas 7336 invalidate(false); 7337 info.mScaleY = scaleY; 7338 info.mMatrixDirty = true; 7339 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7340 invalidate(false); 7341 } 7342 } 7343 7344 /** 7345 * The x location of the point around which the view is {@link #setRotation(float) rotated} 7346 * and {@link #setScaleX(float) scaled}. 7347 * 7348 * @see #getRotation() 7349 * @see #getScaleX() 7350 * @see #getScaleY() 7351 * @see #getPivotY() 7352 * @return The x location of the pivot point. 7353 */ 7354 public float getPivotX() { 7355 return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0; 7356 } 7357 7358 /** 7359 * Sets the x location of the point around which the view is 7360 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 7361 * By default, the pivot point is centered on the object. 7362 * Setting this property disables this behavior and causes the view to use only the 7363 * explicitly set pivotX and pivotY values. 7364 * 7365 * @param pivotX The x location of the pivot point. 7366 * @see #getRotation() 7367 * @see #getScaleX() 7368 * @see #getScaleY() 7369 * @see #getPivotY() 7370 * 7371 * @attr ref android.R.styleable#View_transformPivotX 7372 */ 7373 public void setPivotX(float pivotX) { 7374 ensureTransformationInfo(); 7375 mPrivateFlags |= PIVOT_EXPLICITLY_SET; 7376 final TransformationInfo info = mTransformationInfo; 7377 if (info.mPivotX != pivotX) { 7378 invalidateParentCaches(); 7379 // Double-invalidation is necessary to capture view's old and new areas 7380 invalidate(false); 7381 info.mPivotX = pivotX; 7382 info.mMatrixDirty = true; 7383 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7384 invalidate(false); 7385 } 7386 } 7387 7388 /** 7389 * The y location of the point around which the view is {@link #setRotation(float) rotated} 7390 * and {@link #setScaleY(float) scaled}. 7391 * 7392 * @see #getRotation() 7393 * @see #getScaleX() 7394 * @see #getScaleY() 7395 * @see #getPivotY() 7396 * @return The y location of the pivot point. 7397 */ 7398 public float getPivotY() { 7399 return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0; 7400 } 7401 7402 /** 7403 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 7404 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 7405 * Setting this property disables this behavior and causes the view to use only the 7406 * explicitly set pivotX and pivotY values. 7407 * 7408 * @param pivotY The y location of the pivot point. 7409 * @see #getRotation() 7410 * @see #getScaleX() 7411 * @see #getScaleY() 7412 * @see #getPivotY() 7413 * 7414 * @attr ref android.R.styleable#View_transformPivotY 7415 */ 7416 public void setPivotY(float pivotY) { 7417 ensureTransformationInfo(); 7418 mPrivateFlags |= PIVOT_EXPLICITLY_SET; 7419 final TransformationInfo info = mTransformationInfo; 7420 if (info.mPivotY != pivotY) { 7421 invalidateParentCaches(); 7422 // Double-invalidation is necessary to capture view's old and new areas 7423 invalidate(false); 7424 info.mPivotY = pivotY; 7425 info.mMatrixDirty = true; 7426 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7427 invalidate(false); 7428 } 7429 } 7430 7431 /** 7432 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 7433 * completely transparent and 1 means the view is completely opaque. 7434 * 7435 * <p>By default this is 1.0f. 7436 * @return The opacity of the view. 7437 */ 7438 public float getAlpha() { 7439 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 7440 } 7441 7442 /** 7443 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is 7444 * completely transparent and 1 means the view is completely opaque.</p> 7445 * 7446 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 7447 * responsible for applying the opacity itself. Otherwise, calling this method is 7448 * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and 7449 * setting a hardware layer.</p> 7450 * 7451 * @param alpha The opacity of the view. 7452 * 7453 * @see #setLayerType(int, android.graphics.Paint) 7454 * 7455 * @attr ref android.R.styleable#View_alpha 7456 */ 7457 public void setAlpha(float alpha) { 7458 ensureTransformationInfo(); 7459 mTransformationInfo.mAlpha = alpha; 7460 invalidateParentCaches(); 7461 if (onSetAlpha((int) (alpha * 255))) { 7462 mPrivateFlags |= ALPHA_SET; 7463 // subclass is handling alpha - don't optimize rendering cache invalidation 7464 invalidate(true); 7465 } else { 7466 mPrivateFlags &= ~ALPHA_SET; 7467 invalidate(false); 7468 } 7469 } 7470 7471 /** 7472 * Faster version of setAlpha() which performs the same steps except there are 7473 * no calls to invalidate(). The caller of this function should perform proper invalidation 7474 * on the parent and this object. The return value indicates whether the subclass handles 7475 * alpha (the return value for onSetAlpha()). 7476 * 7477 * @param alpha The new value for the alpha property 7478 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) 7479 */ 7480 boolean setAlphaNoInvalidation(float alpha) { 7481 ensureTransformationInfo(); 7482 mTransformationInfo.mAlpha = alpha; 7483 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 7484 if (subclassHandlesAlpha) { 7485 mPrivateFlags |= ALPHA_SET; 7486 } else { 7487 mPrivateFlags &= ~ALPHA_SET; 7488 } 7489 return subclassHandlesAlpha; 7490 } 7491 7492 /** 7493 * Top position of this view relative to its parent. 7494 * 7495 * @return The top of this view, in pixels. 7496 */ 7497 @ViewDebug.CapturedViewProperty 7498 public final int getTop() { 7499 return mTop; 7500 } 7501 7502 /** 7503 * Sets the top position of this view relative to its parent. This method is meant to be called 7504 * by the layout system and should not generally be called otherwise, because the property 7505 * may be changed at any time by the layout. 7506 * 7507 * @param top The top of this view, in pixels. 7508 */ 7509 public final void setTop(int top) { 7510 if (top != mTop) { 7511 updateMatrix(); 7512 final boolean matrixIsIdentity = mTransformationInfo == null 7513 || mTransformationInfo.mMatrixIsIdentity; 7514 if (matrixIsIdentity) { 7515 if (mAttachInfo != null) { 7516 int minTop; 7517 int yLoc; 7518 if (top < mTop) { 7519 minTop = top; 7520 yLoc = top - mTop; 7521 } else { 7522 minTop = mTop; 7523 yLoc = 0; 7524 } 7525 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 7526 } 7527 } else { 7528 // Double-invalidation is necessary to capture view's old and new areas 7529 invalidate(true); 7530 } 7531 7532 int width = mRight - mLeft; 7533 int oldHeight = mBottom - mTop; 7534 7535 mTop = top; 7536 7537 onSizeChanged(width, mBottom - mTop, width, oldHeight); 7538 7539 if (!matrixIsIdentity) { 7540 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 7541 // A change in dimension means an auto-centered pivot point changes, too 7542 mTransformationInfo.mMatrixDirty = true; 7543 } 7544 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7545 invalidate(true); 7546 } 7547 mBackgroundSizeChanged = true; 7548 invalidateParentIfNeeded(); 7549 } 7550 } 7551 7552 /** 7553 * Bottom position of this view relative to its parent. 7554 * 7555 * @return The bottom of this view, in pixels. 7556 */ 7557 @ViewDebug.CapturedViewProperty 7558 public final int getBottom() { 7559 return mBottom; 7560 } 7561 7562 /** 7563 * True if this view has changed since the last time being drawn. 7564 * 7565 * @return The dirty state of this view. 7566 */ 7567 public boolean isDirty() { 7568 return (mPrivateFlags & DIRTY_MASK) != 0; 7569 } 7570 7571 /** 7572 * Sets the bottom position of this view relative to its parent. This method is meant to be 7573 * called by the layout system and should not generally be called otherwise, because the 7574 * property may be changed at any time by the layout. 7575 * 7576 * @param bottom The bottom of this view, in pixels. 7577 */ 7578 public final void setBottom(int bottom) { 7579 if (bottom != mBottom) { 7580 updateMatrix(); 7581 final boolean matrixIsIdentity = mTransformationInfo == null 7582 || mTransformationInfo.mMatrixIsIdentity; 7583 if (matrixIsIdentity) { 7584 if (mAttachInfo != null) { 7585 int maxBottom; 7586 if (bottom < mBottom) { 7587 maxBottom = mBottom; 7588 } else { 7589 maxBottom = bottom; 7590 } 7591 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 7592 } 7593 } else { 7594 // Double-invalidation is necessary to capture view's old and new areas 7595 invalidate(true); 7596 } 7597 7598 int width = mRight - mLeft; 7599 int oldHeight = mBottom - mTop; 7600 7601 mBottom = bottom; 7602 7603 onSizeChanged(width, mBottom - mTop, width, oldHeight); 7604 7605 if (!matrixIsIdentity) { 7606 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 7607 // A change in dimension means an auto-centered pivot point changes, too 7608 mTransformationInfo.mMatrixDirty = true; 7609 } 7610 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7611 invalidate(true); 7612 } 7613 mBackgroundSizeChanged = true; 7614 invalidateParentIfNeeded(); 7615 } 7616 } 7617 7618 /** 7619 * Left position of this view relative to its parent. 7620 * 7621 * @return The left edge of this view, in pixels. 7622 */ 7623 @ViewDebug.CapturedViewProperty 7624 public final int getLeft() { 7625 return mLeft; 7626 } 7627 7628 /** 7629 * Sets the left position of this view relative to its parent. This method is meant to be called 7630 * by the layout system and should not generally be called otherwise, because the property 7631 * may be changed at any time by the layout. 7632 * 7633 * @param left The bottom of this view, in pixels. 7634 */ 7635 public final void setLeft(int left) { 7636 if (left != mLeft) { 7637 updateMatrix(); 7638 final boolean matrixIsIdentity = mTransformationInfo == null 7639 || mTransformationInfo.mMatrixIsIdentity; 7640 if (matrixIsIdentity) { 7641 if (mAttachInfo != null) { 7642 int minLeft; 7643 int xLoc; 7644 if (left < mLeft) { 7645 minLeft = left; 7646 xLoc = left - mLeft; 7647 } else { 7648 minLeft = mLeft; 7649 xLoc = 0; 7650 } 7651 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 7652 } 7653 } else { 7654 // Double-invalidation is necessary to capture view's old and new areas 7655 invalidate(true); 7656 } 7657 7658 int oldWidth = mRight - mLeft; 7659 int height = mBottom - mTop; 7660 7661 mLeft = left; 7662 7663 onSizeChanged(mRight - mLeft, height, oldWidth, height); 7664 7665 if (!matrixIsIdentity) { 7666 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 7667 // A change in dimension means an auto-centered pivot point changes, too 7668 mTransformationInfo.mMatrixDirty = true; 7669 } 7670 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7671 invalidate(true); 7672 } 7673 mBackgroundSizeChanged = true; 7674 invalidateParentIfNeeded(); 7675 } 7676 } 7677 7678 /** 7679 * Right position of this view relative to its parent. 7680 * 7681 * @return The right edge of this view, in pixels. 7682 */ 7683 @ViewDebug.CapturedViewProperty 7684 public final int getRight() { 7685 return mRight; 7686 } 7687 7688 /** 7689 * Sets the right position of this view relative to its parent. This method is meant to be called 7690 * by the layout system and should not generally be called otherwise, because the property 7691 * may be changed at any time by the layout. 7692 * 7693 * @param right The bottom of this view, in pixels. 7694 */ 7695 public final void setRight(int right) { 7696 if (right != mRight) { 7697 updateMatrix(); 7698 final boolean matrixIsIdentity = mTransformationInfo == null 7699 || mTransformationInfo.mMatrixIsIdentity; 7700 if (matrixIsIdentity) { 7701 if (mAttachInfo != null) { 7702 int maxRight; 7703 if (right < mRight) { 7704 maxRight = mRight; 7705 } else { 7706 maxRight = right; 7707 } 7708 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 7709 } 7710 } else { 7711 // Double-invalidation is necessary to capture view's old and new areas 7712 invalidate(true); 7713 } 7714 7715 int oldWidth = mRight - mLeft; 7716 int height = mBottom - mTop; 7717 7718 mRight = right; 7719 7720 onSizeChanged(mRight - mLeft, height, oldWidth, height); 7721 7722 if (!matrixIsIdentity) { 7723 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 7724 // A change in dimension means an auto-centered pivot point changes, too 7725 mTransformationInfo.mMatrixDirty = true; 7726 } 7727 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7728 invalidate(true); 7729 } 7730 mBackgroundSizeChanged = true; 7731 invalidateParentIfNeeded(); 7732 } 7733 } 7734 7735 /** 7736 * The visual x position of this view, in pixels. This is equivalent to the 7737 * {@link #setTranslationX(float) translationX} property plus the current 7738 * {@link #getLeft() left} property. 7739 * 7740 * @return The visual x position of this view, in pixels. 7741 */ 7742 public float getX() { 7743 return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0); 7744 } 7745 7746 /** 7747 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 7748 * {@link #setTranslationX(float) translationX} property to be the difference between 7749 * the x value passed in and the current {@link #getLeft() left} property. 7750 * 7751 * @param x The visual x position of this view, in pixels. 7752 */ 7753 public void setX(float x) { 7754 setTranslationX(x - mLeft); 7755 } 7756 7757 /** 7758 * The visual y position of this view, in pixels. This is equivalent to the 7759 * {@link #setTranslationY(float) translationY} property plus the current 7760 * {@link #getTop() top} property. 7761 * 7762 * @return The visual y position of this view, in pixels. 7763 */ 7764 public float getY() { 7765 return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0); 7766 } 7767 7768 /** 7769 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 7770 * {@link #setTranslationY(float) translationY} property to be the difference between 7771 * the y value passed in and the current {@link #getTop() top} property. 7772 * 7773 * @param y The visual y position of this view, in pixels. 7774 */ 7775 public void setY(float y) { 7776 setTranslationY(y - mTop); 7777 } 7778 7779 7780 /** 7781 * The horizontal location of this view relative to its {@link #getLeft() left} position. 7782 * This position is post-layout, in addition to wherever the object's 7783 * layout placed it. 7784 * 7785 * @return The horizontal position of this view relative to its left position, in pixels. 7786 */ 7787 public float getTranslationX() { 7788 return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0; 7789 } 7790 7791 /** 7792 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 7793 * This effectively positions the object post-layout, in addition to wherever the object's 7794 * layout placed it. 7795 * 7796 * @param translationX The horizontal position of this view relative to its left position, 7797 * in pixels. 7798 * 7799 * @attr ref android.R.styleable#View_translationX 7800 */ 7801 public void setTranslationX(float translationX) { 7802 ensureTransformationInfo(); 7803 final TransformationInfo info = mTransformationInfo; 7804 if (info.mTranslationX != translationX) { 7805 invalidateParentCaches(); 7806 // Double-invalidation is necessary to capture view's old and new areas 7807 invalidate(false); 7808 info.mTranslationX = translationX; 7809 info.mMatrixDirty = true; 7810 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7811 invalidate(false); 7812 } 7813 } 7814 7815 /** 7816 * The horizontal location of this view relative to its {@link #getTop() top} position. 7817 * This position is post-layout, in addition to wherever the object's 7818 * layout placed it. 7819 * 7820 * @return The vertical position of this view relative to its top position, 7821 * in pixels. 7822 */ 7823 public float getTranslationY() { 7824 return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0; 7825 } 7826 7827 /** 7828 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 7829 * This effectively positions the object post-layout, in addition to wherever the object's 7830 * layout placed it. 7831 * 7832 * @param translationY The vertical position of this view relative to its top position, 7833 * in pixels. 7834 * 7835 * @attr ref android.R.styleable#View_translationY 7836 */ 7837 public void setTranslationY(float translationY) { 7838 ensureTransformationInfo(); 7839 final TransformationInfo info = mTransformationInfo; 7840 if (info.mTranslationY != translationY) { 7841 invalidateParentCaches(); 7842 // Double-invalidation is necessary to capture view's old and new areas 7843 invalidate(false); 7844 info.mTranslationY = translationY; 7845 info.mMatrixDirty = true; 7846 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 7847 invalidate(false); 7848 } 7849 } 7850 7851 /** 7852 * @hide 7853 */ 7854 public void setFastTranslationX(float x) { 7855 ensureTransformationInfo(); 7856 final TransformationInfo info = mTransformationInfo; 7857 info.mTranslationX = x; 7858 info.mMatrixDirty = true; 7859 } 7860 7861 /** 7862 * @hide 7863 */ 7864 public void setFastTranslationY(float y) { 7865 ensureTransformationInfo(); 7866 final TransformationInfo info = mTransformationInfo; 7867 info.mTranslationY = y; 7868 info.mMatrixDirty = true; 7869 } 7870 7871 /** 7872 * @hide 7873 */ 7874 public void setFastX(float x) { 7875 ensureTransformationInfo(); 7876 final TransformationInfo info = mTransformationInfo; 7877 info.mTranslationX = x - mLeft; 7878 info.mMatrixDirty = true; 7879 } 7880 7881 /** 7882 * @hide 7883 */ 7884 public void setFastY(float y) { 7885 ensureTransformationInfo(); 7886 final TransformationInfo info = mTransformationInfo; 7887 info.mTranslationY = y - mTop; 7888 info.mMatrixDirty = true; 7889 } 7890 7891 /** 7892 * @hide 7893 */ 7894 public void setFastScaleX(float x) { 7895 ensureTransformationInfo(); 7896 final TransformationInfo info = mTransformationInfo; 7897 info.mScaleX = x; 7898 info.mMatrixDirty = true; 7899 } 7900 7901 /** 7902 * @hide 7903 */ 7904 public void setFastScaleY(float y) { 7905 ensureTransformationInfo(); 7906 final TransformationInfo info = mTransformationInfo; 7907 info.mScaleY = y; 7908 info.mMatrixDirty = true; 7909 } 7910 7911 /** 7912 * @hide 7913 */ 7914 public void setFastAlpha(float alpha) { 7915 ensureTransformationInfo(); 7916 mTransformationInfo.mAlpha = alpha; 7917 } 7918 7919 /** 7920 * @hide 7921 */ 7922 public void setFastRotationY(float y) { 7923 ensureTransformationInfo(); 7924 final TransformationInfo info = mTransformationInfo; 7925 info.mRotationY = y; 7926 info.mMatrixDirty = true; 7927 } 7928 7929 /** 7930 * Hit rectangle in parent's coordinates 7931 * 7932 * @param outRect The hit rectangle of the view. 7933 */ 7934 public void getHitRect(Rect outRect) { 7935 updateMatrix(); 7936 final TransformationInfo info = mTransformationInfo; 7937 if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) { 7938 outRect.set(mLeft, mTop, mRight, mBottom); 7939 } else { 7940 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 7941 tmpRect.set(-info.mPivotX, -info.mPivotY, 7942 getWidth() - info.mPivotX, getHeight() - info.mPivotY); 7943 info.mMatrix.mapRect(tmpRect); 7944 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 7945 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 7946 } 7947 } 7948 7949 /** 7950 * Determines whether the given point, in local coordinates is inside the view. 7951 */ 7952 /*package*/ final boolean pointInView(float localX, float localY) { 7953 return localX >= 0 && localX < (mRight - mLeft) 7954 && localY >= 0 && localY < (mBottom - mTop); 7955 } 7956 7957 /** 7958 * Utility method to determine whether the given point, in local coordinates, 7959 * is inside the view, where the area of the view is expanded by the slop factor. 7960 * This method is called while processing touch-move events to determine if the event 7961 * is still within the view. 7962 */ 7963 private boolean pointInView(float localX, float localY, float slop) { 7964 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 7965 localY < ((mBottom - mTop) + slop); 7966 } 7967 7968 /** 7969 * When a view has focus and the user navigates away from it, the next view is searched for 7970 * starting from the rectangle filled in by this method. 7971 * 7972 * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)}) 7973 * of the view. However, if your view maintains some idea of internal selection, 7974 * such as a cursor, or a selected row or column, you should override this method and 7975 * fill in a more specific rectangle. 7976 * 7977 * @param r The rectangle to fill in, in this view's coordinates. 7978 */ 7979 public void getFocusedRect(Rect r) { 7980 getDrawingRect(r); 7981 } 7982 7983 /** 7984 * If some part of this view is not clipped by any of its parents, then 7985 * return that area in r in global (root) coordinates. To convert r to local 7986 * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x, 7987 * -globalOffset.y)) If the view is completely clipped or translated out, 7988 * return false. 7989 * 7990 * @param r If true is returned, r holds the global coordinates of the 7991 * visible portion of this view. 7992 * @param globalOffset If true is returned, globalOffset holds the dx,dy 7993 * between this view and its root. globalOffet may be null. 7994 * @return true if r is non-empty (i.e. part of the view is visible at the 7995 * root level. 7996 */ 7997 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 7998 int width = mRight - mLeft; 7999 int height = mBottom - mTop; 8000 if (width > 0 && height > 0) { 8001 r.set(0, 0, width, height); 8002 if (globalOffset != null) { 8003 globalOffset.set(-mScrollX, -mScrollY); 8004 } 8005 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 8006 } 8007 return false; 8008 } 8009 8010 public final boolean getGlobalVisibleRect(Rect r) { 8011 return getGlobalVisibleRect(r, null); 8012 } 8013 8014 public final boolean getLocalVisibleRect(Rect r) { 8015 Point offset = new Point(); 8016 if (getGlobalVisibleRect(r, offset)) { 8017 r.offset(-offset.x, -offset.y); // make r local 8018 return true; 8019 } 8020 return false; 8021 } 8022 8023 /** 8024 * Offset this view's vertical location by the specified number of pixels. 8025 * 8026 * @param offset the number of pixels to offset the view by 8027 */ 8028 public void offsetTopAndBottom(int offset) { 8029 if (offset != 0) { 8030 updateMatrix(); 8031 final boolean matrixIsIdentity = mTransformationInfo == null 8032 || mTransformationInfo.mMatrixIsIdentity; 8033 if (matrixIsIdentity) { 8034 final ViewParent p = mParent; 8035 if (p != null && mAttachInfo != null) { 8036 final Rect r = mAttachInfo.mTmpInvalRect; 8037 int minTop; 8038 int maxBottom; 8039 int yLoc; 8040 if (offset < 0) { 8041 minTop = mTop + offset; 8042 maxBottom = mBottom; 8043 yLoc = offset; 8044 } else { 8045 minTop = mTop; 8046 maxBottom = mBottom + offset; 8047 yLoc = 0; 8048 } 8049 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 8050 p.invalidateChild(this, r); 8051 } 8052 } else { 8053 invalidate(false); 8054 } 8055 8056 mTop += offset; 8057 mBottom += offset; 8058 8059 if (!matrixIsIdentity) { 8060 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 8061 invalidate(false); 8062 } 8063 invalidateParentIfNeeded(); 8064 } 8065 } 8066 8067 /** 8068 * Offset this view's horizontal location by the specified amount of pixels. 8069 * 8070 * @param offset the numer of pixels to offset the view by 8071 */ 8072 public void offsetLeftAndRight(int offset) { 8073 if (offset != 0) { 8074 updateMatrix(); 8075 final boolean matrixIsIdentity = mTransformationInfo == null 8076 || mTransformationInfo.mMatrixIsIdentity; 8077 if (matrixIsIdentity) { 8078 final ViewParent p = mParent; 8079 if (p != null && mAttachInfo != null) { 8080 final Rect r = mAttachInfo.mTmpInvalRect; 8081 int minLeft; 8082 int maxRight; 8083 if (offset < 0) { 8084 minLeft = mLeft + offset; 8085 maxRight = mRight; 8086 } else { 8087 minLeft = mLeft; 8088 maxRight = mRight + offset; 8089 } 8090 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 8091 p.invalidateChild(this, r); 8092 } 8093 } else { 8094 invalidate(false); 8095 } 8096 8097 mLeft += offset; 8098 mRight += offset; 8099 8100 if (!matrixIsIdentity) { 8101 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation 8102 invalidate(false); 8103 } 8104 invalidateParentIfNeeded(); 8105 } 8106 } 8107 8108 /** 8109 * Get the LayoutParams associated with this view. All views should have 8110 * layout parameters. These supply parameters to the <i>parent</i> of this 8111 * view specifying how it should be arranged. There are many subclasses of 8112 * ViewGroup.LayoutParams, and these correspond to the different subclasses 8113 * of ViewGroup that are responsible for arranging their children. 8114 * 8115 * This method may return null if this View is not attached to a parent 8116 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 8117 * was not invoked successfully. When a View is attached to a parent 8118 * ViewGroup, this method must not return null. 8119 * 8120 * @return The LayoutParams associated with this view, or null if no 8121 * parameters have been set yet 8122 */ 8123 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 8124 public ViewGroup.LayoutParams getLayoutParams() { 8125 return mLayoutParams; 8126 } 8127 8128 /** 8129 * Set the layout parameters associated with this view. These supply 8130 * parameters to the <i>parent</i> of this view specifying how it should be 8131 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 8132 * correspond to the different subclasses of ViewGroup that are responsible 8133 * for arranging their children. 8134 * 8135 * @param params The layout parameters for this view, cannot be null 8136 */ 8137 public void setLayoutParams(ViewGroup.LayoutParams params) { 8138 if (params == null) { 8139 throw new NullPointerException("Layout parameters cannot be null"); 8140 } 8141 mLayoutParams = params; 8142 requestLayout(); 8143 } 8144 8145 /** 8146 * Set the scrolled position of your view. This will cause a call to 8147 * {@link #onScrollChanged(int, int, int, int)} and the view will be 8148 * invalidated. 8149 * @param x the x position to scroll to 8150 * @param y the y position to scroll to 8151 */ 8152 public void scrollTo(int x, int y) { 8153 if (mScrollX != x || mScrollY != y) { 8154 int oldX = mScrollX; 8155 int oldY = mScrollY; 8156 mScrollX = x; 8157 mScrollY = y; 8158 invalidateParentCaches(); 8159 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 8160 if (!awakenScrollBars()) { 8161 invalidate(true); 8162 } 8163 } 8164 } 8165 8166 /** 8167 * Move the scrolled position of your view. This will cause a call to 8168 * {@link #onScrollChanged(int, int, int, int)} and the view will be 8169 * invalidated. 8170 * @param x the amount of pixels to scroll by horizontally 8171 * @param y the amount of pixels to scroll by vertically 8172 */ 8173 public void scrollBy(int x, int y) { 8174 scrollTo(mScrollX + x, mScrollY + y); 8175 } 8176 8177 /** 8178 * <p>Trigger the scrollbars to draw. When invoked this method starts an 8179 * animation to fade the scrollbars out after a default delay. If a subclass 8180 * provides animated scrolling, the start delay should equal the duration 8181 * of the scrolling animation.</p> 8182 * 8183 * <p>The animation starts only if at least one of the scrollbars is 8184 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 8185 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 8186 * this method returns true, and false otherwise. If the animation is 8187 * started, this method calls {@link #invalidate()}; in that case the 8188 * caller should not call {@link #invalidate()}.</p> 8189 * 8190 * <p>This method should be invoked every time a subclass directly updates 8191 * the scroll parameters.</p> 8192 * 8193 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 8194 * and {@link #scrollTo(int, int)}.</p> 8195 * 8196 * @return true if the animation is played, false otherwise 8197 * 8198 * @see #awakenScrollBars(int) 8199 * @see #scrollBy(int, int) 8200 * @see #scrollTo(int, int) 8201 * @see #isHorizontalScrollBarEnabled() 8202 * @see #isVerticalScrollBarEnabled() 8203 * @see #setHorizontalScrollBarEnabled(boolean) 8204 * @see #setVerticalScrollBarEnabled(boolean) 8205 */ 8206 protected boolean awakenScrollBars() { 8207 return mScrollCache != null && 8208 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 8209 } 8210 8211 /** 8212 * Trigger the scrollbars to draw. 8213 * This method differs from awakenScrollBars() only in its default duration. 8214 * initialAwakenScrollBars() will show the scroll bars for longer than 8215 * usual to give the user more of a chance to notice them. 8216 * 8217 * @return true if the animation is played, false otherwise. 8218 */ 8219 private boolean initialAwakenScrollBars() { 8220 return mScrollCache != null && 8221 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 8222 } 8223 8224 /** 8225 * <p> 8226 * Trigger the scrollbars to draw. When invoked this method starts an 8227 * animation to fade the scrollbars out after a fixed delay. If a subclass 8228 * provides animated scrolling, the start delay should equal the duration of 8229 * the scrolling animation. 8230 * </p> 8231 * 8232 * <p> 8233 * The animation starts only if at least one of the scrollbars is enabled, 8234 * as specified by {@link #isHorizontalScrollBarEnabled()} and 8235 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 8236 * this method returns true, and false otherwise. If the animation is 8237 * started, this method calls {@link #invalidate()}; in that case the caller 8238 * should not call {@link #invalidate()}. 8239 * </p> 8240 * 8241 * <p> 8242 * This method should be invoked everytime a subclass directly updates the 8243 * scroll parameters. 8244 * </p> 8245 * 8246 * @param startDelay the delay, in milliseconds, after which the animation 8247 * should start; when the delay is 0, the animation starts 8248 * immediately 8249 * @return true if the animation is played, false otherwise 8250 * 8251 * @see #scrollBy(int, int) 8252 * @see #scrollTo(int, int) 8253 * @see #isHorizontalScrollBarEnabled() 8254 * @see #isVerticalScrollBarEnabled() 8255 * @see #setHorizontalScrollBarEnabled(boolean) 8256 * @see #setVerticalScrollBarEnabled(boolean) 8257 */ 8258 protected boolean awakenScrollBars(int startDelay) { 8259 return awakenScrollBars(startDelay, true); 8260 } 8261 8262 /** 8263 * <p> 8264 * Trigger the scrollbars to draw. When invoked this method starts an 8265 * animation to fade the scrollbars out after a fixed delay. If a subclass 8266 * provides animated scrolling, the start delay should equal the duration of 8267 * the scrolling animation. 8268 * </p> 8269 * 8270 * <p> 8271 * The animation starts only if at least one of the scrollbars is enabled, 8272 * as specified by {@link #isHorizontalScrollBarEnabled()} and 8273 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 8274 * this method returns true, and false otherwise. If the animation is 8275 * started, this method calls {@link #invalidate()} if the invalidate parameter 8276 * is set to true; in that case the caller 8277 * should not call {@link #invalidate()}. 8278 * </p> 8279 * 8280 * <p> 8281 * This method should be invoked everytime a subclass directly updates the 8282 * scroll parameters. 8283 * </p> 8284 * 8285 * @param startDelay the delay, in milliseconds, after which the animation 8286 * should start; when the delay is 0, the animation starts 8287 * immediately 8288 * 8289 * @param invalidate Wheter this method should call invalidate 8290 * 8291 * @return true if the animation is played, false otherwise 8292 * 8293 * @see #scrollBy(int, int) 8294 * @see #scrollTo(int, int) 8295 * @see #isHorizontalScrollBarEnabled() 8296 * @see #isVerticalScrollBarEnabled() 8297 * @see #setHorizontalScrollBarEnabled(boolean) 8298 * @see #setVerticalScrollBarEnabled(boolean) 8299 */ 8300 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 8301 final ScrollabilityCache scrollCache = mScrollCache; 8302 8303 if (scrollCache == null || !scrollCache.fadeScrollBars) { 8304 return false; 8305 } 8306 8307 if (scrollCache.scrollBar == null) { 8308 scrollCache.scrollBar = new ScrollBarDrawable(); 8309 } 8310 8311 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 8312 8313 if (invalidate) { 8314 // Invalidate to show the scrollbars 8315 invalidate(true); 8316 } 8317 8318 if (scrollCache.state == ScrollabilityCache.OFF) { 8319 // FIXME: this is copied from WindowManagerService. 8320 // We should get this value from the system when it 8321 // is possible to do so. 8322 final int KEY_REPEAT_FIRST_DELAY = 750; 8323 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 8324 } 8325 8326 // Tell mScrollCache when we should start fading. This may 8327 // extend the fade start time if one was already scheduled 8328 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 8329 scrollCache.fadeStartTime = fadeStartTime; 8330 scrollCache.state = ScrollabilityCache.ON; 8331 8332 // Schedule our fader to run, unscheduling any old ones first 8333 if (mAttachInfo != null) { 8334 mAttachInfo.mHandler.removeCallbacks(scrollCache); 8335 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 8336 } 8337 8338 return true; 8339 } 8340 8341 return false; 8342 } 8343 8344 /** 8345 * Do not invalidate views which are not visible and which are not running an animation. They 8346 * will not get drawn and they should not set dirty flags as if they will be drawn 8347 */ 8348 private boolean skipInvalidate() { 8349 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 8350 (!(mParent instanceof ViewGroup) || 8351 !((ViewGroup) mParent).isViewTransitioning(this)); 8352 } 8353 /** 8354 * Mark the the area defined by dirty as needing to be drawn. If the view is 8355 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point 8356 * in the future. This must be called from a UI thread. To call from a non-UI 8357 * thread, call {@link #postInvalidate()}. 8358 * 8359 * WARNING: This method is destructive to dirty. 8360 * @param dirty the rectangle representing the bounds of the dirty region 8361 */ 8362 public void invalidate(Rect dirty) { 8363 if (ViewDebug.TRACE_HIERARCHY) { 8364 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 8365 } 8366 8367 if (skipInvalidate()) { 8368 return; 8369 } 8370 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || 8371 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID || 8372 (mPrivateFlags & INVALIDATED) != INVALIDATED) { 8373 mPrivateFlags &= ~DRAWING_CACHE_VALID; 8374 mPrivateFlags |= INVALIDATED; 8375 mPrivateFlags |= DIRTY; 8376 final ViewParent p = mParent; 8377 final AttachInfo ai = mAttachInfo; 8378 //noinspection PointlessBooleanExpression,ConstantConditions 8379 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 8380 if (p != null && ai != null && ai.mHardwareAccelerated) { 8381 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 8382 // with a null dirty rect, which tells the ViewAncestor to redraw everything 8383 p.invalidateChild(this, null); 8384 return; 8385 } 8386 } 8387 if (p != null && ai != null) { 8388 final int scrollX = mScrollX; 8389 final int scrollY = mScrollY; 8390 final Rect r = ai.mTmpInvalRect; 8391 r.set(dirty.left - scrollX, dirty.top - scrollY, 8392 dirty.right - scrollX, dirty.bottom - scrollY); 8393 mParent.invalidateChild(this, r); 8394 } 8395 } 8396 } 8397 8398 /** 8399 * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn. 8400 * The coordinates of the dirty rect are relative to the view. 8401 * If the view is visible, {@link #onDraw(android.graphics.Canvas)} 8402 * will be called at some point in the future. This must be called from 8403 * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. 8404 * @param l the left position of the dirty region 8405 * @param t the top position of the dirty region 8406 * @param r the right position of the dirty region 8407 * @param b the bottom position of the dirty region 8408 */ 8409 public void invalidate(int l, int t, int r, int b) { 8410 if (ViewDebug.TRACE_HIERARCHY) { 8411 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 8412 } 8413 8414 if (skipInvalidate()) { 8415 return; 8416 } 8417 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || 8418 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID || 8419 (mPrivateFlags & INVALIDATED) != INVALIDATED) { 8420 mPrivateFlags &= ~DRAWING_CACHE_VALID; 8421 mPrivateFlags |= INVALIDATED; 8422 mPrivateFlags |= DIRTY; 8423 final ViewParent p = mParent; 8424 final AttachInfo ai = mAttachInfo; 8425 //noinspection PointlessBooleanExpression,ConstantConditions 8426 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 8427 if (p != null && ai != null && ai.mHardwareAccelerated) { 8428 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 8429 // with a null dirty rect, which tells the ViewAncestor to redraw everything 8430 p.invalidateChild(this, null); 8431 return; 8432 } 8433 } 8434 if (p != null && ai != null && l < r && t < b) { 8435 final int scrollX = mScrollX; 8436 final int scrollY = mScrollY; 8437 final Rect tmpr = ai.mTmpInvalRect; 8438 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); 8439 p.invalidateChild(this, tmpr); 8440 } 8441 } 8442 } 8443 8444 /** 8445 * Invalidate the whole view. If the view is visible, 8446 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 8447 * the future. This must be called from a UI thread. To call from a non-UI thread, 8448 * call {@link #postInvalidate()}. 8449 */ 8450 public void invalidate() { 8451 invalidate(true); 8452 } 8453 8454 /** 8455 * This is where the invalidate() work actually happens. A full invalidate() 8456 * causes the drawing cache to be invalidated, but this function can be called with 8457 * invalidateCache set to false to skip that invalidation step for cases that do not 8458 * need it (for example, a component that remains at the same dimensions with the same 8459 * content). 8460 * 8461 * @param invalidateCache Whether the drawing cache for this view should be invalidated as 8462 * well. This is usually true for a full invalidate, but may be set to false if the 8463 * View's contents or dimensions have not changed. 8464 */ 8465 void invalidate(boolean invalidateCache) { 8466 if (ViewDebug.TRACE_HIERARCHY) { 8467 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 8468 } 8469 8470 if (skipInvalidate()) { 8471 return; 8472 } 8473 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || 8474 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) || 8475 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) { 8476 mLastIsOpaque = isOpaque(); 8477 mPrivateFlags &= ~DRAWN; 8478 mPrivateFlags |= DIRTY; 8479 if (invalidateCache) { 8480 mPrivateFlags |= INVALIDATED; 8481 mPrivateFlags &= ~DRAWING_CACHE_VALID; 8482 } 8483 final AttachInfo ai = mAttachInfo; 8484 final ViewParent p = mParent; 8485 //noinspection PointlessBooleanExpression,ConstantConditions 8486 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) { 8487 if (p != null && ai != null && ai.mHardwareAccelerated) { 8488 // fast-track for GL-enabled applications; just invalidate the whole hierarchy 8489 // with a null dirty rect, which tells the ViewAncestor to redraw everything 8490 p.invalidateChild(this, null); 8491 return; 8492 } 8493 } 8494 8495 if (p != null && ai != null) { 8496 final Rect r = ai.mTmpInvalRect; 8497 r.set(0, 0, mRight - mLeft, mBottom - mTop); 8498 // Don't call invalidate -- we don't want to internally scroll 8499 // our own bounds 8500 p.invalidateChild(this, r); 8501 } 8502 } 8503 } 8504 8505 /** 8506 * @hide 8507 */ 8508 public void fastInvalidate() { 8509 if (skipInvalidate()) { 8510 return; 8511 } 8512 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) || 8513 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID || 8514 (mPrivateFlags & INVALIDATED) != INVALIDATED) { 8515 if (mParent instanceof View) { 8516 ((View) mParent).mPrivateFlags |= INVALIDATED; 8517 } 8518 mPrivateFlags &= ~DRAWN; 8519 mPrivateFlags |= DIRTY; 8520 mPrivateFlags |= INVALIDATED; 8521 mPrivateFlags &= ~DRAWING_CACHE_VALID; 8522 if (mParent != null && mAttachInfo != null) { 8523 if (mAttachInfo.mHardwareAccelerated) { 8524 mParent.invalidateChild(this, null); 8525 } else { 8526 final Rect r = mAttachInfo.mTmpInvalRect; 8527 r.set(0, 0, mRight - mLeft, mBottom - mTop); 8528 // Don't call invalidate -- we don't want to internally scroll 8529 // our own bounds 8530 mParent.invalidateChild(this, r); 8531 } 8532 } 8533 } 8534 } 8535 8536 /** 8537 * Used to indicate that the parent of this view should clear its caches. This functionality 8538 * is used to force the parent to rebuild its display list (when hardware-accelerated), 8539 * which is necessary when various parent-managed properties of the view change, such as 8540 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 8541 * clears the parent caches and does not causes an invalidate event. 8542 * 8543 * @hide 8544 */ 8545 protected void invalidateParentCaches() { 8546 if (mParent instanceof View) { 8547 ((View) mParent).mPrivateFlags |= INVALIDATED; 8548 } 8549 } 8550 8551 /** 8552 * Used to indicate that the parent of this view should be invalidated. This functionality 8553 * is used to force the parent to rebuild its display list (when hardware-accelerated), 8554 * which is necessary when various parent-managed properties of the view change, such as 8555 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 8556 * an invalidation event to the parent. 8557 * 8558 * @hide 8559 */ 8560 protected void invalidateParentIfNeeded() { 8561 if (isHardwareAccelerated() && mParent instanceof View) { 8562 ((View) mParent).invalidate(true); 8563 } 8564 } 8565 8566 /** 8567 * Indicates whether this View is opaque. An opaque View guarantees that it will 8568 * draw all the pixels overlapping its bounds using a fully opaque color. 8569 * 8570 * Subclasses of View should override this method whenever possible to indicate 8571 * whether an instance is opaque. Opaque Views are treated in a special way by 8572 * the View hierarchy, possibly allowing it to perform optimizations during 8573 * invalidate/draw passes. 8574 * 8575 * @return True if this View is guaranteed to be fully opaque, false otherwise. 8576 */ 8577 @ViewDebug.ExportedProperty(category = "drawing") 8578 public boolean isOpaque() { 8579 return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK && 8580 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1) 8581 >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD); 8582 } 8583 8584 /** 8585 * @hide 8586 */ 8587 protected void computeOpaqueFlags() { 8588 // Opaque if: 8589 // - Has a background 8590 // - Background is opaque 8591 // - Doesn't have scrollbars or scrollbars are inside overlay 8592 8593 if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) { 8594 mPrivateFlags |= OPAQUE_BACKGROUND; 8595 } else { 8596 mPrivateFlags &= ~OPAQUE_BACKGROUND; 8597 } 8598 8599 final int flags = mViewFlags; 8600 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 8601 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) { 8602 mPrivateFlags |= OPAQUE_SCROLLBARS; 8603 } else { 8604 mPrivateFlags &= ~OPAQUE_SCROLLBARS; 8605 } 8606 } 8607 8608 /** 8609 * @hide 8610 */ 8611 protected boolean hasOpaqueScrollbars() { 8612 return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS; 8613 } 8614 8615 /** 8616 * @return A handler associated with the thread running the View. This 8617 * handler can be used to pump events in the UI events queue. 8618 */ 8619 public Handler getHandler() { 8620 if (mAttachInfo != null) { 8621 return mAttachInfo.mHandler; 8622 } 8623 return null; 8624 } 8625 8626 /** 8627 * <p>Causes the Runnable to be added to the message queue. 8628 * The runnable will be run on the user interface thread.</p> 8629 * 8630 * <p>This method can be invoked from outside of the UI thread 8631 * only when this View is attached to a window.</p> 8632 * 8633 * @param action The Runnable that will be executed. 8634 * 8635 * @return Returns true if the Runnable was successfully placed in to the 8636 * message queue. Returns false on failure, usually because the 8637 * looper processing the message queue is exiting. 8638 */ 8639 public boolean post(Runnable action) { 8640 Handler handler; 8641 AttachInfo attachInfo = mAttachInfo; 8642 if (attachInfo != null) { 8643 handler = attachInfo.mHandler; 8644 } else { 8645 // Assume that post will succeed later 8646 ViewRootImpl.getRunQueue().post(action); 8647 return true; 8648 } 8649 8650 return handler.post(action); 8651 } 8652 8653 /** 8654 * <p>Causes the Runnable to be added to the message queue, to be run 8655 * after the specified amount of time elapses. 8656 * The runnable will be run on the user interface thread.</p> 8657 * 8658 * <p>This method can be invoked from outside of the UI thread 8659 * only when this View is attached to a window.</p> 8660 * 8661 * @param action The Runnable that will be executed. 8662 * @param delayMillis The delay (in milliseconds) until the Runnable 8663 * will be executed. 8664 * 8665 * @return true if the Runnable was successfully placed in to the 8666 * message queue. Returns false on failure, usually because the 8667 * looper processing the message queue is exiting. Note that a 8668 * result of true does not mean the Runnable will be processed -- 8669 * if the looper is quit before the delivery time of the message 8670 * occurs then the message will be dropped. 8671 */ 8672 public boolean postDelayed(Runnable action, long delayMillis) { 8673 Handler handler; 8674 AttachInfo attachInfo = mAttachInfo; 8675 if (attachInfo != null) { 8676 handler = attachInfo.mHandler; 8677 } else { 8678 // Assume that post will succeed later 8679 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis); 8680 return true; 8681 } 8682 8683 return handler.postDelayed(action, delayMillis); 8684 } 8685 8686 /** 8687 * <p>Removes the specified Runnable from the message queue.</p> 8688 * 8689 * <p>This method can be invoked from outside of the UI thread 8690 * only when this View is attached to a window.</p> 8691 * 8692 * @param action The Runnable to remove from the message handling queue 8693 * 8694 * @return true if this view could ask the Handler to remove the Runnable, 8695 * false otherwise. When the returned value is true, the Runnable 8696 * may or may not have been actually removed from the message queue 8697 * (for instance, if the Runnable was not in the queue already.) 8698 */ 8699 public boolean removeCallbacks(Runnable action) { 8700 Handler handler; 8701 AttachInfo attachInfo = mAttachInfo; 8702 if (attachInfo != null) { 8703 handler = attachInfo.mHandler; 8704 } else { 8705 // Assume that post will succeed later 8706 ViewRootImpl.getRunQueue().removeCallbacks(action); 8707 return true; 8708 } 8709 8710 handler.removeCallbacks(action); 8711 return true; 8712 } 8713 8714 /** 8715 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 8716 * Use this to invalidate the View from a non-UI thread.</p> 8717 * 8718 * <p>This method can be invoked from outside of the UI thread 8719 * only when this View is attached to a window.</p> 8720 * 8721 * @see #invalidate() 8722 */ 8723 public void postInvalidate() { 8724 postInvalidateDelayed(0); 8725 } 8726 8727 /** 8728 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 8729 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 8730 * 8731 * <p>This method can be invoked from outside of the UI thread 8732 * only when this View is attached to a window.</p> 8733 * 8734 * @param left The left coordinate of the rectangle to invalidate. 8735 * @param top The top coordinate of the rectangle to invalidate. 8736 * @param right The right coordinate of the rectangle to invalidate. 8737 * @param bottom The bottom coordinate of the rectangle to invalidate. 8738 * 8739 * @see #invalidate(int, int, int, int) 8740 * @see #invalidate(Rect) 8741 */ 8742 public void postInvalidate(int left, int top, int right, int bottom) { 8743 postInvalidateDelayed(0, left, top, right, bottom); 8744 } 8745 8746 /** 8747 * <p>Cause an invalidate to happen on a subsequent cycle through the event 8748 * loop. Waits for the specified amount of time.</p> 8749 * 8750 * <p>This method can be invoked from outside of the UI thread 8751 * only when this View is attached to a window.</p> 8752 * 8753 * @param delayMilliseconds the duration in milliseconds to delay the 8754 * invalidation by 8755 */ 8756 public void postInvalidateDelayed(long delayMilliseconds) { 8757 // We try only with the AttachInfo because there's no point in invalidating 8758 // if we are not attached to our window 8759 AttachInfo attachInfo = mAttachInfo; 8760 if (attachInfo != null) { 8761 Message msg = Message.obtain(); 8762 msg.what = AttachInfo.INVALIDATE_MSG; 8763 msg.obj = this; 8764 attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 8765 } 8766 } 8767 8768 /** 8769 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 8770 * through the event loop. Waits for the specified amount of time.</p> 8771 * 8772 * <p>This method can be invoked from outside of the UI thread 8773 * only when this View is attached to a window.</p> 8774 * 8775 * @param delayMilliseconds the duration in milliseconds to delay the 8776 * invalidation by 8777 * @param left The left coordinate of the rectangle to invalidate. 8778 * @param top The top coordinate of the rectangle to invalidate. 8779 * @param right The right coordinate of the rectangle to invalidate. 8780 * @param bottom The bottom coordinate of the rectangle to invalidate. 8781 */ 8782 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 8783 int right, int bottom) { 8784 8785 // We try only with the AttachInfo because there's no point in invalidating 8786 // if we are not attached to our window 8787 AttachInfo attachInfo = mAttachInfo; 8788 if (attachInfo != null) { 8789 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire(); 8790 info.target = this; 8791 info.left = left; 8792 info.top = top; 8793 info.right = right; 8794 info.bottom = bottom; 8795 8796 final Message msg = Message.obtain(); 8797 msg.what = AttachInfo.INVALIDATE_RECT_MSG; 8798 msg.obj = info; 8799 attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 8800 } 8801 } 8802 8803 /** 8804 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 8805 * This event is sent at most once every 8806 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 8807 */ 8808 private void postSendViewScrolledAccessibilityEventCallback() { 8809 if (mSendViewScrolledAccessibilityEvent == null) { 8810 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 8811 } 8812 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 8813 mSendViewScrolledAccessibilityEvent.mIsPending = true; 8814 postDelayed(mSendViewScrolledAccessibilityEvent, 8815 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 8816 } 8817 } 8818 8819 /** 8820 * Called by a parent to request that a child update its values for mScrollX 8821 * and mScrollY if necessary. This will typically be done if the child is 8822 * animating a scroll using a {@link android.widget.Scroller Scroller} 8823 * object. 8824 */ 8825 public void computeScroll() { 8826 } 8827 8828 /** 8829 * <p>Indicate whether the horizontal edges are faded when the view is 8830 * scrolled horizontally.</p> 8831 * 8832 * @return true if the horizontal edges should are faded on scroll, false 8833 * otherwise 8834 * 8835 * @see #setHorizontalFadingEdgeEnabled(boolean) 8836 * @attr ref android.R.styleable#View_requiresFadingEdge 8837 */ 8838 public boolean isHorizontalFadingEdgeEnabled() { 8839 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 8840 } 8841 8842 /** 8843 * <p>Define whether the horizontal edges should be faded when this view 8844 * is scrolled horizontally.</p> 8845 * 8846 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 8847 * be faded when the view is scrolled 8848 * horizontally 8849 * 8850 * @see #isHorizontalFadingEdgeEnabled() 8851 * @attr ref android.R.styleable#View_requiresFadingEdge 8852 */ 8853 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 8854 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 8855 if (horizontalFadingEdgeEnabled) { 8856 initScrollCache(); 8857 } 8858 8859 mViewFlags ^= FADING_EDGE_HORIZONTAL; 8860 } 8861 } 8862 8863 /** 8864 * <p>Indicate whether the vertical edges are faded when the view is 8865 * scrolled horizontally.</p> 8866 * 8867 * @return true if the vertical edges should are faded on scroll, false 8868 * otherwise 8869 * 8870 * @see #setVerticalFadingEdgeEnabled(boolean) 8871 * @attr ref android.R.styleable#View_requiresFadingEdge 8872 */ 8873 public boolean isVerticalFadingEdgeEnabled() { 8874 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 8875 } 8876 8877 /** 8878 * <p>Define whether the vertical edges should be faded when this view 8879 * is scrolled vertically.</p> 8880 * 8881 * @param verticalFadingEdgeEnabled true if the vertical edges should 8882 * be faded when the view is scrolled 8883 * vertically 8884 * 8885 * @see #isVerticalFadingEdgeEnabled() 8886 * @attr ref android.R.styleable#View_requiresFadingEdge 8887 */ 8888 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 8889 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 8890 if (verticalFadingEdgeEnabled) { 8891 initScrollCache(); 8892 } 8893 8894 mViewFlags ^= FADING_EDGE_VERTICAL; 8895 } 8896 } 8897 8898 /** 8899 * Returns the strength, or intensity, of the top faded edge. The strength is 8900 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 8901 * returns 0.0 or 1.0 but no value in between. 8902 * 8903 * Subclasses should override this method to provide a smoother fade transition 8904 * when scrolling occurs. 8905 * 8906 * @return the intensity of the top fade as a float between 0.0f and 1.0f 8907 */ 8908 protected float getTopFadingEdgeStrength() { 8909 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 8910 } 8911 8912 /** 8913 * Returns the strength, or intensity, of the bottom faded edge. The strength is 8914 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 8915 * returns 0.0 or 1.0 but no value in between. 8916 * 8917 * Subclasses should override this method to provide a smoother fade transition 8918 * when scrolling occurs. 8919 * 8920 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 8921 */ 8922 protected float getBottomFadingEdgeStrength() { 8923 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 8924 computeVerticalScrollRange() ? 1.0f : 0.0f; 8925 } 8926 8927 /** 8928 * Returns the strength, or intensity, of the left faded edge. The strength is 8929 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 8930 * returns 0.0 or 1.0 but no value in between. 8931 * 8932 * Subclasses should override this method to provide a smoother fade transition 8933 * when scrolling occurs. 8934 * 8935 * @return the intensity of the left fade as a float between 0.0f and 1.0f 8936 */ 8937 protected float getLeftFadingEdgeStrength() { 8938 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 8939 } 8940 8941 /** 8942 * Returns the strength, or intensity, of the right faded edge. The strength is 8943 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 8944 * returns 0.0 or 1.0 but no value in between. 8945 * 8946 * Subclasses should override this method to provide a smoother fade transition 8947 * when scrolling occurs. 8948 * 8949 * @return the intensity of the right fade as a float between 0.0f and 1.0f 8950 */ 8951 protected float getRightFadingEdgeStrength() { 8952 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 8953 computeHorizontalScrollRange() ? 1.0f : 0.0f; 8954 } 8955 8956 /** 8957 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 8958 * scrollbar is not drawn by default.</p> 8959 * 8960 * @return true if the horizontal scrollbar should be painted, false 8961 * otherwise 8962 * 8963 * @see #setHorizontalScrollBarEnabled(boolean) 8964 */ 8965 public boolean isHorizontalScrollBarEnabled() { 8966 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 8967 } 8968 8969 /** 8970 * <p>Define whether the horizontal scrollbar should be drawn or not. The 8971 * scrollbar is not drawn by default.</p> 8972 * 8973 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 8974 * be painted 8975 * 8976 * @see #isHorizontalScrollBarEnabled() 8977 */ 8978 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 8979 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 8980 mViewFlags ^= SCROLLBARS_HORIZONTAL; 8981 computeOpaqueFlags(); 8982 resolvePadding(); 8983 } 8984 } 8985 8986 /** 8987 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 8988 * scrollbar is not drawn by default.</p> 8989 * 8990 * @return true if the vertical scrollbar should be painted, false 8991 * otherwise 8992 * 8993 * @see #setVerticalScrollBarEnabled(boolean) 8994 */ 8995 public boolean isVerticalScrollBarEnabled() { 8996 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 8997 } 8998 8999 /** 9000 * <p>Define whether the vertical scrollbar should be drawn or not. The 9001 * scrollbar is not drawn by default.</p> 9002 * 9003 * @param verticalScrollBarEnabled true if the vertical scrollbar should 9004 * be painted 9005 * 9006 * @see #isVerticalScrollBarEnabled() 9007 */ 9008 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 9009 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 9010 mViewFlags ^= SCROLLBARS_VERTICAL; 9011 computeOpaqueFlags(); 9012 resolvePadding(); 9013 } 9014 } 9015 9016 /** 9017 * @hide 9018 */ 9019 protected void recomputePadding() { 9020 setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 9021 } 9022 9023 /** 9024 * Define whether scrollbars will fade when the view is not scrolling. 9025 * 9026 * @param fadeScrollbars wheter to enable fading 9027 * 9028 */ 9029 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 9030 initScrollCache(); 9031 final ScrollabilityCache scrollabilityCache = mScrollCache; 9032 scrollabilityCache.fadeScrollBars = fadeScrollbars; 9033 if (fadeScrollbars) { 9034 scrollabilityCache.state = ScrollabilityCache.OFF; 9035 } else { 9036 scrollabilityCache.state = ScrollabilityCache.ON; 9037 } 9038 } 9039 9040 /** 9041 * 9042 * Returns true if scrollbars will fade when this view is not scrolling 9043 * 9044 * @return true if scrollbar fading is enabled 9045 */ 9046 public boolean isScrollbarFadingEnabled() { 9047 return mScrollCache != null && mScrollCache.fadeScrollBars; 9048 } 9049 9050 /** 9051 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 9052 * inset. When inset, they add to the padding of the view. And the scrollbars 9053 * can be drawn inside the padding area or on the edge of the view. For example, 9054 * if a view has a background drawable and you want to draw the scrollbars 9055 * inside the padding specified by the drawable, you can use 9056 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 9057 * appear at the edge of the view, ignoring the padding, then you can use 9058 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 9059 * @param style the style of the scrollbars. Should be one of 9060 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 9061 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 9062 * @see #SCROLLBARS_INSIDE_OVERLAY 9063 * @see #SCROLLBARS_INSIDE_INSET 9064 * @see #SCROLLBARS_OUTSIDE_OVERLAY 9065 * @see #SCROLLBARS_OUTSIDE_INSET 9066 */ 9067 public void setScrollBarStyle(int style) { 9068 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 9069 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 9070 computeOpaqueFlags(); 9071 resolvePadding(); 9072 } 9073 } 9074 9075 /** 9076 * <p>Returns the current scrollbar style.</p> 9077 * @return the current scrollbar style 9078 * @see #SCROLLBARS_INSIDE_OVERLAY 9079 * @see #SCROLLBARS_INSIDE_INSET 9080 * @see #SCROLLBARS_OUTSIDE_OVERLAY 9081 * @see #SCROLLBARS_OUTSIDE_INSET 9082 */ 9083 @ViewDebug.ExportedProperty(mapping = { 9084 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 9085 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 9086 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 9087 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 9088 }) 9089 public int getScrollBarStyle() { 9090 return mViewFlags & SCROLLBARS_STYLE_MASK; 9091 } 9092 9093 /** 9094 * <p>Compute the horizontal range that the horizontal scrollbar 9095 * represents.</p> 9096 * 9097 * <p>The range is expressed in arbitrary units that must be the same as the 9098 * units used by {@link #computeHorizontalScrollExtent()} and 9099 * {@link #computeHorizontalScrollOffset()}.</p> 9100 * 9101 * <p>The default range is the drawing width of this view.</p> 9102 * 9103 * @return the total horizontal range represented by the horizontal 9104 * scrollbar 9105 * 9106 * @see #computeHorizontalScrollExtent() 9107 * @see #computeHorizontalScrollOffset() 9108 * @see android.widget.ScrollBarDrawable 9109 */ 9110 protected int computeHorizontalScrollRange() { 9111 return getWidth(); 9112 } 9113 9114 /** 9115 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 9116 * within the horizontal range. This value is used to compute the position 9117 * of the thumb within the scrollbar's track.</p> 9118 * 9119 * <p>The range is expressed in arbitrary units that must be the same as the 9120 * units used by {@link #computeHorizontalScrollRange()} and 9121 * {@link #computeHorizontalScrollExtent()}.</p> 9122 * 9123 * <p>The default offset is the scroll offset of this view.</p> 9124 * 9125 * @return the horizontal offset of the scrollbar's thumb 9126 * 9127 * @see #computeHorizontalScrollRange() 9128 * @see #computeHorizontalScrollExtent() 9129 * @see android.widget.ScrollBarDrawable 9130 */ 9131 protected int computeHorizontalScrollOffset() { 9132 return mScrollX; 9133 } 9134 9135 /** 9136 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 9137 * within the horizontal range. This value is used to compute the length 9138 * of the thumb within the scrollbar's track.</p> 9139 * 9140 * <p>The range is expressed in arbitrary units that must be the same as the 9141 * units used by {@link #computeHorizontalScrollRange()} and 9142 * {@link #computeHorizontalScrollOffset()}.</p> 9143 * 9144 * <p>The default extent is the drawing width of this view.</p> 9145 * 9146 * @return the horizontal extent of the scrollbar's thumb 9147 * 9148 * @see #computeHorizontalScrollRange() 9149 * @see #computeHorizontalScrollOffset() 9150 * @see android.widget.ScrollBarDrawable 9151 */ 9152 protected int computeHorizontalScrollExtent() { 9153 return getWidth(); 9154 } 9155 9156 /** 9157 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 9158 * 9159 * <p>The range is expressed in arbitrary units that must be the same as the 9160 * units used by {@link #computeVerticalScrollExtent()} and 9161 * {@link #computeVerticalScrollOffset()}.</p> 9162 * 9163 * @return the total vertical range represented by the vertical scrollbar 9164 * 9165 * <p>The default range is the drawing height of this view.</p> 9166 * 9167 * @see #computeVerticalScrollExtent() 9168 * @see #computeVerticalScrollOffset() 9169 * @see android.widget.ScrollBarDrawable 9170 */ 9171 protected int computeVerticalScrollRange() { 9172 return getHeight(); 9173 } 9174 9175 /** 9176 * <p>Compute the vertical offset of the vertical scrollbar's thumb 9177 * within the horizontal range. This value is used to compute the position 9178 * of the thumb within the scrollbar's track.</p> 9179 * 9180 * <p>The range is expressed in arbitrary units that must be the same as the 9181 * units used by {@link #computeVerticalScrollRange()} and 9182 * {@link #computeVerticalScrollExtent()}.</p> 9183 * 9184 * <p>The default offset is the scroll offset of this view.</p> 9185 * 9186 * @return the vertical offset of the scrollbar's thumb 9187 * 9188 * @see #computeVerticalScrollRange() 9189 * @see #computeVerticalScrollExtent() 9190 * @see android.widget.ScrollBarDrawable 9191 */ 9192 protected int computeVerticalScrollOffset() { 9193 return mScrollY; 9194 } 9195 9196 /** 9197 * <p>Compute the vertical extent of the horizontal scrollbar's thumb 9198 * within the vertical range. This value is used to compute the length 9199 * of the thumb within the scrollbar's track.</p> 9200 * 9201 * <p>The range is expressed in arbitrary units that must be the same as the 9202 * units used by {@link #computeVerticalScrollRange()} and 9203 * {@link #computeVerticalScrollOffset()}.</p> 9204 * 9205 * <p>The default extent is the drawing height of this view.</p> 9206 * 9207 * @return the vertical extent of the scrollbar's thumb 9208 * 9209 * @see #computeVerticalScrollRange() 9210 * @see #computeVerticalScrollOffset() 9211 * @see android.widget.ScrollBarDrawable 9212 */ 9213 protected int computeVerticalScrollExtent() { 9214 return getHeight(); 9215 } 9216 9217 /** 9218 * Check if this view can be scrolled horizontally in a certain direction. 9219 * 9220 * @param direction Negative to check scrolling left, positive to check scrolling right. 9221 * @return true if this view can be scrolled in the specified direction, false otherwise. 9222 */ 9223 public boolean canScrollHorizontally(int direction) { 9224 final int offset = computeHorizontalScrollOffset(); 9225 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 9226 if (range == 0) return false; 9227 if (direction < 0) { 9228 return offset > 0; 9229 } else { 9230 return offset < range - 1; 9231 } 9232 } 9233 9234 /** 9235 * Check if this view can be scrolled vertically in a certain direction. 9236 * 9237 * @param direction Negative to check scrolling up, positive to check scrolling down. 9238 * @return true if this view can be scrolled in the specified direction, false otherwise. 9239 */ 9240 public boolean canScrollVertically(int direction) { 9241 final int offset = computeVerticalScrollOffset(); 9242 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 9243 if (range == 0) return false; 9244 if (direction < 0) { 9245 return offset > 0; 9246 } else { 9247 return offset < range - 1; 9248 } 9249 } 9250 9251 /** 9252 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 9253 * scrollbars are painted only if they have been awakened first.</p> 9254 * 9255 * @param canvas the canvas on which to draw the scrollbars 9256 * 9257 * @see #awakenScrollBars(int) 9258 */ 9259 protected final void onDrawScrollBars(Canvas canvas) { 9260 // scrollbars are drawn only when the animation is running 9261 final ScrollabilityCache cache = mScrollCache; 9262 if (cache != null) { 9263 9264 int state = cache.state; 9265 9266 if (state == ScrollabilityCache.OFF) { 9267 return; 9268 } 9269 9270 boolean invalidate = false; 9271 9272 if (state == ScrollabilityCache.FADING) { 9273 // We're fading -- get our fade interpolation 9274 if (cache.interpolatorValues == null) { 9275 cache.interpolatorValues = new float[1]; 9276 } 9277 9278 float[] values = cache.interpolatorValues; 9279 9280 // Stops the animation if we're done 9281 if (cache.scrollBarInterpolator.timeToValues(values) == 9282 Interpolator.Result.FREEZE_END) { 9283 cache.state = ScrollabilityCache.OFF; 9284 } else { 9285 cache.scrollBar.setAlpha(Math.round(values[0])); 9286 } 9287 9288 // This will make the scroll bars inval themselves after 9289 // drawing. We only want this when we're fading so that 9290 // we prevent excessive redraws 9291 invalidate = true; 9292 } else { 9293 // We're just on -- but we may have been fading before so 9294 // reset alpha 9295 cache.scrollBar.setAlpha(255); 9296 } 9297 9298 9299 final int viewFlags = mViewFlags; 9300 9301 final boolean drawHorizontalScrollBar = 9302 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 9303 final boolean drawVerticalScrollBar = 9304 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 9305 && !isVerticalScrollBarHidden(); 9306 9307 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 9308 final int width = mRight - mLeft; 9309 final int height = mBottom - mTop; 9310 9311 final ScrollBarDrawable scrollBar = cache.scrollBar; 9312 9313 final int scrollX = mScrollX; 9314 final int scrollY = mScrollY; 9315 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 9316 9317 int left, top, right, bottom; 9318 9319 if (drawHorizontalScrollBar) { 9320 int size = scrollBar.getSize(false); 9321 if (size <= 0) { 9322 size = cache.scrollBarSize; 9323 } 9324 9325 scrollBar.setParameters(computeHorizontalScrollRange(), 9326 computeHorizontalScrollOffset(), 9327 computeHorizontalScrollExtent(), false); 9328 final int verticalScrollBarGap = drawVerticalScrollBar ? 9329 getVerticalScrollbarWidth() : 0; 9330 top = scrollY + height - size - (mUserPaddingBottom & inside); 9331 left = scrollX + (mPaddingLeft & inside); 9332 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 9333 bottom = top + size; 9334 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); 9335 if (invalidate) { 9336 invalidate(left, top, right, bottom); 9337 } 9338 } 9339 9340 if (drawVerticalScrollBar) { 9341 int size = scrollBar.getSize(true); 9342 if (size <= 0) { 9343 size = cache.scrollBarSize; 9344 } 9345 9346 scrollBar.setParameters(computeVerticalScrollRange(), 9347 computeVerticalScrollOffset(), 9348 computeVerticalScrollExtent(), true); 9349 switch (mVerticalScrollbarPosition) { 9350 default: 9351 case SCROLLBAR_POSITION_DEFAULT: 9352 case SCROLLBAR_POSITION_RIGHT: 9353 left = scrollX + width - size - (mUserPaddingRight & inside); 9354 break; 9355 case SCROLLBAR_POSITION_LEFT: 9356 left = scrollX + (mUserPaddingLeft & inside); 9357 break; 9358 } 9359 top = scrollY + (mPaddingTop & inside); 9360 right = left + size; 9361 bottom = scrollY + height - (mUserPaddingBottom & inside); 9362 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); 9363 if (invalidate) { 9364 invalidate(left, top, right, bottom); 9365 } 9366 } 9367 } 9368 } 9369 } 9370 9371 /** 9372 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 9373 * FastScroller is visible. 9374 * @return whether to temporarily hide the vertical scrollbar 9375 * @hide 9376 */ 9377 protected boolean isVerticalScrollBarHidden() { 9378 return false; 9379 } 9380 9381 /** 9382 * <p>Draw the horizontal scrollbar if 9383 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 9384 * 9385 * @param canvas the canvas on which to draw the scrollbar 9386 * @param scrollBar the scrollbar's drawable 9387 * 9388 * @see #isHorizontalScrollBarEnabled() 9389 * @see #computeHorizontalScrollRange() 9390 * @see #computeHorizontalScrollExtent() 9391 * @see #computeHorizontalScrollOffset() 9392 * @see android.widget.ScrollBarDrawable 9393 * @hide 9394 */ 9395 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 9396 int l, int t, int r, int b) { 9397 scrollBar.setBounds(l, t, r, b); 9398 scrollBar.draw(canvas); 9399 } 9400 9401 /** 9402 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 9403 * returns true.</p> 9404 * 9405 * @param canvas the canvas on which to draw the scrollbar 9406 * @param scrollBar the scrollbar's drawable 9407 * 9408 * @see #isVerticalScrollBarEnabled() 9409 * @see #computeVerticalScrollRange() 9410 * @see #computeVerticalScrollExtent() 9411 * @see #computeVerticalScrollOffset() 9412 * @see android.widget.ScrollBarDrawable 9413 * @hide 9414 */ 9415 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 9416 int l, int t, int r, int b) { 9417 scrollBar.setBounds(l, t, r, b); 9418 scrollBar.draw(canvas); 9419 } 9420 9421 /** 9422 * Implement this to do your drawing. 9423 * 9424 * @param canvas the canvas on which the background will be drawn 9425 */ 9426 protected void onDraw(Canvas canvas) { 9427 } 9428 9429 /* 9430 * Caller is responsible for calling requestLayout if necessary. 9431 * (This allows addViewInLayout to not request a new layout.) 9432 */ 9433 void assignParent(ViewParent parent) { 9434 if (mParent == null) { 9435 mParent = parent; 9436 } else if (parent == null) { 9437 mParent = null; 9438 } else { 9439 throw new RuntimeException("view " + this + " being added, but" 9440 + " it already has a parent"); 9441 } 9442 } 9443 9444 /** 9445 * This is called when the view is attached to a window. At this point it 9446 * has a Surface and will start drawing. Note that this function is 9447 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 9448 * however it may be called any time before the first onDraw -- including 9449 * before or after {@link #onMeasure(int, int)}. 9450 * 9451 * @see #onDetachedFromWindow() 9452 */ 9453 protected void onAttachedToWindow() { 9454 if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) { 9455 mParent.requestTransparentRegion(this); 9456 } 9457 if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) { 9458 initialAwakenScrollBars(); 9459 mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH; 9460 } 9461 jumpDrawablesToCurrentState(); 9462 // Order is important here: LayoutDirection MUST be resolved before Padding 9463 // and TextDirection 9464 resolveLayoutDirectionIfNeeded(); 9465 resolvePadding(); 9466 resolveTextDirection(); 9467 if (isFocused()) { 9468 InputMethodManager imm = InputMethodManager.peekInstance(); 9469 imm.focusIn(this); 9470 } 9471 } 9472 9473 /** 9474 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 9475 * that the parent directionality can and will be resolved before its children. 9476 */ 9477 private void resolveLayoutDirectionIfNeeded() { 9478 // Do not resolve if it is not needed 9479 if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return; 9480 9481 // Clear any previous layout direction resolution 9482 mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL; 9483 9484 // Reset also TextDirection as a change into LayoutDirection may impact the selected 9485 // TextDirectionHeuristic 9486 resetResolvedTextDirection(); 9487 9488 // Set resolved depending on layout direction 9489 switch (getLayoutDirection()) { 9490 case LAYOUT_DIRECTION_INHERIT: 9491 // We cannot do the resolution if there is no parent 9492 if (mParent == null) return; 9493 9494 // If this is root view, no need to look at parent's layout dir. 9495 if (mParent instanceof ViewGroup) { 9496 ViewGroup viewGroup = ((ViewGroup) mParent); 9497 9498 // Check if the parent view group can resolve 9499 if (! viewGroup.canResolveLayoutDirection()) { 9500 return; 9501 } 9502 if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) { 9503 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL; 9504 } 9505 } 9506 break; 9507 case LAYOUT_DIRECTION_RTL: 9508 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL; 9509 break; 9510 case LAYOUT_DIRECTION_LOCALE: 9511 if(isLayoutDirectionRtl(Locale.getDefault())) { 9512 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL; 9513 } 9514 break; 9515 default: 9516 // Nothing to do, LTR by default 9517 } 9518 9519 // Set to resolved 9520 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED; 9521 } 9522 9523 /** 9524 * @hide 9525 */ 9526 protected void resolvePadding() { 9527 // If the user specified the absolute padding (either with android:padding or 9528 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise 9529 // use the default padding or the padding from the background drawable 9530 // (stored at this point in mPadding*) 9531 switch (getResolvedLayoutDirection()) { 9532 case LAYOUT_DIRECTION_RTL: 9533 // Start user padding override Right user padding. Otherwise, if Right user 9534 // padding is not defined, use the default Right padding. If Right user padding 9535 // is defined, just use it. 9536 if (mUserPaddingStart >= 0) { 9537 mUserPaddingRight = mUserPaddingStart; 9538 } else if (mUserPaddingRight < 0) { 9539 mUserPaddingRight = mPaddingRight; 9540 } 9541 if (mUserPaddingEnd >= 0) { 9542 mUserPaddingLeft = mUserPaddingEnd; 9543 } else if (mUserPaddingLeft < 0) { 9544 mUserPaddingLeft = mPaddingLeft; 9545 } 9546 break; 9547 case LAYOUT_DIRECTION_LTR: 9548 default: 9549 // Start user padding override Left user padding. Otherwise, if Left user 9550 // padding is not defined, use the default left padding. If Left user padding 9551 // is defined, just use it. 9552 if (mUserPaddingStart >= 0) { 9553 mUserPaddingLeft = mUserPaddingStart; 9554 } else if (mUserPaddingLeft < 0) { 9555 mUserPaddingLeft = mPaddingLeft; 9556 } 9557 if (mUserPaddingEnd >= 0) { 9558 mUserPaddingRight = mUserPaddingEnd; 9559 } else if (mUserPaddingRight < 0) { 9560 mUserPaddingRight = mPaddingRight; 9561 } 9562 } 9563 9564 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 9565 9566 recomputePadding(); 9567 } 9568 9569 /** 9570 * Return true if layout direction resolution can be done 9571 * 9572 * @hide 9573 */ 9574 protected boolean canResolveLayoutDirection() { 9575 switch (getLayoutDirection()) { 9576 case LAYOUT_DIRECTION_INHERIT: 9577 return (mParent != null); 9578 default: 9579 return true; 9580 } 9581 } 9582 9583 /** 9584 * Reset the resolved layout direction. 9585 * 9586 * Subclasses need to override this method to clear cached information that depends on the 9587 * resolved layout direction, or to inform child views that inherit their layout direction. 9588 * Overrides must also call the superclass implementation at the start of their implementation. 9589 * 9590 * @hide 9591 */ 9592 protected void resetResolvedLayoutDirection() { 9593 // Reset the current View resolution 9594 mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED; 9595 } 9596 9597 /** 9598 * Check if a Locale is corresponding to a RTL script. 9599 * 9600 * @param locale Locale to check 9601 * @return true if a Locale is corresponding to a RTL script. 9602 * 9603 * @hide 9604 */ 9605 protected static boolean isLayoutDirectionRtl(Locale locale) { 9606 return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE == 9607 LocaleUtil.getLayoutDirectionFromLocale(locale)); 9608 } 9609 9610 /** 9611 * This is called when the view is detached from a window. At this point it 9612 * no longer has a surface for drawing. 9613 * 9614 * @see #onAttachedToWindow() 9615 */ 9616 protected void onDetachedFromWindow() { 9617 mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT; 9618 9619 removeUnsetPressCallback(); 9620 removeLongPressCallback(); 9621 removePerformClickCallback(); 9622 removeSendViewScrolledAccessibilityEventCallback(); 9623 9624 destroyDrawingCache(); 9625 9626 destroyLayer(); 9627 9628 if (mDisplayList != null) { 9629 mDisplayList.invalidate(); 9630 } 9631 9632 if (mAttachInfo != null) { 9633 mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this); 9634 } 9635 9636 mCurrentAnimation = null; 9637 9638 resetResolvedLayoutDirection(); 9639 resetResolvedTextDirection(); 9640 } 9641 9642 /** 9643 * @return The number of times this view has been attached to a window 9644 */ 9645 protected int getWindowAttachCount() { 9646 return mWindowAttachCount; 9647 } 9648 9649 /** 9650 * Retrieve a unique token identifying the window this view is attached to. 9651 * @return Return the window's token for use in 9652 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 9653 */ 9654 public IBinder getWindowToken() { 9655 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 9656 } 9657 9658 /** 9659 * Retrieve a unique token identifying the top-level "real" window of 9660 * the window that this view is attached to. That is, this is like 9661 * {@link #getWindowToken}, except if the window this view in is a panel 9662 * window (attached to another containing window), then the token of 9663 * the containing window is returned instead. 9664 * 9665 * @return Returns the associated window token, either 9666 * {@link #getWindowToken()} or the containing window's token. 9667 */ 9668 public IBinder getApplicationWindowToken() { 9669 AttachInfo ai = mAttachInfo; 9670 if (ai != null) { 9671 IBinder appWindowToken = ai.mPanelParentWindowToken; 9672 if (appWindowToken == null) { 9673 appWindowToken = ai.mWindowToken; 9674 } 9675 return appWindowToken; 9676 } 9677 return null; 9678 } 9679 9680 /** 9681 * Retrieve private session object this view hierarchy is using to 9682 * communicate with the window manager. 9683 * @return the session object to communicate with the window manager 9684 */ 9685 /*package*/ IWindowSession getWindowSession() { 9686 return mAttachInfo != null ? mAttachInfo.mSession : null; 9687 } 9688 9689 /** 9690 * @param info the {@link android.view.View.AttachInfo} to associated with 9691 * this view 9692 */ 9693 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 9694 //System.out.println("Attached! " + this); 9695 mAttachInfo = info; 9696 mWindowAttachCount++; 9697 // We will need to evaluate the drawable state at least once. 9698 mPrivateFlags |= DRAWABLE_STATE_DIRTY; 9699 if (mFloatingTreeObserver != null) { 9700 info.mTreeObserver.merge(mFloatingTreeObserver); 9701 mFloatingTreeObserver = null; 9702 } 9703 if ((mPrivateFlags&SCROLL_CONTAINER) != 0) { 9704 mAttachInfo.mScrollContainers.add(this); 9705 mPrivateFlags |= SCROLL_CONTAINER_ADDED; 9706 } 9707 performCollectViewAttributes(visibility); 9708 onAttachedToWindow(); 9709 9710 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 9711 mOnAttachStateChangeListeners; 9712 if (listeners != null && listeners.size() > 0) { 9713 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 9714 // perform the dispatching. The iterator is a safe guard against listeners that 9715 // could mutate the list by calling the various add/remove methods. This prevents 9716 // the array from being modified while we iterate it. 9717 for (OnAttachStateChangeListener listener : listeners) { 9718 listener.onViewAttachedToWindow(this); 9719 } 9720 } 9721 9722 int vis = info.mWindowVisibility; 9723 if (vis != GONE) { 9724 onWindowVisibilityChanged(vis); 9725 } 9726 if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) { 9727 // If nobody has evaluated the drawable state yet, then do it now. 9728 refreshDrawableState(); 9729 } 9730 } 9731 9732 void dispatchDetachedFromWindow() { 9733 AttachInfo info = mAttachInfo; 9734 if (info != null) { 9735 int vis = info.mWindowVisibility; 9736 if (vis != GONE) { 9737 onWindowVisibilityChanged(GONE); 9738 } 9739 } 9740 9741 onDetachedFromWindow(); 9742 9743 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 9744 mOnAttachStateChangeListeners; 9745 if (listeners != null && listeners.size() > 0) { 9746 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 9747 // perform the dispatching. The iterator is a safe guard against listeners that 9748 // could mutate the list by calling the various add/remove methods. This prevents 9749 // the array from being modified while we iterate it. 9750 for (OnAttachStateChangeListener listener : listeners) { 9751 listener.onViewDetachedFromWindow(this); 9752 } 9753 } 9754 9755 if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) { 9756 mAttachInfo.mScrollContainers.remove(this); 9757 mPrivateFlags &= ~SCROLL_CONTAINER_ADDED; 9758 } 9759 9760 mAttachInfo = null; 9761 } 9762 9763 /** 9764 * Store this view hierarchy's frozen state into the given container. 9765 * 9766 * @param container The SparseArray in which to save the view's state. 9767 * 9768 * @see #restoreHierarchyState(android.util.SparseArray) 9769 * @see #dispatchSaveInstanceState(android.util.SparseArray) 9770 * @see #onSaveInstanceState() 9771 */ 9772 public void saveHierarchyState(SparseArray<Parcelable> container) { 9773 dispatchSaveInstanceState(container); 9774 } 9775 9776 /** 9777 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 9778 * this view and its children. May be overridden to modify how freezing happens to a 9779 * view's children; for example, some views may want to not store state for their children. 9780 * 9781 * @param container The SparseArray in which to save the view's state. 9782 * 9783 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 9784 * @see #saveHierarchyState(android.util.SparseArray) 9785 * @see #onSaveInstanceState() 9786 */ 9787 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 9788 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 9789 mPrivateFlags &= ~SAVE_STATE_CALLED; 9790 Parcelable state = onSaveInstanceState(); 9791 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 9792 throw new IllegalStateException( 9793 "Derived class did not call super.onSaveInstanceState()"); 9794 } 9795 if (state != null) { 9796 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 9797 // + ": " + state); 9798 container.put(mID, state); 9799 } 9800 } 9801 } 9802 9803 /** 9804 * Hook allowing a view to generate a representation of its internal state 9805 * that can later be used to create a new instance with that same state. 9806 * This state should only contain information that is not persistent or can 9807 * not be reconstructed later. For example, you will never store your 9808 * current position on screen because that will be computed again when a 9809 * new instance of the view is placed in its view hierarchy. 9810 * <p> 9811 * Some examples of things you may store here: the current cursor position 9812 * in a text view (but usually not the text itself since that is stored in a 9813 * content provider or other persistent storage), the currently selected 9814 * item in a list view. 9815 * 9816 * @return Returns a Parcelable object containing the view's current dynamic 9817 * state, or null if there is nothing interesting to save. The 9818 * default implementation returns null. 9819 * @see #onRestoreInstanceState(android.os.Parcelable) 9820 * @see #saveHierarchyState(android.util.SparseArray) 9821 * @see #dispatchSaveInstanceState(android.util.SparseArray) 9822 * @see #setSaveEnabled(boolean) 9823 */ 9824 protected Parcelable onSaveInstanceState() { 9825 mPrivateFlags |= SAVE_STATE_CALLED; 9826 return BaseSavedState.EMPTY_STATE; 9827 } 9828 9829 /** 9830 * Restore this view hierarchy's frozen state from the given container. 9831 * 9832 * @param container The SparseArray which holds previously frozen states. 9833 * 9834 * @see #saveHierarchyState(android.util.SparseArray) 9835 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 9836 * @see #onRestoreInstanceState(android.os.Parcelable) 9837 */ 9838 public void restoreHierarchyState(SparseArray<Parcelable> container) { 9839 dispatchRestoreInstanceState(container); 9840 } 9841 9842 /** 9843 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 9844 * state for this view and its children. May be overridden to modify how restoring 9845 * happens to a view's children; for example, some views may want to not store state 9846 * for their children. 9847 * 9848 * @param container The SparseArray which holds previously saved state. 9849 * 9850 * @see #dispatchSaveInstanceState(android.util.SparseArray) 9851 * @see #restoreHierarchyState(android.util.SparseArray) 9852 * @see #onRestoreInstanceState(android.os.Parcelable) 9853 */ 9854 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 9855 if (mID != NO_ID) { 9856 Parcelable state = container.get(mID); 9857 if (state != null) { 9858 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 9859 // + ": " + state); 9860 mPrivateFlags &= ~SAVE_STATE_CALLED; 9861 onRestoreInstanceState(state); 9862 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 9863 throw new IllegalStateException( 9864 "Derived class did not call super.onRestoreInstanceState()"); 9865 } 9866 } 9867 } 9868 } 9869 9870 /** 9871 * Hook allowing a view to re-apply a representation of its internal state that had previously 9872 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 9873 * null state. 9874 * 9875 * @param state The frozen state that had previously been returned by 9876 * {@link #onSaveInstanceState}. 9877 * 9878 * @see #onSaveInstanceState() 9879 * @see #restoreHierarchyState(android.util.SparseArray) 9880 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 9881 */ 9882 protected void onRestoreInstanceState(Parcelable state) { 9883 mPrivateFlags |= SAVE_STATE_CALLED; 9884 if (state != BaseSavedState.EMPTY_STATE && state != null) { 9885 throw new IllegalArgumentException("Wrong state class, expecting View State but " 9886 + "received " + state.getClass().toString() + " instead. This usually happens " 9887 + "when two views of different type have the same id in the same hierarchy. " 9888 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 9889 + "other views do not use the same id."); 9890 } 9891 } 9892 9893 /** 9894 * <p>Return the time at which the drawing of the view hierarchy started.</p> 9895 * 9896 * @return the drawing start time in milliseconds 9897 */ 9898 public long getDrawingTime() { 9899 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 9900 } 9901 9902 /** 9903 * <p>Enables or disables the duplication of the parent's state into this view. When 9904 * duplication is enabled, this view gets its drawable state from its parent rather 9905 * than from its own internal properties.</p> 9906 * 9907 * <p>Note: in the current implementation, setting this property to true after the 9908 * view was added to a ViewGroup might have no effect at all. This property should 9909 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 9910 * 9911 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 9912 * property is enabled, an exception will be thrown.</p> 9913 * 9914 * <p>Note: if the child view uses and updates additionnal states which are unknown to the 9915 * parent, these states should not be affected by this method.</p> 9916 * 9917 * @param enabled True to enable duplication of the parent's drawable state, false 9918 * to disable it. 9919 * 9920 * @see #getDrawableState() 9921 * @see #isDuplicateParentStateEnabled() 9922 */ 9923 public void setDuplicateParentStateEnabled(boolean enabled) { 9924 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 9925 } 9926 9927 /** 9928 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 9929 * 9930 * @return True if this view's drawable state is duplicated from the parent, 9931 * false otherwise 9932 * 9933 * @see #getDrawableState() 9934 * @see #setDuplicateParentStateEnabled(boolean) 9935 */ 9936 public boolean isDuplicateParentStateEnabled() { 9937 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 9938 } 9939 9940 /** 9941 * <p>Specifies the type of layer backing this view. The layer can be 9942 * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or 9943 * {@link #LAYER_TYPE_HARDWARE hardware}.</p> 9944 * 9945 * <p>A layer is associated with an optional {@link android.graphics.Paint} 9946 * instance that controls how the layer is composed on screen. The following 9947 * properties of the paint are taken into account when composing the layer:</p> 9948 * <ul> 9949 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 9950 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 9951 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 9952 * </ul> 9953 * 9954 * <p>If this view has an alpha value set to < 1.0 by calling 9955 * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by 9956 * this view's alpha value. Calling {@link #setAlpha(float)} is therefore 9957 * equivalent to setting a hardware layer on this view and providing a paint with 9958 * the desired alpha value.<p> 9959 * 9960 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled}, 9961 * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware} 9962 * for more information on when and how to use layers.</p> 9963 * 9964 * @param layerType The ype of layer to use with this view, must be one of 9965 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 9966 * {@link #LAYER_TYPE_HARDWARE} 9967 * @param paint The paint used to compose the layer. This argument is optional 9968 * and can be null. It is ignored when the layer type is 9969 * {@link #LAYER_TYPE_NONE} 9970 * 9971 * @see #getLayerType() 9972 * @see #LAYER_TYPE_NONE 9973 * @see #LAYER_TYPE_SOFTWARE 9974 * @see #LAYER_TYPE_HARDWARE 9975 * @see #setAlpha(float) 9976 * 9977 * @attr ref android.R.styleable#View_layerType 9978 */ 9979 public void setLayerType(int layerType, Paint paint) { 9980 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 9981 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 9982 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 9983 } 9984 9985 if (layerType == mLayerType) { 9986 if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) { 9987 mLayerPaint = paint == null ? new Paint() : paint; 9988 invalidateParentCaches(); 9989 invalidate(true); 9990 } 9991 return; 9992 } 9993 9994 // Destroy any previous software drawing cache if needed 9995 switch (mLayerType) { 9996 case LAYER_TYPE_HARDWARE: 9997 destroyLayer(); 9998 // fall through - unaccelerated views may use software layer mechanism instead 9999 case LAYER_TYPE_SOFTWARE: 10000 destroyDrawingCache(); 10001 break; 10002 default: 10003 break; 10004 } 10005 10006 mLayerType = layerType; 10007 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE; 10008 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint); 10009 mLocalDirtyRect = layerDisabled ? null : new Rect(); 10010 10011 invalidateParentCaches(); 10012 invalidate(true); 10013 } 10014 10015 /** 10016 * Indicates whether this view has a static layer. A view with layer type 10017 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are 10018 * dynamic. 10019 */ 10020 boolean hasStaticLayer() { 10021 return mLayerType == LAYER_TYPE_NONE; 10022 } 10023 10024 /** 10025 * Indicates what type of layer is currently associated with this view. By default 10026 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 10027 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 10028 * for more information on the different types of layers. 10029 * 10030 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 10031 * {@link #LAYER_TYPE_HARDWARE} 10032 * 10033 * @see #setLayerType(int, android.graphics.Paint) 10034 * @see #buildLayer() 10035 * @see #LAYER_TYPE_NONE 10036 * @see #LAYER_TYPE_SOFTWARE 10037 * @see #LAYER_TYPE_HARDWARE 10038 */ 10039 public int getLayerType() { 10040 return mLayerType; 10041 } 10042 10043 /** 10044 * Forces this view's layer to be created and this view to be rendered 10045 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 10046 * invoking this method will have no effect. 10047 * 10048 * This method can for instance be used to render a view into its layer before 10049 * starting an animation. If this view is complex, rendering into the layer 10050 * before starting the animation will avoid skipping frames. 10051 * 10052 * @throws IllegalStateException If this view is not attached to a window 10053 * 10054 * @see #setLayerType(int, android.graphics.Paint) 10055 */ 10056 public void buildLayer() { 10057 if (mLayerType == LAYER_TYPE_NONE) return; 10058 10059 if (mAttachInfo == null) { 10060 throw new IllegalStateException("This view must be attached to a window first"); 10061 } 10062 10063 switch (mLayerType) { 10064 case LAYER_TYPE_HARDWARE: 10065 getHardwareLayer(); 10066 break; 10067 case LAYER_TYPE_SOFTWARE: 10068 buildDrawingCache(true); 10069 break; 10070 } 10071 } 10072 10073 /** 10074 * <p>Returns a hardware layer that can be used to draw this view again 10075 * without executing its draw method.</p> 10076 * 10077 * @return A HardwareLayer ready to render, or null if an error occurred. 10078 */ 10079 HardwareLayer getHardwareLayer() { 10080 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null || 10081 !mAttachInfo.mHardwareRenderer.isEnabled()) { 10082 return null; 10083 } 10084 10085 final int width = mRight - mLeft; 10086 final int height = mBottom - mTop; 10087 10088 if (width == 0 || height == 0) { 10089 return null; 10090 } 10091 10092 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) { 10093 if (mHardwareLayer == null) { 10094 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer( 10095 width, height, isOpaque()); 10096 mLocalDirtyRect.setEmpty(); 10097 } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) { 10098 mHardwareLayer.resize(width, height); 10099 mLocalDirtyRect.setEmpty(); 10100 } 10101 10102 HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas; 10103 final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas); 10104 mAttachInfo.mHardwareCanvas = canvas; 10105 try { 10106 canvas.setViewport(width, height); 10107 canvas.onPreDraw(mLocalDirtyRect); 10108 mLocalDirtyRect.setEmpty(); 10109 10110 final int restoreCount = canvas.save(); 10111 10112 computeScroll(); 10113 canvas.translate(-mScrollX, -mScrollY); 10114 10115 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID; 10116 10117 // Fast path for layouts with no backgrounds 10118 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 10119 mPrivateFlags &= ~DIRTY_MASK; 10120 dispatchDraw(canvas); 10121 } else { 10122 draw(canvas); 10123 } 10124 10125 canvas.restoreToCount(restoreCount); 10126 } finally { 10127 canvas.onPostDraw(); 10128 mHardwareLayer.end(currentCanvas); 10129 mAttachInfo.mHardwareCanvas = currentCanvas; 10130 } 10131 } 10132 10133 return mHardwareLayer; 10134 } 10135 10136 boolean destroyLayer() { 10137 if (mHardwareLayer != null) { 10138 mHardwareLayer.destroy(); 10139 mHardwareLayer = null; 10140 return true; 10141 } 10142 return false; 10143 } 10144 10145 /** 10146 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 10147 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 10148 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 10149 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 10150 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 10151 * null.</p> 10152 * 10153 * <p>Enabling the drawing cache is similar to 10154 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 10155 * acceleration is turned off. When hardware acceleration is turned on, enabling the 10156 * drawing cache has no effect on rendering because the system uses a different mechanism 10157 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 10158 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 10159 * for information on how to enable software and hardware layers.</p> 10160 * 10161 * <p>This API can be used to manually generate 10162 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 10163 * {@link #getDrawingCache()}.</p> 10164 * 10165 * @param enabled true to enable the drawing cache, false otherwise 10166 * 10167 * @see #isDrawingCacheEnabled() 10168 * @see #getDrawingCache() 10169 * @see #buildDrawingCache() 10170 * @see #setLayerType(int, android.graphics.Paint) 10171 */ 10172 public void setDrawingCacheEnabled(boolean enabled) { 10173 mCachingFailed = false; 10174 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 10175 } 10176 10177 /** 10178 * <p>Indicates whether the drawing cache is enabled for this view.</p> 10179 * 10180 * @return true if the drawing cache is enabled 10181 * 10182 * @see #setDrawingCacheEnabled(boolean) 10183 * @see #getDrawingCache() 10184 */ 10185 @ViewDebug.ExportedProperty(category = "drawing") 10186 public boolean isDrawingCacheEnabled() { 10187 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 10188 } 10189 10190 /** 10191 * Debugging utility which recursively outputs the dirty state of a view and its 10192 * descendants. 10193 * 10194 * @hide 10195 */ 10196 @SuppressWarnings({"UnusedDeclaration"}) 10197 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 10198 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) + 10199 ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" + 10200 (mPrivateFlags & View.DRAWING_CACHE_VALID) + 10201 ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")"); 10202 if (clear) { 10203 mPrivateFlags &= clearMask; 10204 } 10205 if (this instanceof ViewGroup) { 10206 ViewGroup parent = (ViewGroup) this; 10207 final int count = parent.getChildCount(); 10208 for (int i = 0; i < count; i++) { 10209 final View child = parent.getChildAt(i); 10210 child.outputDirtyFlags(indent + " ", clear, clearMask); 10211 } 10212 } 10213 } 10214 10215 /** 10216 * This method is used by ViewGroup to cause its children to restore or recreate their 10217 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 10218 * to recreate its own display list, which would happen if it went through the normal 10219 * draw/dispatchDraw mechanisms. 10220 * 10221 * @hide 10222 */ 10223 protected void dispatchGetDisplayList() {} 10224 10225 /** 10226 * A view that is not attached or hardware accelerated cannot create a display list. 10227 * This method checks these conditions and returns the appropriate result. 10228 * 10229 * @return true if view has the ability to create a display list, false otherwise. 10230 * 10231 * @hide 10232 */ 10233 public boolean canHaveDisplayList() { 10234 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 10235 } 10236 10237 /** 10238 * <p>Returns a display list that can be used to draw this view again 10239 * without executing its draw method.</p> 10240 * 10241 * @return A DisplayList ready to replay, or null if caching is not enabled. 10242 * 10243 * @hide 10244 */ 10245 public DisplayList getDisplayList() { 10246 if (!canHaveDisplayList()) { 10247 return null; 10248 } 10249 10250 if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || 10251 mDisplayList == null || !mDisplayList.isValid() || 10252 mRecreateDisplayList)) { 10253 // Don't need to recreate the display list, just need to tell our 10254 // children to restore/recreate theirs 10255 if (mDisplayList != null && mDisplayList.isValid() && 10256 !mRecreateDisplayList) { 10257 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID; 10258 mPrivateFlags &= ~DIRTY_MASK; 10259 dispatchGetDisplayList(); 10260 10261 return mDisplayList; 10262 } 10263 10264 // If we got here, we're recreating it. Mark it as such to ensure that 10265 // we copy in child display lists into ours in drawChild() 10266 mRecreateDisplayList = true; 10267 if (mDisplayList == null) { 10268 mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(); 10269 // If we're creating a new display list, make sure our parent gets invalidated 10270 // since they will need to recreate their display list to account for this 10271 // new child display list. 10272 invalidateParentCaches(); 10273 } 10274 10275 final HardwareCanvas canvas = mDisplayList.start(); 10276 int restoreCount = 0; 10277 try { 10278 int width = mRight - mLeft; 10279 int height = mBottom - mTop; 10280 10281 canvas.setViewport(width, height); 10282 // The dirty rect should always be null for a display list 10283 canvas.onPreDraw(null); 10284 10285 computeScroll(); 10286 10287 restoreCount = canvas.save(); 10288 canvas.translate(-mScrollX, -mScrollY); 10289 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID; 10290 mPrivateFlags &= ~DIRTY_MASK; 10291 10292 // Fast path for layouts with no backgrounds 10293 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 10294 dispatchDraw(canvas); 10295 } else { 10296 draw(canvas); 10297 } 10298 } finally { 10299 canvas.restoreToCount(restoreCount); 10300 canvas.onPostDraw(); 10301 10302 mDisplayList.end(); 10303 } 10304 } else { 10305 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID; 10306 mPrivateFlags &= ~DIRTY_MASK; 10307 } 10308 10309 return mDisplayList; 10310 } 10311 10312 /** 10313 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 10314 * 10315 * @return A non-scaled bitmap representing this view or null if cache is disabled. 10316 * 10317 * @see #getDrawingCache(boolean) 10318 */ 10319 public Bitmap getDrawingCache() { 10320 return getDrawingCache(false); 10321 } 10322 10323 /** 10324 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 10325 * is null when caching is disabled. If caching is enabled and the cache is not ready, 10326 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 10327 * draw from the cache when the cache is enabled. To benefit from the cache, you must 10328 * request the drawing cache by calling this method and draw it on screen if the 10329 * returned bitmap is not null.</p> 10330 * 10331 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 10332 * this method will create a bitmap of the same size as this view. Because this bitmap 10333 * will be drawn scaled by the parent ViewGroup, the result on screen might show 10334 * scaling artifacts. To avoid such artifacts, you should call this method by setting 10335 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 10336 * size than the view. This implies that your application must be able to handle this 10337 * size.</p> 10338 * 10339 * @param autoScale Indicates whether the generated bitmap should be scaled based on 10340 * the current density of the screen when the application is in compatibility 10341 * mode. 10342 * 10343 * @return A bitmap representing this view or null if cache is disabled. 10344 * 10345 * @see #setDrawingCacheEnabled(boolean) 10346 * @see #isDrawingCacheEnabled() 10347 * @see #buildDrawingCache(boolean) 10348 * @see #destroyDrawingCache() 10349 */ 10350 public Bitmap getDrawingCache(boolean autoScale) { 10351 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 10352 return null; 10353 } 10354 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 10355 buildDrawingCache(autoScale); 10356 } 10357 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 10358 } 10359 10360 /** 10361 * <p>Frees the resources used by the drawing cache. If you call 10362 * {@link #buildDrawingCache()} manually without calling 10363 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 10364 * should cleanup the cache with this method afterwards.</p> 10365 * 10366 * @see #setDrawingCacheEnabled(boolean) 10367 * @see #buildDrawingCache() 10368 * @see #getDrawingCache() 10369 */ 10370 public void destroyDrawingCache() { 10371 if (mDrawingCache != null) { 10372 mDrawingCache.recycle(); 10373 mDrawingCache = null; 10374 } 10375 if (mUnscaledDrawingCache != null) { 10376 mUnscaledDrawingCache.recycle(); 10377 mUnscaledDrawingCache = null; 10378 } 10379 } 10380 10381 /** 10382 * Setting a solid background color for the drawing cache's bitmaps will improve 10383 * performance and memory usage. Note, though that this should only be used if this 10384 * view will always be drawn on top of a solid color. 10385 * 10386 * @param color The background color to use for the drawing cache's bitmap 10387 * 10388 * @see #setDrawingCacheEnabled(boolean) 10389 * @see #buildDrawingCache() 10390 * @see #getDrawingCache() 10391 */ 10392 public void setDrawingCacheBackgroundColor(int color) { 10393 if (color != mDrawingCacheBackgroundColor) { 10394 mDrawingCacheBackgroundColor = color; 10395 mPrivateFlags &= ~DRAWING_CACHE_VALID; 10396 } 10397 } 10398 10399 /** 10400 * @see #setDrawingCacheBackgroundColor(int) 10401 * 10402 * @return The background color to used for the drawing cache's bitmap 10403 */ 10404 public int getDrawingCacheBackgroundColor() { 10405 return mDrawingCacheBackgroundColor; 10406 } 10407 10408 /** 10409 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 10410 * 10411 * @see #buildDrawingCache(boolean) 10412 */ 10413 public void buildDrawingCache() { 10414 buildDrawingCache(false); 10415 } 10416 10417 /** 10418 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 10419 * 10420 * <p>If you call {@link #buildDrawingCache()} manually without calling 10421 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 10422 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 10423 * 10424 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 10425 * this method will create a bitmap of the same size as this view. Because this bitmap 10426 * will be drawn scaled by the parent ViewGroup, the result on screen might show 10427 * scaling artifacts. To avoid such artifacts, you should call this method by setting 10428 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 10429 * size than the view. This implies that your application must be able to handle this 10430 * size.</p> 10431 * 10432 * <p>You should avoid calling this method when hardware acceleration is enabled. If 10433 * you do not need the drawing cache bitmap, calling this method will increase memory 10434 * usage and cause the view to be rendered in software once, thus negatively impacting 10435 * performance.</p> 10436 * 10437 * @see #getDrawingCache() 10438 * @see #destroyDrawingCache() 10439 */ 10440 public void buildDrawingCache(boolean autoScale) { 10441 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ? 10442 mDrawingCache == null : mUnscaledDrawingCache == null)) { 10443 mCachingFailed = false; 10444 10445 if (ViewDebug.TRACE_HIERARCHY) { 10446 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE); 10447 } 10448 10449 int width = mRight - mLeft; 10450 int height = mBottom - mTop; 10451 10452 final AttachInfo attachInfo = mAttachInfo; 10453 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 10454 10455 if (autoScale && scalingRequired) { 10456 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 10457 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 10458 } 10459 10460 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 10461 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 10462 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 10463 10464 if (width <= 0 || height <= 0 || 10465 // Projected bitmap size in bytes 10466 (width * height * (opaque && !use32BitCache ? 2 : 4) > 10467 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { 10468 destroyDrawingCache(); 10469 mCachingFailed = true; 10470 return; 10471 } 10472 10473 boolean clear = true; 10474 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 10475 10476 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 10477 Bitmap.Config quality; 10478 if (!opaque) { 10479 // Never pick ARGB_4444 because it looks awful 10480 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 10481 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 10482 case DRAWING_CACHE_QUALITY_AUTO: 10483 quality = Bitmap.Config.ARGB_8888; 10484 break; 10485 case DRAWING_CACHE_QUALITY_LOW: 10486 quality = Bitmap.Config.ARGB_8888; 10487 break; 10488 case DRAWING_CACHE_QUALITY_HIGH: 10489 quality = Bitmap.Config.ARGB_8888; 10490 break; 10491 default: 10492 quality = Bitmap.Config.ARGB_8888; 10493 break; 10494 } 10495 } else { 10496 // Optimization for translucent windows 10497 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 10498 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 10499 } 10500 10501 // Try to cleanup memory 10502 if (bitmap != null) bitmap.recycle(); 10503 10504 try { 10505 bitmap = Bitmap.createBitmap(width, height, quality); 10506 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 10507 if (autoScale) { 10508 mDrawingCache = bitmap; 10509 } else { 10510 mUnscaledDrawingCache = bitmap; 10511 } 10512 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 10513 } catch (OutOfMemoryError e) { 10514 // If there is not enough memory to create the bitmap cache, just 10515 // ignore the issue as bitmap caches are not required to draw the 10516 // view hierarchy 10517 if (autoScale) { 10518 mDrawingCache = null; 10519 } else { 10520 mUnscaledDrawingCache = null; 10521 } 10522 mCachingFailed = true; 10523 return; 10524 } 10525 10526 clear = drawingCacheBackgroundColor != 0; 10527 } 10528 10529 Canvas canvas; 10530 if (attachInfo != null) { 10531 canvas = attachInfo.mCanvas; 10532 if (canvas == null) { 10533 canvas = new Canvas(); 10534 } 10535 canvas.setBitmap(bitmap); 10536 // Temporarily clobber the cached Canvas in case one of our children 10537 // is also using a drawing cache. Without this, the children would 10538 // steal the canvas by attaching their own bitmap to it and bad, bad 10539 // thing would happen (invisible views, corrupted drawings, etc.) 10540 attachInfo.mCanvas = null; 10541 } else { 10542 // This case should hopefully never or seldom happen 10543 canvas = new Canvas(bitmap); 10544 } 10545 10546 if (clear) { 10547 bitmap.eraseColor(drawingCacheBackgroundColor); 10548 } 10549 10550 computeScroll(); 10551 final int restoreCount = canvas.save(); 10552 10553 if (autoScale && scalingRequired) { 10554 final float scale = attachInfo.mApplicationScale; 10555 canvas.scale(scale, scale); 10556 } 10557 10558 canvas.translate(-mScrollX, -mScrollY); 10559 10560 mPrivateFlags |= DRAWN; 10561 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 10562 mLayerType != LAYER_TYPE_NONE) { 10563 mPrivateFlags |= DRAWING_CACHE_VALID; 10564 } 10565 10566 // Fast path for layouts with no backgrounds 10567 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 10568 if (ViewDebug.TRACE_HIERARCHY) { 10569 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 10570 } 10571 mPrivateFlags &= ~DIRTY_MASK; 10572 dispatchDraw(canvas); 10573 } else { 10574 draw(canvas); 10575 } 10576 10577 canvas.restoreToCount(restoreCount); 10578 canvas.setBitmap(null); 10579 10580 if (attachInfo != null) { 10581 // Restore the cached Canvas for our siblings 10582 attachInfo.mCanvas = canvas; 10583 } 10584 } 10585 } 10586 10587 /** 10588 * Create a snapshot of the view into a bitmap. We should probably make 10589 * some form of this public, but should think about the API. 10590 */ 10591 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 10592 int width = mRight - mLeft; 10593 int height = mBottom - mTop; 10594 10595 final AttachInfo attachInfo = mAttachInfo; 10596 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 10597 width = (int) ((width * scale) + 0.5f); 10598 height = (int) ((height * scale) + 0.5f); 10599 10600 Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality); 10601 if (bitmap == null) { 10602 throw new OutOfMemoryError(); 10603 } 10604 10605 Resources resources = getResources(); 10606 if (resources != null) { 10607 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 10608 } 10609 10610 Canvas canvas; 10611 if (attachInfo != null) { 10612 canvas = attachInfo.mCanvas; 10613 if (canvas == null) { 10614 canvas = new Canvas(); 10615 } 10616 canvas.setBitmap(bitmap); 10617 // Temporarily clobber the cached Canvas in case one of our children 10618 // is also using a drawing cache. Without this, the children would 10619 // steal the canvas by attaching their own bitmap to it and bad, bad 10620 // things would happen (invisible views, corrupted drawings, etc.) 10621 attachInfo.mCanvas = null; 10622 } else { 10623 // This case should hopefully never or seldom happen 10624 canvas = new Canvas(bitmap); 10625 } 10626 10627 if ((backgroundColor & 0xff000000) != 0) { 10628 bitmap.eraseColor(backgroundColor); 10629 } 10630 10631 computeScroll(); 10632 final int restoreCount = canvas.save(); 10633 canvas.scale(scale, scale); 10634 canvas.translate(-mScrollX, -mScrollY); 10635 10636 // Temporarily remove the dirty mask 10637 int flags = mPrivateFlags; 10638 mPrivateFlags &= ~DIRTY_MASK; 10639 10640 // Fast path for layouts with no backgrounds 10641 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 10642 dispatchDraw(canvas); 10643 } else { 10644 draw(canvas); 10645 } 10646 10647 mPrivateFlags = flags; 10648 10649 canvas.restoreToCount(restoreCount); 10650 canvas.setBitmap(null); 10651 10652 if (attachInfo != null) { 10653 // Restore the cached Canvas for our siblings 10654 attachInfo.mCanvas = canvas; 10655 } 10656 10657 return bitmap; 10658 } 10659 10660 /** 10661 * Indicates whether this View is currently in edit mode. A View is usually 10662 * in edit mode when displayed within a developer tool. For instance, if 10663 * this View is being drawn by a visual user interface builder, this method 10664 * should return true. 10665 * 10666 * Subclasses should check the return value of this method to provide 10667 * different behaviors if their normal behavior might interfere with the 10668 * host environment. For instance: the class spawns a thread in its 10669 * constructor, the drawing code relies on device-specific features, etc. 10670 * 10671 * This method is usually checked in the drawing code of custom widgets. 10672 * 10673 * @return True if this View is in edit mode, false otherwise. 10674 */ 10675 public boolean isInEditMode() { 10676 return false; 10677 } 10678 10679 /** 10680 * If the View draws content inside its padding and enables fading edges, 10681 * it needs to support padding offsets. Padding offsets are added to the 10682 * fading edges to extend the length of the fade so that it covers pixels 10683 * drawn inside the padding. 10684 * 10685 * Subclasses of this class should override this method if they need 10686 * to draw content inside the padding. 10687 * 10688 * @return True if padding offset must be applied, false otherwise. 10689 * 10690 * @see #getLeftPaddingOffset() 10691 * @see #getRightPaddingOffset() 10692 * @see #getTopPaddingOffset() 10693 * @see #getBottomPaddingOffset() 10694 * 10695 * @since CURRENT 10696 */ 10697 protected boolean isPaddingOffsetRequired() { 10698 return false; 10699 } 10700 10701 /** 10702 * Amount by which to extend the left fading region. Called only when 10703 * {@link #isPaddingOffsetRequired()} returns true. 10704 * 10705 * @return The left padding offset in pixels. 10706 * 10707 * @see #isPaddingOffsetRequired() 10708 * 10709 * @since CURRENT 10710 */ 10711 protected int getLeftPaddingOffset() { 10712 return 0; 10713 } 10714 10715 /** 10716 * Amount by which to extend the right fading region. Called only when 10717 * {@link #isPaddingOffsetRequired()} returns true. 10718 * 10719 * @return The right padding offset in pixels. 10720 * 10721 * @see #isPaddingOffsetRequired() 10722 * 10723 * @since CURRENT 10724 */ 10725 protected int getRightPaddingOffset() { 10726 return 0; 10727 } 10728 10729 /** 10730 * Amount by which to extend the top fading region. Called only when 10731 * {@link #isPaddingOffsetRequired()} returns true. 10732 * 10733 * @return The top padding offset in pixels. 10734 * 10735 * @see #isPaddingOffsetRequired() 10736 * 10737 * @since CURRENT 10738 */ 10739 protected int getTopPaddingOffset() { 10740 return 0; 10741 } 10742 10743 /** 10744 * Amount by which to extend the bottom fading region. Called only when 10745 * {@link #isPaddingOffsetRequired()} returns true. 10746 * 10747 * @return The bottom padding offset in pixels. 10748 * 10749 * @see #isPaddingOffsetRequired() 10750 * 10751 * @since CURRENT 10752 */ 10753 protected int getBottomPaddingOffset() { 10754 return 0; 10755 } 10756 10757 /** 10758 * @hide 10759 * @param offsetRequired 10760 */ 10761 protected int getFadeTop(boolean offsetRequired) { 10762 int top = mPaddingTop; 10763 if (offsetRequired) top += getTopPaddingOffset(); 10764 return top; 10765 } 10766 10767 /** 10768 * @hide 10769 * @param offsetRequired 10770 */ 10771 protected int getFadeHeight(boolean offsetRequired) { 10772 int padding = mPaddingTop; 10773 if (offsetRequired) padding += getTopPaddingOffset(); 10774 return mBottom - mTop - mPaddingBottom - padding; 10775 } 10776 10777 /** 10778 * <p>Indicates whether this view is attached to an hardware accelerated 10779 * window or not.</p> 10780 * 10781 * <p>Even if this method returns true, it does not mean that every call 10782 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 10783 * accelerated {@link android.graphics.Canvas}. For instance, if this view 10784 * is drawn onto an offscren {@link android.graphics.Bitmap} and its 10785 * window is hardware accelerated, 10786 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 10787 * return false, and this method will return true.</p> 10788 * 10789 * @return True if the view is attached to a window and the window is 10790 * hardware accelerated; false in any other case. 10791 */ 10792 public boolean isHardwareAccelerated() { 10793 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 10794 } 10795 10796 /** 10797 * Manually render this view (and all of its children) to the given Canvas. 10798 * The view must have already done a full layout before this function is 10799 * called. When implementing a view, implement 10800 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 10801 * If you do need to override this method, call the superclass version. 10802 * 10803 * @param canvas The Canvas to which the View is rendered. 10804 */ 10805 public void draw(Canvas canvas) { 10806 if (ViewDebug.TRACE_HIERARCHY) { 10807 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 10808 } 10809 10810 final int privateFlags = mPrivateFlags; 10811 final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE && 10812 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 10813 mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN; 10814 10815 /* 10816 * Draw traversal performs several drawing steps which must be executed 10817 * in the appropriate order: 10818 * 10819 * 1. Draw the background 10820 * 2. If necessary, save the canvas' layers to prepare for fading 10821 * 3. Draw view's content 10822 * 4. Draw children 10823 * 5. If necessary, draw the fading edges and restore layers 10824 * 6. Draw decorations (scrollbars for instance) 10825 */ 10826 10827 // Step 1, draw the background, if needed 10828 int saveCount; 10829 10830 if (!dirtyOpaque) { 10831 final Drawable background = mBGDrawable; 10832 if (background != null) { 10833 final int scrollX = mScrollX; 10834 final int scrollY = mScrollY; 10835 10836 if (mBackgroundSizeChanged) { 10837 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 10838 mBackgroundSizeChanged = false; 10839 } 10840 10841 if ((scrollX | scrollY) == 0) { 10842 background.draw(canvas); 10843 } else { 10844 canvas.translate(scrollX, scrollY); 10845 background.draw(canvas); 10846 canvas.translate(-scrollX, -scrollY); 10847 } 10848 } 10849 } 10850 10851 // skip step 2 & 5 if possible (common case) 10852 final int viewFlags = mViewFlags; 10853 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 10854 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 10855 if (!verticalEdges && !horizontalEdges) { 10856 // Step 3, draw the content 10857 if (!dirtyOpaque) onDraw(canvas); 10858 10859 // Step 4, draw the children 10860 dispatchDraw(canvas); 10861 10862 // Step 6, draw decorations (scrollbars) 10863 onDrawScrollBars(canvas); 10864 10865 // we're done... 10866 return; 10867 } 10868 10869 /* 10870 * Here we do the full fledged routine... 10871 * (this is an uncommon case where speed matters less, 10872 * this is why we repeat some of the tests that have been 10873 * done above) 10874 */ 10875 10876 boolean drawTop = false; 10877 boolean drawBottom = false; 10878 boolean drawLeft = false; 10879 boolean drawRight = false; 10880 10881 float topFadeStrength = 0.0f; 10882 float bottomFadeStrength = 0.0f; 10883 float leftFadeStrength = 0.0f; 10884 float rightFadeStrength = 0.0f; 10885 10886 // Step 2, save the canvas' layers 10887 int paddingLeft = mPaddingLeft; 10888 10889 final boolean offsetRequired = isPaddingOffsetRequired(); 10890 if (offsetRequired) { 10891 paddingLeft += getLeftPaddingOffset(); 10892 } 10893 10894 int left = mScrollX + paddingLeft; 10895 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 10896 int top = mScrollY + getFadeTop(offsetRequired); 10897 int bottom = top + getFadeHeight(offsetRequired); 10898 10899 if (offsetRequired) { 10900 right += getRightPaddingOffset(); 10901 bottom += getBottomPaddingOffset(); 10902 } 10903 10904 final ScrollabilityCache scrollabilityCache = mScrollCache; 10905 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 10906 int length = (int) fadeHeight; 10907 10908 // clip the fade length if top and bottom fades overlap 10909 // overlapping fades produce odd-looking artifacts 10910 if (verticalEdges && (top + length > bottom - length)) { 10911 length = (bottom - top) / 2; 10912 } 10913 10914 // also clip horizontal fades if necessary 10915 if (horizontalEdges && (left + length > right - length)) { 10916 length = (right - left) / 2; 10917 } 10918 10919 if (verticalEdges) { 10920 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 10921 drawTop = topFadeStrength * fadeHeight > 1.0f; 10922 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 10923 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 10924 } 10925 10926 if (horizontalEdges) { 10927 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 10928 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 10929 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 10930 drawRight = rightFadeStrength * fadeHeight > 1.0f; 10931 } 10932 10933 saveCount = canvas.getSaveCount(); 10934 10935 int solidColor = getSolidColor(); 10936 if (solidColor == 0) { 10937 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 10938 10939 if (drawTop) { 10940 canvas.saveLayer(left, top, right, top + length, null, flags); 10941 } 10942 10943 if (drawBottom) { 10944 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 10945 } 10946 10947 if (drawLeft) { 10948 canvas.saveLayer(left, top, left + length, bottom, null, flags); 10949 } 10950 10951 if (drawRight) { 10952 canvas.saveLayer(right - length, top, right, bottom, null, flags); 10953 } 10954 } else { 10955 scrollabilityCache.setFadeColor(solidColor); 10956 } 10957 10958 // Step 3, draw the content 10959 if (!dirtyOpaque) onDraw(canvas); 10960 10961 // Step 4, draw the children 10962 dispatchDraw(canvas); 10963 10964 // Step 5, draw the fade effect and restore layers 10965 final Paint p = scrollabilityCache.paint; 10966 final Matrix matrix = scrollabilityCache.matrix; 10967 final Shader fade = scrollabilityCache.shader; 10968 10969 if (drawTop) { 10970 matrix.setScale(1, fadeHeight * topFadeStrength); 10971 matrix.postTranslate(left, top); 10972 fade.setLocalMatrix(matrix); 10973 canvas.drawRect(left, top, right, top + length, p); 10974 } 10975 10976 if (drawBottom) { 10977 matrix.setScale(1, fadeHeight * bottomFadeStrength); 10978 matrix.postRotate(180); 10979 matrix.postTranslate(left, bottom); 10980 fade.setLocalMatrix(matrix); 10981 canvas.drawRect(left, bottom - length, right, bottom, p); 10982 } 10983 10984 if (drawLeft) { 10985 matrix.setScale(1, fadeHeight * leftFadeStrength); 10986 matrix.postRotate(-90); 10987 matrix.postTranslate(left, top); 10988 fade.setLocalMatrix(matrix); 10989 canvas.drawRect(left, top, left + length, bottom, p); 10990 } 10991 10992 if (drawRight) { 10993 matrix.setScale(1, fadeHeight * rightFadeStrength); 10994 matrix.postRotate(90); 10995 matrix.postTranslate(right, top); 10996 fade.setLocalMatrix(matrix); 10997 canvas.drawRect(right - length, top, right, bottom, p); 10998 } 10999 11000 canvas.restoreToCount(saveCount); 11001 11002 // Step 6, draw decorations (scrollbars) 11003 onDrawScrollBars(canvas); 11004 } 11005 11006 /** 11007 * Override this if your view is known to always be drawn on top of a solid color background, 11008 * and needs to draw fading edges. Returning a non-zero color enables the view system to 11009 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 11010 * should be set to 0xFF. 11011 * 11012 * @see #setVerticalFadingEdgeEnabled(boolean) 11013 * @see #setHorizontalFadingEdgeEnabled(boolean) 11014 * 11015 * @return The known solid color background for this view, or 0 if the color may vary 11016 */ 11017 @ViewDebug.ExportedProperty(category = "drawing") 11018 public int getSolidColor() { 11019 return 0; 11020 } 11021 11022 /** 11023 * Build a human readable string representation of the specified view flags. 11024 * 11025 * @param flags the view flags to convert to a string 11026 * @return a String representing the supplied flags 11027 */ 11028 private static String printFlags(int flags) { 11029 String output = ""; 11030 int numFlags = 0; 11031 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 11032 output += "TAKES_FOCUS"; 11033 numFlags++; 11034 } 11035 11036 switch (flags & VISIBILITY_MASK) { 11037 case INVISIBLE: 11038 if (numFlags > 0) { 11039 output += " "; 11040 } 11041 output += "INVISIBLE"; 11042 // USELESS HERE numFlags++; 11043 break; 11044 case GONE: 11045 if (numFlags > 0) { 11046 output += " "; 11047 } 11048 output += "GONE"; 11049 // USELESS HERE numFlags++; 11050 break; 11051 default: 11052 break; 11053 } 11054 return output; 11055 } 11056 11057 /** 11058 * Build a human readable string representation of the specified private 11059 * view flags. 11060 * 11061 * @param privateFlags the private view flags to convert to a string 11062 * @return a String representing the supplied flags 11063 */ 11064 private static String printPrivateFlags(int privateFlags) { 11065 String output = ""; 11066 int numFlags = 0; 11067 11068 if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) { 11069 output += "WANTS_FOCUS"; 11070 numFlags++; 11071 } 11072 11073 if ((privateFlags & FOCUSED) == FOCUSED) { 11074 if (numFlags > 0) { 11075 output += " "; 11076 } 11077 output += "FOCUSED"; 11078 numFlags++; 11079 } 11080 11081 if ((privateFlags & SELECTED) == SELECTED) { 11082 if (numFlags > 0) { 11083 output += " "; 11084 } 11085 output += "SELECTED"; 11086 numFlags++; 11087 } 11088 11089 if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) { 11090 if (numFlags > 0) { 11091 output += " "; 11092 } 11093 output += "IS_ROOT_NAMESPACE"; 11094 numFlags++; 11095 } 11096 11097 if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) { 11098 if (numFlags > 0) { 11099 output += " "; 11100 } 11101 output += "HAS_BOUNDS"; 11102 numFlags++; 11103 } 11104 11105 if ((privateFlags & DRAWN) == DRAWN) { 11106 if (numFlags > 0) { 11107 output += " "; 11108 } 11109 output += "DRAWN"; 11110 // USELESS HERE numFlags++; 11111 } 11112 return output; 11113 } 11114 11115 /** 11116 * <p>Indicates whether or not this view's layout will be requested during 11117 * the next hierarchy layout pass.</p> 11118 * 11119 * @return true if the layout will be forced during next layout pass 11120 */ 11121 public boolean isLayoutRequested() { 11122 return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT; 11123 } 11124 11125 /** 11126 * Assign a size and position to a view and all of its 11127 * descendants 11128 * 11129 * <p>This is the second phase of the layout mechanism. 11130 * (The first is measuring). In this phase, each parent calls 11131 * layout on all of its children to position them. 11132 * This is typically done using the child measurements 11133 * that were stored in the measure pass().</p> 11134 * 11135 * <p>Derived classes should not override this method. 11136 * Derived classes with children should override 11137 * onLayout. In that method, they should 11138 * call layout on each of their children.</p> 11139 * 11140 * @param l Left position, relative to parent 11141 * @param t Top position, relative to parent 11142 * @param r Right position, relative to parent 11143 * @param b Bottom position, relative to parent 11144 */ 11145 @SuppressWarnings({"unchecked"}) 11146 public void layout(int l, int t, int r, int b) { 11147 int oldL = mLeft; 11148 int oldT = mTop; 11149 int oldB = mBottom; 11150 int oldR = mRight; 11151 boolean changed = setFrame(l, t, r, b); 11152 if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) { 11153 if (ViewDebug.TRACE_HIERARCHY) { 11154 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT); 11155 } 11156 11157 onLayout(changed, l, t, r, b); 11158 mPrivateFlags &= ~LAYOUT_REQUIRED; 11159 11160 if (mOnLayoutChangeListeners != null) { 11161 ArrayList<OnLayoutChangeListener> listenersCopy = 11162 (ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone(); 11163 int numListeners = listenersCopy.size(); 11164 for (int i = 0; i < numListeners; ++i) { 11165 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 11166 } 11167 } 11168 } 11169 mPrivateFlags &= ~FORCE_LAYOUT; 11170 } 11171 11172 /** 11173 * Called from layout when this view should 11174 * assign a size and position to each of its children. 11175 * 11176 * Derived classes with children should override 11177 * this method and call layout on each of 11178 * their children. 11179 * @param changed This is a new size or position for this view 11180 * @param left Left position, relative to parent 11181 * @param top Top position, relative to parent 11182 * @param right Right position, relative to parent 11183 * @param bottom Bottom position, relative to parent 11184 */ 11185 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 11186 } 11187 11188 /** 11189 * Assign a size and position to this view. 11190 * 11191 * This is called from layout. 11192 * 11193 * @param left Left position, relative to parent 11194 * @param top Top position, relative to parent 11195 * @param right Right position, relative to parent 11196 * @param bottom Bottom position, relative to parent 11197 * @return true if the new size and position are different than the 11198 * previous ones 11199 * {@hide} 11200 */ 11201 protected boolean setFrame(int left, int top, int right, int bottom) { 11202 boolean changed = false; 11203 11204 if (DBG) { 11205 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 11206 + right + "," + bottom + ")"); 11207 } 11208 11209 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 11210 changed = true; 11211 11212 // Remember our drawn bit 11213 int drawn = mPrivateFlags & DRAWN; 11214 11215 int oldWidth = mRight - mLeft; 11216 int oldHeight = mBottom - mTop; 11217 int newWidth = right - left; 11218 int newHeight = bottom - top; 11219 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 11220 11221 // Invalidate our old position 11222 invalidate(sizeChanged); 11223 11224 mLeft = left; 11225 mTop = top; 11226 mRight = right; 11227 mBottom = bottom; 11228 11229 mPrivateFlags |= HAS_BOUNDS; 11230 11231 11232 if (sizeChanged) { 11233 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { 11234 // A change in dimension means an auto-centered pivot point changes, too 11235 if (mTransformationInfo != null) { 11236 mTransformationInfo.mMatrixDirty = true; 11237 } 11238 } 11239 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 11240 } 11241 11242 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { 11243 // If we are visible, force the DRAWN bit to on so that 11244 // this invalidate will go through (at least to our parent). 11245 // This is because someone may have invalidated this view 11246 // before this call to setFrame came in, thereby clearing 11247 // the DRAWN bit. 11248 mPrivateFlags |= DRAWN; 11249 invalidate(sizeChanged); 11250 // parent display list may need to be recreated based on a change in the bounds 11251 // of any child 11252 invalidateParentCaches(); 11253 } 11254 11255 // Reset drawn bit to original value (invalidate turns it off) 11256 mPrivateFlags |= drawn; 11257 11258 mBackgroundSizeChanged = true; 11259 } 11260 return changed; 11261 } 11262 11263 /** 11264 * Finalize inflating a view from XML. This is called as the last phase 11265 * of inflation, after all child views have been added. 11266 * 11267 * <p>Even if the subclass overrides onFinishInflate, they should always be 11268 * sure to call the super method, so that we get called. 11269 */ 11270 protected void onFinishInflate() { 11271 } 11272 11273 /** 11274 * Returns the resources associated with this view. 11275 * 11276 * @return Resources object. 11277 */ 11278 public Resources getResources() { 11279 return mResources; 11280 } 11281 11282 /** 11283 * Invalidates the specified Drawable. 11284 * 11285 * @param drawable the drawable to invalidate 11286 */ 11287 public void invalidateDrawable(Drawable drawable) { 11288 if (verifyDrawable(drawable)) { 11289 final Rect dirty = drawable.getBounds(); 11290 final int scrollX = mScrollX; 11291 final int scrollY = mScrollY; 11292 11293 invalidate(dirty.left + scrollX, dirty.top + scrollY, 11294 dirty.right + scrollX, dirty.bottom + scrollY); 11295 } 11296 } 11297 11298 /** 11299 * Schedules an action on a drawable to occur at a specified time. 11300 * 11301 * @param who the recipient of the action 11302 * @param what the action to run on the drawable 11303 * @param when the time at which the action must occur. Uses the 11304 * {@link SystemClock#uptimeMillis} timebase. 11305 */ 11306 public void scheduleDrawable(Drawable who, Runnable what, long when) { 11307 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 11308 mAttachInfo.mHandler.postAtTime(what, who, when); 11309 } 11310 } 11311 11312 /** 11313 * Cancels a scheduled action on a drawable. 11314 * 11315 * @param who the recipient of the action 11316 * @param what the action to cancel 11317 */ 11318 public void unscheduleDrawable(Drawable who, Runnable what) { 11319 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 11320 mAttachInfo.mHandler.removeCallbacks(what, who); 11321 } 11322 } 11323 11324 /** 11325 * Unschedule any events associated with the given Drawable. This can be 11326 * used when selecting a new Drawable into a view, so that the previous 11327 * one is completely unscheduled. 11328 * 11329 * @param who The Drawable to unschedule. 11330 * 11331 * @see #drawableStateChanged 11332 */ 11333 public void unscheduleDrawable(Drawable who) { 11334 if (mAttachInfo != null) { 11335 mAttachInfo.mHandler.removeCallbacksAndMessages(who); 11336 } 11337 } 11338 11339 /** 11340 * Return the layout direction of a given Drawable. 11341 * 11342 * @param who the Drawable to query 11343 * 11344 * @hide 11345 */ 11346 public int getResolvedLayoutDirection(Drawable who) { 11347 return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT; 11348 } 11349 11350 /** 11351 * If your view subclass is displaying its own Drawable objects, it should 11352 * override this function and return true for any Drawable it is 11353 * displaying. This allows animations for those drawables to be 11354 * scheduled. 11355 * 11356 * <p>Be sure to call through to the super class when overriding this 11357 * function. 11358 * 11359 * @param who The Drawable to verify. Return true if it is one you are 11360 * displaying, else return the result of calling through to the 11361 * super class. 11362 * 11363 * @return boolean If true than the Drawable is being displayed in the 11364 * view; else false and it is not allowed to animate. 11365 * 11366 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 11367 * @see #drawableStateChanged() 11368 */ 11369 protected boolean verifyDrawable(Drawable who) { 11370 return who == mBGDrawable; 11371 } 11372 11373 /** 11374 * This function is called whenever the state of the view changes in such 11375 * a way that it impacts the state of drawables being shown. 11376 * 11377 * <p>Be sure to call through to the superclass when overriding this 11378 * function. 11379 * 11380 * @see Drawable#setState(int[]) 11381 */ 11382 protected void drawableStateChanged() { 11383 Drawable d = mBGDrawable; 11384 if (d != null && d.isStateful()) { 11385 d.setState(getDrawableState()); 11386 } 11387 } 11388 11389 /** 11390 * Call this to force a view to update its drawable state. This will cause 11391 * drawableStateChanged to be called on this view. Views that are interested 11392 * in the new state should call getDrawableState. 11393 * 11394 * @see #drawableStateChanged 11395 * @see #getDrawableState 11396 */ 11397 public void refreshDrawableState() { 11398 mPrivateFlags |= DRAWABLE_STATE_DIRTY; 11399 drawableStateChanged(); 11400 11401 ViewParent parent = mParent; 11402 if (parent != null) { 11403 parent.childDrawableStateChanged(this); 11404 } 11405 } 11406 11407 /** 11408 * Return an array of resource IDs of the drawable states representing the 11409 * current state of the view. 11410 * 11411 * @return The current drawable state 11412 * 11413 * @see Drawable#setState(int[]) 11414 * @see #drawableStateChanged() 11415 * @see #onCreateDrawableState(int) 11416 */ 11417 public final int[] getDrawableState() { 11418 if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) { 11419 return mDrawableState; 11420 } else { 11421 mDrawableState = onCreateDrawableState(0); 11422 mPrivateFlags &= ~DRAWABLE_STATE_DIRTY; 11423 return mDrawableState; 11424 } 11425 } 11426 11427 /** 11428 * Generate the new {@link android.graphics.drawable.Drawable} state for 11429 * this view. This is called by the view 11430 * system when the cached Drawable state is determined to be invalid. To 11431 * retrieve the current state, you should use {@link #getDrawableState}. 11432 * 11433 * @param extraSpace if non-zero, this is the number of extra entries you 11434 * would like in the returned array in which you can place your own 11435 * states. 11436 * 11437 * @return Returns an array holding the current {@link Drawable} state of 11438 * the view. 11439 * 11440 * @see #mergeDrawableStates(int[], int[]) 11441 */ 11442 protected int[] onCreateDrawableState(int extraSpace) { 11443 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 11444 mParent instanceof View) { 11445 return ((View) mParent).onCreateDrawableState(extraSpace); 11446 } 11447 11448 int[] drawableState; 11449 11450 int privateFlags = mPrivateFlags; 11451 11452 int viewStateIndex = 0; 11453 if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED; 11454 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED; 11455 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED; 11456 if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED; 11457 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED; 11458 if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED; 11459 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 11460 HardwareRenderer.isAvailable()) { 11461 // This is set if HW acceleration is requested, even if the current 11462 // process doesn't allow it. This is just to allow app preview 11463 // windows to better match their app. 11464 viewStateIndex |= VIEW_STATE_ACCELERATED; 11465 } 11466 if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED; 11467 11468 final int privateFlags2 = mPrivateFlags2; 11469 if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT; 11470 if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED; 11471 11472 drawableState = VIEW_STATE_SETS[viewStateIndex]; 11473 11474 //noinspection ConstantIfStatement 11475 if (false) { 11476 Log.i("View", "drawableStateIndex=" + viewStateIndex); 11477 Log.i("View", toString() 11478 + " pressed=" + ((privateFlags & PRESSED) != 0) 11479 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 11480 + " fo=" + hasFocus() 11481 + " sl=" + ((privateFlags & SELECTED) != 0) 11482 + " wf=" + hasWindowFocus() 11483 + ": " + Arrays.toString(drawableState)); 11484 } 11485 11486 if (extraSpace == 0) { 11487 return drawableState; 11488 } 11489 11490 final int[] fullState; 11491 if (drawableState != null) { 11492 fullState = new int[drawableState.length + extraSpace]; 11493 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 11494 } else { 11495 fullState = new int[extraSpace]; 11496 } 11497 11498 return fullState; 11499 } 11500 11501 /** 11502 * Merge your own state values in <var>additionalState</var> into the base 11503 * state values <var>baseState</var> that were returned by 11504 * {@link #onCreateDrawableState(int)}. 11505 * 11506 * @param baseState The base state values returned by 11507 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 11508 * own additional state values. 11509 * 11510 * @param additionalState The additional state values you would like 11511 * added to <var>baseState</var>; this array is not modified. 11512 * 11513 * @return As a convenience, the <var>baseState</var> array you originally 11514 * passed into the function is returned. 11515 * 11516 * @see #onCreateDrawableState(int) 11517 */ 11518 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 11519 final int N = baseState.length; 11520 int i = N - 1; 11521 while (i >= 0 && baseState[i] == 0) { 11522 i--; 11523 } 11524 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 11525 return baseState; 11526 } 11527 11528 /** 11529 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 11530 * on all Drawable objects associated with this view. 11531 */ 11532 public void jumpDrawablesToCurrentState() { 11533 if (mBGDrawable != null) { 11534 mBGDrawable.jumpToCurrentState(); 11535 } 11536 } 11537 11538 /** 11539 * Sets the background color for this view. 11540 * @param color the color of the background 11541 */ 11542 @RemotableViewMethod 11543 public void setBackgroundColor(int color) { 11544 if (mBGDrawable instanceof ColorDrawable) { 11545 ((ColorDrawable) mBGDrawable).setColor(color); 11546 } else { 11547 setBackgroundDrawable(new ColorDrawable(color)); 11548 } 11549 } 11550 11551 /** 11552 * Set the background to a given resource. The resource should refer to 11553 * a Drawable object or 0 to remove the background. 11554 * @param resid The identifier of the resource. 11555 * @attr ref android.R.styleable#View_background 11556 */ 11557 @RemotableViewMethod 11558 public void setBackgroundResource(int resid) { 11559 if (resid != 0 && resid == mBackgroundResource) { 11560 return; 11561 } 11562 11563 Drawable d= null; 11564 if (resid != 0) { 11565 d = mResources.getDrawable(resid); 11566 } 11567 setBackgroundDrawable(d); 11568 11569 mBackgroundResource = resid; 11570 } 11571 11572 /** 11573 * Set the background to a given Drawable, or remove the background. If the 11574 * background has padding, this View's padding is set to the background's 11575 * padding. However, when a background is removed, this View's padding isn't 11576 * touched. If setting the padding is desired, please use 11577 * {@link #setPadding(int, int, int, int)}. 11578 * 11579 * @param d The Drawable to use as the background, or null to remove the 11580 * background 11581 */ 11582 public void setBackgroundDrawable(Drawable d) { 11583 if (d == mBGDrawable) { 11584 return; 11585 } 11586 11587 boolean requestLayout = false; 11588 11589 mBackgroundResource = 0; 11590 11591 /* 11592 * Regardless of whether we're setting a new background or not, we want 11593 * to clear the previous drawable. 11594 */ 11595 if (mBGDrawable != null) { 11596 mBGDrawable.setCallback(null); 11597 unscheduleDrawable(mBGDrawable); 11598 } 11599 11600 if (d != null) { 11601 Rect padding = sThreadLocal.get(); 11602 if (padding == null) { 11603 padding = new Rect(); 11604 sThreadLocal.set(padding); 11605 } 11606 if (d.getPadding(padding)) { 11607 switch (d.getResolvedLayoutDirectionSelf()) { 11608 case LAYOUT_DIRECTION_RTL: 11609 setPadding(padding.right, padding.top, padding.left, padding.bottom); 11610 break; 11611 case LAYOUT_DIRECTION_LTR: 11612 default: 11613 setPadding(padding.left, padding.top, padding.right, padding.bottom); 11614 } 11615 } 11616 11617 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 11618 // if it has a different minimum size, we should layout again 11619 if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() || 11620 mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) { 11621 requestLayout = true; 11622 } 11623 11624 d.setCallback(this); 11625 if (d.isStateful()) { 11626 d.setState(getDrawableState()); 11627 } 11628 d.setVisible(getVisibility() == VISIBLE, false); 11629 mBGDrawable = d; 11630 11631 if ((mPrivateFlags & SKIP_DRAW) != 0) { 11632 mPrivateFlags &= ~SKIP_DRAW; 11633 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 11634 requestLayout = true; 11635 } 11636 } else { 11637 /* Remove the background */ 11638 mBGDrawable = null; 11639 11640 if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) { 11641 /* 11642 * This view ONLY drew the background before and we're removing 11643 * the background, so now it won't draw anything 11644 * (hence we SKIP_DRAW) 11645 */ 11646 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND; 11647 mPrivateFlags |= SKIP_DRAW; 11648 } 11649 11650 /* 11651 * When the background is set, we try to apply its padding to this 11652 * View. When the background is removed, we don't touch this View's 11653 * padding. This is noted in the Javadocs. Hence, we don't need to 11654 * requestLayout(), the invalidate() below is sufficient. 11655 */ 11656 11657 // The old background's minimum size could have affected this 11658 // View's layout, so let's requestLayout 11659 requestLayout = true; 11660 } 11661 11662 computeOpaqueFlags(); 11663 11664 if (requestLayout) { 11665 requestLayout(); 11666 } 11667 11668 mBackgroundSizeChanged = true; 11669 invalidate(true); 11670 } 11671 11672 /** 11673 * Gets the background drawable 11674 * @return The drawable used as the background for this view, if any. 11675 */ 11676 public Drawable getBackground() { 11677 return mBGDrawable; 11678 } 11679 11680 /** 11681 * Sets the padding. The view may add on the space required to display 11682 * the scrollbars, depending on the style and visibility of the scrollbars. 11683 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 11684 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 11685 * from the values set in this call. 11686 * 11687 * @attr ref android.R.styleable#View_padding 11688 * @attr ref android.R.styleable#View_paddingBottom 11689 * @attr ref android.R.styleable#View_paddingLeft 11690 * @attr ref android.R.styleable#View_paddingRight 11691 * @attr ref android.R.styleable#View_paddingTop 11692 * @param left the left padding in pixels 11693 * @param top the top padding in pixels 11694 * @param right the right padding in pixels 11695 * @param bottom the bottom padding in pixels 11696 */ 11697 public void setPadding(int left, int top, int right, int bottom) { 11698 boolean changed = false; 11699 11700 mUserPaddingRelative = false; 11701 11702 mUserPaddingLeft = left; 11703 mUserPaddingRight = right; 11704 mUserPaddingBottom = bottom; 11705 11706 final int viewFlags = mViewFlags; 11707 11708 // Common case is there are no scroll bars. 11709 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 11710 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 11711 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 11712 ? 0 : getVerticalScrollbarWidth(); 11713 switch (mVerticalScrollbarPosition) { 11714 case SCROLLBAR_POSITION_DEFAULT: 11715 if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) { 11716 left += offset; 11717 } else { 11718 right += offset; 11719 } 11720 break; 11721 case SCROLLBAR_POSITION_RIGHT: 11722 right += offset; 11723 break; 11724 case SCROLLBAR_POSITION_LEFT: 11725 left += offset; 11726 break; 11727 } 11728 } 11729 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 11730 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 11731 ? 0 : getHorizontalScrollbarHeight(); 11732 } 11733 } 11734 11735 if (mPaddingLeft != left) { 11736 changed = true; 11737 mPaddingLeft = left; 11738 } 11739 if (mPaddingTop != top) { 11740 changed = true; 11741 mPaddingTop = top; 11742 } 11743 if (mPaddingRight != right) { 11744 changed = true; 11745 mPaddingRight = right; 11746 } 11747 if (mPaddingBottom != bottom) { 11748 changed = true; 11749 mPaddingBottom = bottom; 11750 } 11751 11752 if (changed) { 11753 requestLayout(); 11754 } 11755 } 11756 11757 /** 11758 * Sets the relative padding. The view may add on the space required to display 11759 * the scrollbars, depending on the style and visibility of the scrollbars. 11760 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 11761 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 11762 * from the values set in this call. 11763 * 11764 * @attr ref android.R.styleable#View_padding 11765 * @attr ref android.R.styleable#View_paddingBottom 11766 * @attr ref android.R.styleable#View_paddingStart 11767 * @attr ref android.R.styleable#View_paddingEnd 11768 * @attr ref android.R.styleable#View_paddingTop 11769 * @param start the start padding in pixels 11770 * @param top the top padding in pixels 11771 * @param end the end padding in pixels 11772 * @param bottom the bottom padding in pixels 11773 * 11774 * @hide 11775 */ 11776 public void setPaddingRelative(int start, int top, int end, int bottom) { 11777 mUserPaddingRelative = true; 11778 11779 mUserPaddingStart = start; 11780 mUserPaddingEnd = end; 11781 11782 switch(getResolvedLayoutDirection()) { 11783 case LAYOUT_DIRECTION_RTL: 11784 setPadding(end, top, start, bottom); 11785 break; 11786 case LAYOUT_DIRECTION_LTR: 11787 default: 11788 setPadding(start, top, end, bottom); 11789 } 11790 } 11791 11792 /** 11793 * Returns the top padding of this view. 11794 * 11795 * @return the top padding in pixels 11796 */ 11797 public int getPaddingTop() { 11798 return mPaddingTop; 11799 } 11800 11801 /** 11802 * Returns the bottom padding of this view. If there are inset and enabled 11803 * scrollbars, this value may include the space required to display the 11804 * scrollbars as well. 11805 * 11806 * @return the bottom padding in pixels 11807 */ 11808 public int getPaddingBottom() { 11809 return mPaddingBottom; 11810 } 11811 11812 /** 11813 * Returns the left padding of this view. If there are inset and enabled 11814 * scrollbars, this value may include the space required to display the 11815 * scrollbars as well. 11816 * 11817 * @return the left padding in pixels 11818 */ 11819 public int getPaddingLeft() { 11820 return mPaddingLeft; 11821 } 11822 11823 /** 11824 * Returns the start padding of this view. If there are inset and enabled 11825 * scrollbars, this value may include the space required to display the 11826 * scrollbars as well. 11827 * 11828 * @return the start padding in pixels 11829 * 11830 * @hide 11831 */ 11832 public int getPaddingStart() { 11833 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 11834 mPaddingRight : mPaddingLeft; 11835 } 11836 11837 /** 11838 * Returns the right padding of this view. If there are inset and enabled 11839 * scrollbars, this value may include the space required to display the 11840 * scrollbars as well. 11841 * 11842 * @return the right padding in pixels 11843 */ 11844 public int getPaddingRight() { 11845 return mPaddingRight; 11846 } 11847 11848 /** 11849 * Returns the end padding of this view. If there are inset and enabled 11850 * scrollbars, this value may include the space required to display the 11851 * scrollbars as well. 11852 * 11853 * @return the end padding in pixels 11854 * 11855 * @hide 11856 */ 11857 public int getPaddingEnd() { 11858 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 11859 mPaddingLeft : mPaddingRight; 11860 } 11861 11862 /** 11863 * Return if the padding as been set thru relative values 11864 * {@link #setPaddingRelative(int, int, int, int)} or thru 11865 * @attr ref android.R.styleable#View_paddingStart or 11866 * @attr ref android.R.styleable#View_paddingEnd 11867 * 11868 * @return true if the padding is relative or false if it is not. 11869 * 11870 * @hide 11871 */ 11872 public boolean isPaddingRelative() { 11873 return mUserPaddingRelative; 11874 } 11875 11876 /** 11877 * Changes the selection state of this view. A view can be selected or not. 11878 * Note that selection is not the same as focus. Views are typically 11879 * selected in the context of an AdapterView like ListView or GridView; 11880 * the selected view is the view that is highlighted. 11881 * 11882 * @param selected true if the view must be selected, false otherwise 11883 */ 11884 public void setSelected(boolean selected) { 11885 if (((mPrivateFlags & SELECTED) != 0) != selected) { 11886 mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0); 11887 if (!selected) resetPressedState(); 11888 invalidate(true); 11889 refreshDrawableState(); 11890 dispatchSetSelected(selected); 11891 } 11892 } 11893 11894 /** 11895 * Dispatch setSelected to all of this View's children. 11896 * 11897 * @see #setSelected(boolean) 11898 * 11899 * @param selected The new selected state 11900 */ 11901 protected void dispatchSetSelected(boolean selected) { 11902 } 11903 11904 /** 11905 * Indicates the selection state of this view. 11906 * 11907 * @return true if the view is selected, false otherwise 11908 */ 11909 @ViewDebug.ExportedProperty 11910 public boolean isSelected() { 11911 return (mPrivateFlags & SELECTED) != 0; 11912 } 11913 11914 /** 11915 * Changes the activated state of this view. A view can be activated or not. 11916 * Note that activation is not the same as selection. Selection is 11917 * a transient property, representing the view (hierarchy) the user is 11918 * currently interacting with. Activation is a longer-term state that the 11919 * user can move views in and out of. For example, in a list view with 11920 * single or multiple selection enabled, the views in the current selection 11921 * set are activated. (Um, yeah, we are deeply sorry about the terminology 11922 * here.) The activated state is propagated down to children of the view it 11923 * is set on. 11924 * 11925 * @param activated true if the view must be activated, false otherwise 11926 */ 11927 public void setActivated(boolean activated) { 11928 if (((mPrivateFlags & ACTIVATED) != 0) != activated) { 11929 mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0); 11930 invalidate(true); 11931 refreshDrawableState(); 11932 dispatchSetActivated(activated); 11933 } 11934 } 11935 11936 /** 11937 * Dispatch setActivated to all of this View's children. 11938 * 11939 * @see #setActivated(boolean) 11940 * 11941 * @param activated The new activated state 11942 */ 11943 protected void dispatchSetActivated(boolean activated) { 11944 } 11945 11946 /** 11947 * Indicates the activation state of this view. 11948 * 11949 * @return true if the view is activated, false otherwise 11950 */ 11951 @ViewDebug.ExportedProperty 11952 public boolean isActivated() { 11953 return (mPrivateFlags & ACTIVATED) != 0; 11954 } 11955 11956 /** 11957 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 11958 * observer can be used to get notifications when global events, like 11959 * layout, happen. 11960 * 11961 * The returned ViewTreeObserver observer is not guaranteed to remain 11962 * valid for the lifetime of this View. If the caller of this method keeps 11963 * a long-lived reference to ViewTreeObserver, it should always check for 11964 * the return value of {@link ViewTreeObserver#isAlive()}. 11965 * 11966 * @return The ViewTreeObserver for this view's hierarchy. 11967 */ 11968 public ViewTreeObserver getViewTreeObserver() { 11969 if (mAttachInfo != null) { 11970 return mAttachInfo.mTreeObserver; 11971 } 11972 if (mFloatingTreeObserver == null) { 11973 mFloatingTreeObserver = new ViewTreeObserver(); 11974 } 11975 return mFloatingTreeObserver; 11976 } 11977 11978 /** 11979 * <p>Finds the topmost view in the current view hierarchy.</p> 11980 * 11981 * @return the topmost view containing this view 11982 */ 11983 public View getRootView() { 11984 if (mAttachInfo != null) { 11985 final View v = mAttachInfo.mRootView; 11986 if (v != null) { 11987 return v; 11988 } 11989 } 11990 11991 View parent = this; 11992 11993 while (parent.mParent != null && parent.mParent instanceof View) { 11994 parent = (View) parent.mParent; 11995 } 11996 11997 return parent; 11998 } 11999 12000 /** 12001 * <p>Computes the coordinates of this view on the screen. The argument 12002 * must be an array of two integers. After the method returns, the array 12003 * contains the x and y location in that order.</p> 12004 * 12005 * @param location an array of two integers in which to hold the coordinates 12006 */ 12007 public void getLocationOnScreen(int[] location) { 12008 getLocationInWindow(location); 12009 12010 final AttachInfo info = mAttachInfo; 12011 if (info != null) { 12012 location[0] += info.mWindowLeft; 12013 location[1] += info.mWindowTop; 12014 } 12015 } 12016 12017 /** 12018 * <p>Computes the coordinates of this view in its window. The argument 12019 * must be an array of two integers. After the method returns, the array 12020 * contains the x and y location in that order.</p> 12021 * 12022 * @param location an array of two integers in which to hold the coordinates 12023 */ 12024 public void getLocationInWindow(int[] location) { 12025 if (location == null || location.length < 2) { 12026 throw new IllegalArgumentException("location must be an array of " 12027 + "two integers"); 12028 } 12029 12030 location[0] = mLeft; 12031 location[1] = mTop; 12032 if (mTransformationInfo != null) { 12033 location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f); 12034 location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f); 12035 } 12036 12037 ViewParent viewParent = mParent; 12038 while (viewParent instanceof View) { 12039 final View view = (View)viewParent; 12040 location[0] += view.mLeft - view.mScrollX; 12041 location[1] += view.mTop - view.mScrollY; 12042 if (view.mTransformationInfo != null) { 12043 location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f); 12044 location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f); 12045 } 12046 viewParent = view.mParent; 12047 } 12048 12049 if (viewParent instanceof ViewRootImpl) { 12050 // *cough* 12051 final ViewRootImpl vr = (ViewRootImpl)viewParent; 12052 location[1] -= vr.mCurScrollY; 12053 } 12054 } 12055 12056 /** 12057 * {@hide} 12058 * @param id the id of the view to be found 12059 * @return the view of the specified id, null if cannot be found 12060 */ 12061 protected View findViewTraversal(int id) { 12062 if (id == mID) { 12063 return this; 12064 } 12065 return null; 12066 } 12067 12068 /** 12069 * {@hide} 12070 * @param tag the tag of the view to be found 12071 * @return the view of specified tag, null if cannot be found 12072 */ 12073 protected View findViewWithTagTraversal(Object tag) { 12074 if (tag != null && tag.equals(mTag)) { 12075 return this; 12076 } 12077 return null; 12078 } 12079 12080 /** 12081 * {@hide} 12082 * @param predicate The predicate to evaluate. 12083 * @param childToSkip If not null, ignores this child during the recursive traversal. 12084 * @return The first view that matches the predicate or null. 12085 */ 12086 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 12087 if (predicate.apply(this)) { 12088 return this; 12089 } 12090 return null; 12091 } 12092 12093 /** 12094 * Look for a child view with the given id. If this view has the given 12095 * id, return this view. 12096 * 12097 * @param id The id to search for. 12098 * @return The view that has the given id in the hierarchy or null 12099 */ 12100 public final View findViewById(int id) { 12101 if (id < 0) { 12102 return null; 12103 } 12104 return findViewTraversal(id); 12105 } 12106 12107 /** 12108 * Finds a view by its unuque and stable accessibility id. 12109 * 12110 * @param accessibilityId The searched accessibility id. 12111 * @return The found view. 12112 */ 12113 final View findViewByAccessibilityId(int accessibilityId) { 12114 if (accessibilityId < 0) { 12115 return null; 12116 } 12117 return findViewByAccessibilityIdTraversal(accessibilityId); 12118 } 12119 12120 /** 12121 * Performs the traversal to find a view by its unuque and stable accessibility id. 12122 * 12123 * <strong>Note:</strong>This method does not stop at the root namespace 12124 * boundary since the user can touch the screen at an arbitrary location 12125 * potentially crossing the root namespace bounday which will send an 12126 * accessibility event to accessibility services and they should be able 12127 * to obtain the event source. Also accessibility ids are guaranteed to be 12128 * unique in the window. 12129 * 12130 * @param accessibilityId The accessibility id. 12131 * @return The found view. 12132 */ 12133 View findViewByAccessibilityIdTraversal(int accessibilityId) { 12134 if (getAccessibilityViewId() == accessibilityId) { 12135 return this; 12136 } 12137 return null; 12138 } 12139 12140 /** 12141 * Look for a child view with the given tag. If this view has the given 12142 * tag, return this view. 12143 * 12144 * @param tag The tag to search for, using "tag.equals(getTag())". 12145 * @return The View that has the given tag in the hierarchy or null 12146 */ 12147 public final View findViewWithTag(Object tag) { 12148 if (tag == null) { 12149 return null; 12150 } 12151 return findViewWithTagTraversal(tag); 12152 } 12153 12154 /** 12155 * {@hide} 12156 * Look for a child view that matches the specified predicate. 12157 * If this view matches the predicate, return this view. 12158 * 12159 * @param predicate The predicate to evaluate. 12160 * @return The first view that matches the predicate or null. 12161 */ 12162 public final View findViewByPredicate(Predicate<View> predicate) { 12163 return findViewByPredicateTraversal(predicate, null); 12164 } 12165 12166 /** 12167 * {@hide} 12168 * Look for a child view that matches the specified predicate, 12169 * starting with the specified view and its descendents and then 12170 * recusively searching the ancestors and siblings of that view 12171 * until this view is reached. 12172 * 12173 * This method is useful in cases where the predicate does not match 12174 * a single unique view (perhaps multiple views use the same id) 12175 * and we are trying to find the view that is "closest" in scope to the 12176 * starting view. 12177 * 12178 * @param start The view to start from. 12179 * @param predicate The predicate to evaluate. 12180 * @return The first view that matches the predicate or null. 12181 */ 12182 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 12183 View childToSkip = null; 12184 for (;;) { 12185 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 12186 if (view != null || start == this) { 12187 return view; 12188 } 12189 12190 ViewParent parent = start.getParent(); 12191 if (parent == null || !(parent instanceof View)) { 12192 return null; 12193 } 12194 12195 childToSkip = start; 12196 start = (View) parent; 12197 } 12198 } 12199 12200 /** 12201 * Sets the identifier for this view. The identifier does not have to be 12202 * unique in this view's hierarchy. The identifier should be a positive 12203 * number. 12204 * 12205 * @see #NO_ID 12206 * @see #getId() 12207 * @see #findViewById(int) 12208 * 12209 * @param id a number used to identify the view 12210 * 12211 * @attr ref android.R.styleable#View_id 12212 */ 12213 public void setId(int id) { 12214 mID = id; 12215 } 12216 12217 /** 12218 * {@hide} 12219 * 12220 * @param isRoot true if the view belongs to the root namespace, false 12221 * otherwise 12222 */ 12223 public void setIsRootNamespace(boolean isRoot) { 12224 if (isRoot) { 12225 mPrivateFlags |= IS_ROOT_NAMESPACE; 12226 } else { 12227 mPrivateFlags &= ~IS_ROOT_NAMESPACE; 12228 } 12229 } 12230 12231 /** 12232 * {@hide} 12233 * 12234 * @return true if the view belongs to the root namespace, false otherwise 12235 */ 12236 public boolean isRootNamespace() { 12237 return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0; 12238 } 12239 12240 /** 12241 * Returns this view's identifier. 12242 * 12243 * @return a positive integer used to identify the view or {@link #NO_ID} 12244 * if the view has no ID 12245 * 12246 * @see #setId(int) 12247 * @see #findViewById(int) 12248 * @attr ref android.R.styleable#View_id 12249 */ 12250 @ViewDebug.CapturedViewProperty 12251 public int getId() { 12252 return mID; 12253 } 12254 12255 /** 12256 * Returns this view's tag. 12257 * 12258 * @return the Object stored in this view as a tag 12259 * 12260 * @see #setTag(Object) 12261 * @see #getTag(int) 12262 */ 12263 @ViewDebug.ExportedProperty 12264 public Object getTag() { 12265 return mTag; 12266 } 12267 12268 /** 12269 * Sets the tag associated with this view. A tag can be used to mark 12270 * a view in its hierarchy and does not have to be unique within the 12271 * hierarchy. Tags can also be used to store data within a view without 12272 * resorting to another data structure. 12273 * 12274 * @param tag an Object to tag the view with 12275 * 12276 * @see #getTag() 12277 * @see #setTag(int, Object) 12278 */ 12279 public void setTag(final Object tag) { 12280 mTag = tag; 12281 } 12282 12283 /** 12284 * Returns the tag associated with this view and the specified key. 12285 * 12286 * @param key The key identifying the tag 12287 * 12288 * @return the Object stored in this view as a tag 12289 * 12290 * @see #setTag(int, Object) 12291 * @see #getTag() 12292 */ 12293 public Object getTag(int key) { 12294 if (mKeyedTags != null) return mKeyedTags.get(key); 12295 return null; 12296 } 12297 12298 /** 12299 * Sets a tag associated with this view and a key. A tag can be used 12300 * to mark a view in its hierarchy and does not have to be unique within 12301 * the hierarchy. Tags can also be used to store data within a view 12302 * without resorting to another data structure. 12303 * 12304 * The specified key should be an id declared in the resources of the 12305 * application to ensure it is unique (see the <a 12306 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 12307 * Keys identified as belonging to 12308 * the Android framework or not associated with any package will cause 12309 * an {@link IllegalArgumentException} to be thrown. 12310 * 12311 * @param key The key identifying the tag 12312 * @param tag An Object to tag the view with 12313 * 12314 * @throws IllegalArgumentException If they specified key is not valid 12315 * 12316 * @see #setTag(Object) 12317 * @see #getTag(int) 12318 */ 12319 public void setTag(int key, final Object tag) { 12320 // If the package id is 0x00 or 0x01, it's either an undefined package 12321 // or a framework id 12322 if ((key >>> 24) < 2) { 12323 throw new IllegalArgumentException("The key must be an application-specific " 12324 + "resource id."); 12325 } 12326 12327 setKeyedTag(key, tag); 12328 } 12329 12330 /** 12331 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 12332 * framework id. 12333 * 12334 * @hide 12335 */ 12336 public void setTagInternal(int key, Object tag) { 12337 if ((key >>> 24) != 0x1) { 12338 throw new IllegalArgumentException("The key must be a framework-specific " 12339 + "resource id."); 12340 } 12341 12342 setKeyedTag(key, tag); 12343 } 12344 12345 private void setKeyedTag(int key, Object tag) { 12346 if (mKeyedTags == null) { 12347 mKeyedTags = new SparseArray<Object>(); 12348 } 12349 12350 mKeyedTags.put(key, tag); 12351 } 12352 12353 /** 12354 * @param consistency The type of consistency. See ViewDebug for more information. 12355 * 12356 * @hide 12357 */ 12358 protected boolean dispatchConsistencyCheck(int consistency) { 12359 return onConsistencyCheck(consistency); 12360 } 12361 12362 /** 12363 * Method that subclasses should implement to check their consistency. The type of 12364 * consistency check is indicated by the bit field passed as a parameter. 12365 * 12366 * @param consistency The type of consistency. See ViewDebug for more information. 12367 * 12368 * @throws IllegalStateException if the view is in an inconsistent state. 12369 * 12370 * @hide 12371 */ 12372 protected boolean onConsistencyCheck(int consistency) { 12373 boolean result = true; 12374 12375 final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0; 12376 final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0; 12377 12378 if (checkLayout) { 12379 if (getParent() == null) { 12380 result = false; 12381 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, 12382 "View " + this + " does not have a parent."); 12383 } 12384 12385 if (mAttachInfo == null) { 12386 result = false; 12387 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, 12388 "View " + this + " is not attached to a window."); 12389 } 12390 } 12391 12392 if (checkDrawing) { 12393 // Do not check the DIRTY/DRAWN flags because views can call invalidate() 12394 // from their draw() method 12395 12396 if ((mPrivateFlags & DRAWN) != DRAWN && 12397 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) { 12398 result = false; 12399 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG, 12400 "View " + this + " was invalidated but its drawing cache is valid."); 12401 } 12402 } 12403 12404 return result; 12405 } 12406 12407 /** 12408 * Prints information about this view in the log output, with the tag 12409 * {@link #VIEW_LOG_TAG}. 12410 * 12411 * @hide 12412 */ 12413 public void debug() { 12414 debug(0); 12415 } 12416 12417 /** 12418 * Prints information about this view in the log output, with the tag 12419 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 12420 * indentation defined by the <code>depth</code>. 12421 * 12422 * @param depth the indentation level 12423 * 12424 * @hide 12425 */ 12426 protected void debug(int depth) { 12427 String output = debugIndent(depth - 1); 12428 12429 output += "+ " + this; 12430 int id = getId(); 12431 if (id != -1) { 12432 output += " (id=" + id + ")"; 12433 } 12434 Object tag = getTag(); 12435 if (tag != null) { 12436 output += " (tag=" + tag + ")"; 12437 } 12438 Log.d(VIEW_LOG_TAG, output); 12439 12440 if ((mPrivateFlags & FOCUSED) != 0) { 12441 output = debugIndent(depth) + " FOCUSED"; 12442 Log.d(VIEW_LOG_TAG, output); 12443 } 12444 12445 output = debugIndent(depth); 12446 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 12447 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 12448 + "} "; 12449 Log.d(VIEW_LOG_TAG, output); 12450 12451 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 12452 || mPaddingBottom != 0) { 12453 output = debugIndent(depth); 12454 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 12455 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 12456 Log.d(VIEW_LOG_TAG, output); 12457 } 12458 12459 output = debugIndent(depth); 12460 output += "mMeasureWidth=" + mMeasuredWidth + 12461 " mMeasureHeight=" + mMeasuredHeight; 12462 Log.d(VIEW_LOG_TAG, output); 12463 12464 output = debugIndent(depth); 12465 if (mLayoutParams == null) { 12466 output += "BAD! no layout params"; 12467 } else { 12468 output = mLayoutParams.debug(output); 12469 } 12470 Log.d(VIEW_LOG_TAG, output); 12471 12472 output = debugIndent(depth); 12473 output += "flags={"; 12474 output += View.printFlags(mViewFlags); 12475 output += "}"; 12476 Log.d(VIEW_LOG_TAG, output); 12477 12478 output = debugIndent(depth); 12479 output += "privateFlags={"; 12480 output += View.printPrivateFlags(mPrivateFlags); 12481 output += "}"; 12482 Log.d(VIEW_LOG_TAG, output); 12483 } 12484 12485 /** 12486 * Creates an string of whitespaces used for indentation. 12487 * 12488 * @param depth the indentation level 12489 * @return a String containing (depth * 2 + 3) * 2 white spaces 12490 * 12491 * @hide 12492 */ 12493 protected static String debugIndent(int depth) { 12494 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 12495 for (int i = 0; i < (depth * 2) + 3; i++) { 12496 spaces.append(' ').append(' '); 12497 } 12498 return spaces.toString(); 12499 } 12500 12501 /** 12502 * <p>Return the offset of the widget's text baseline from the widget's top 12503 * boundary. If this widget does not support baseline alignment, this 12504 * method returns -1. </p> 12505 * 12506 * @return the offset of the baseline within the widget's bounds or -1 12507 * if baseline alignment is not supported 12508 */ 12509 @ViewDebug.ExportedProperty(category = "layout") 12510 public int getBaseline() { 12511 return -1; 12512 } 12513 12514 /** 12515 * Call this when something has changed which has invalidated the 12516 * layout of this view. This will schedule a layout pass of the view 12517 * tree. 12518 */ 12519 public void requestLayout() { 12520 if (ViewDebug.TRACE_HIERARCHY) { 12521 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT); 12522 } 12523 12524 mPrivateFlags |= FORCE_LAYOUT; 12525 mPrivateFlags |= INVALIDATED; 12526 12527 if (mParent != null) { 12528 if (mLayoutParams != null) { 12529 mLayoutParams.resolveWithDirection(getResolvedLayoutDirection()); 12530 } 12531 if (!mParent.isLayoutRequested()) { 12532 mParent.requestLayout(); 12533 } 12534 } 12535 } 12536 12537 /** 12538 * Forces this view to be laid out during the next layout pass. 12539 * This method does not call requestLayout() or forceLayout() 12540 * on the parent. 12541 */ 12542 public void forceLayout() { 12543 mPrivateFlags |= FORCE_LAYOUT; 12544 mPrivateFlags |= INVALIDATED; 12545 } 12546 12547 /** 12548 * <p> 12549 * This is called to find out how big a view should be. The parent 12550 * supplies constraint information in the width and height parameters. 12551 * </p> 12552 * 12553 * <p> 12554 * The actual mesurement work of a view is performed in 12555 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 12556 * {@link #onMeasure(int, int)} can and must be overriden by subclasses. 12557 * </p> 12558 * 12559 * 12560 * @param widthMeasureSpec Horizontal space requirements as imposed by the 12561 * parent 12562 * @param heightMeasureSpec Vertical space requirements as imposed by the 12563 * parent 12564 * 12565 * @see #onMeasure(int, int) 12566 */ 12567 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 12568 if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || 12569 widthMeasureSpec != mOldWidthMeasureSpec || 12570 heightMeasureSpec != mOldHeightMeasureSpec) { 12571 12572 // first clears the measured dimension flag 12573 mPrivateFlags &= ~MEASURED_DIMENSION_SET; 12574 12575 if (ViewDebug.TRACE_HIERARCHY) { 12576 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE); 12577 } 12578 12579 // measure ourselves, this should set the measured dimension flag back 12580 onMeasure(widthMeasureSpec, heightMeasureSpec); 12581 12582 // flag not set, setMeasuredDimension() was not invoked, we raise 12583 // an exception to warn the developer 12584 if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) { 12585 throw new IllegalStateException("onMeasure() did not set the" 12586 + " measured dimension by calling" 12587 + " setMeasuredDimension()"); 12588 } 12589 12590 mPrivateFlags |= LAYOUT_REQUIRED; 12591 } 12592 12593 mOldWidthMeasureSpec = widthMeasureSpec; 12594 mOldHeightMeasureSpec = heightMeasureSpec; 12595 } 12596 12597 /** 12598 * <p> 12599 * Measure the view and its content to determine the measured width and the 12600 * measured height. This method is invoked by {@link #measure(int, int)} and 12601 * should be overriden by subclasses to provide accurate and efficient 12602 * measurement of their contents. 12603 * </p> 12604 * 12605 * <p> 12606 * <strong>CONTRACT:</strong> When overriding this method, you 12607 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 12608 * measured width and height of this view. Failure to do so will trigger an 12609 * <code>IllegalStateException</code>, thrown by 12610 * {@link #measure(int, int)}. Calling the superclass' 12611 * {@link #onMeasure(int, int)} is a valid use. 12612 * </p> 12613 * 12614 * <p> 12615 * The base class implementation of measure defaults to the background size, 12616 * unless a larger size is allowed by the MeasureSpec. Subclasses should 12617 * override {@link #onMeasure(int, int)} to provide better measurements of 12618 * their content. 12619 * </p> 12620 * 12621 * <p> 12622 * If this method is overridden, it is the subclass's responsibility to make 12623 * sure the measured height and width are at least the view's minimum height 12624 * and width ({@link #getSuggestedMinimumHeight()} and 12625 * {@link #getSuggestedMinimumWidth()}). 12626 * </p> 12627 * 12628 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 12629 * The requirements are encoded with 12630 * {@link android.view.View.MeasureSpec}. 12631 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 12632 * The requirements are encoded with 12633 * {@link android.view.View.MeasureSpec}. 12634 * 12635 * @see #getMeasuredWidth() 12636 * @see #getMeasuredHeight() 12637 * @see #setMeasuredDimension(int, int) 12638 * @see #getSuggestedMinimumHeight() 12639 * @see #getSuggestedMinimumWidth() 12640 * @see android.view.View.MeasureSpec#getMode(int) 12641 * @see android.view.View.MeasureSpec#getSize(int) 12642 */ 12643 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 12644 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 12645 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 12646 } 12647 12648 /** 12649 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the 12650 * measured width and measured height. Failing to do so will trigger an 12651 * exception at measurement time.</p> 12652 * 12653 * @param measuredWidth The measured width of this view. May be a complex 12654 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 12655 * {@link #MEASURED_STATE_TOO_SMALL}. 12656 * @param measuredHeight The measured height of this view. May be a complex 12657 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 12658 * {@link #MEASURED_STATE_TOO_SMALL}. 12659 */ 12660 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 12661 mMeasuredWidth = measuredWidth; 12662 mMeasuredHeight = measuredHeight; 12663 12664 mPrivateFlags |= MEASURED_DIMENSION_SET; 12665 } 12666 12667 /** 12668 * Merge two states as returned by {@link #getMeasuredState()}. 12669 * @param curState The current state as returned from a view or the result 12670 * of combining multiple views. 12671 * @param newState The new view state to combine. 12672 * @return Returns a new integer reflecting the combination of the two 12673 * states. 12674 */ 12675 public static int combineMeasuredStates(int curState, int newState) { 12676 return curState | newState; 12677 } 12678 12679 /** 12680 * Version of {@link #resolveSizeAndState(int, int, int)} 12681 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 12682 */ 12683 public static int resolveSize(int size, int measureSpec) { 12684 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 12685 } 12686 12687 /** 12688 * Utility to reconcile a desired size and state, with constraints imposed 12689 * by a MeasureSpec. Will take the desired size, unless a different size 12690 * is imposed by the constraints. The returned value is a compound integer, 12691 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 12692 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting 12693 * size is smaller than the size the view wants to be. 12694 * 12695 * @param size How big the view wants to be 12696 * @param measureSpec Constraints imposed by the parent 12697 * @return Size information bit mask as defined by 12698 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 12699 */ 12700 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 12701 int result = size; 12702 int specMode = MeasureSpec.getMode(measureSpec); 12703 int specSize = MeasureSpec.getSize(measureSpec); 12704 switch (specMode) { 12705 case MeasureSpec.UNSPECIFIED: 12706 result = size; 12707 break; 12708 case MeasureSpec.AT_MOST: 12709 if (specSize < size) { 12710 result = specSize | MEASURED_STATE_TOO_SMALL; 12711 } else { 12712 result = size; 12713 } 12714 break; 12715 case MeasureSpec.EXACTLY: 12716 result = specSize; 12717 break; 12718 } 12719 return result | (childMeasuredState&MEASURED_STATE_MASK); 12720 } 12721 12722 /** 12723 * Utility to return a default size. Uses the supplied size if the 12724 * MeasureSpec imposed no constraints. Will get larger if allowed 12725 * by the MeasureSpec. 12726 * 12727 * @param size Default size for this view 12728 * @param measureSpec Constraints imposed by the parent 12729 * @return The size this view should be. 12730 */ 12731 public static int getDefaultSize(int size, int measureSpec) { 12732 int result = size; 12733 int specMode = MeasureSpec.getMode(measureSpec); 12734 int specSize = MeasureSpec.getSize(measureSpec); 12735 12736 switch (specMode) { 12737 case MeasureSpec.UNSPECIFIED: 12738 result = size; 12739 break; 12740 case MeasureSpec.AT_MOST: 12741 case MeasureSpec.EXACTLY: 12742 result = specSize; 12743 break; 12744 } 12745 return result; 12746 } 12747 12748 /** 12749 * Returns the suggested minimum height that the view should use. This 12750 * returns the maximum of the view's minimum height 12751 * and the background's minimum height 12752 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 12753 * <p> 12754 * When being used in {@link #onMeasure(int, int)}, the caller should still 12755 * ensure the returned height is within the requirements of the parent. 12756 * 12757 * @return The suggested minimum height of the view. 12758 */ 12759 protected int getSuggestedMinimumHeight() { 12760 int suggestedMinHeight = mMinHeight; 12761 12762 if (mBGDrawable != null) { 12763 final int bgMinHeight = mBGDrawable.getMinimumHeight(); 12764 if (suggestedMinHeight < bgMinHeight) { 12765 suggestedMinHeight = bgMinHeight; 12766 } 12767 } 12768 12769 return suggestedMinHeight; 12770 } 12771 12772 /** 12773 * Returns the suggested minimum width that the view should use. This 12774 * returns the maximum of the view's minimum width) 12775 * and the background's minimum width 12776 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 12777 * <p> 12778 * When being used in {@link #onMeasure(int, int)}, the caller should still 12779 * ensure the returned width is within the requirements of the parent. 12780 * 12781 * @return The suggested minimum width of the view. 12782 */ 12783 protected int getSuggestedMinimumWidth() { 12784 int suggestedMinWidth = mMinWidth; 12785 12786 if (mBGDrawable != null) { 12787 final int bgMinWidth = mBGDrawable.getMinimumWidth(); 12788 if (suggestedMinWidth < bgMinWidth) { 12789 suggestedMinWidth = bgMinWidth; 12790 } 12791 } 12792 12793 return suggestedMinWidth; 12794 } 12795 12796 /** 12797 * Sets the minimum height of the view. It is not guaranteed the view will 12798 * be able to achieve this minimum height (for example, if its parent layout 12799 * constrains it with less available height). 12800 * 12801 * @param minHeight The minimum height the view will try to be. 12802 */ 12803 public void setMinimumHeight(int minHeight) { 12804 mMinHeight = minHeight; 12805 } 12806 12807 /** 12808 * Sets the minimum width of the view. It is not guaranteed the view will 12809 * be able to achieve this minimum width (for example, if its parent layout 12810 * constrains it with less available width). 12811 * 12812 * @param minWidth The minimum width the view will try to be. 12813 */ 12814 public void setMinimumWidth(int minWidth) { 12815 mMinWidth = minWidth; 12816 } 12817 12818 /** 12819 * Get the animation currently associated with this view. 12820 * 12821 * @return The animation that is currently playing or 12822 * scheduled to play for this view. 12823 */ 12824 public Animation getAnimation() { 12825 return mCurrentAnimation; 12826 } 12827 12828 /** 12829 * Start the specified animation now. 12830 * 12831 * @param animation the animation to start now 12832 */ 12833 public void startAnimation(Animation animation) { 12834 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 12835 setAnimation(animation); 12836 invalidateParentCaches(); 12837 invalidate(true); 12838 } 12839 12840 /** 12841 * Cancels any animations for this view. 12842 */ 12843 public void clearAnimation() { 12844 if (mCurrentAnimation != null) { 12845 mCurrentAnimation.detach(); 12846 } 12847 mCurrentAnimation = null; 12848 invalidateParentIfNeeded(); 12849 } 12850 12851 /** 12852 * Sets the next animation to play for this view. 12853 * If you want the animation to play immediately, use 12854 * startAnimation. This method provides allows fine-grained 12855 * control over the start time and invalidation, but you 12856 * must make sure that 1) the animation has a start time set, and 12857 * 2) the view will be invalidated when the animation is supposed to 12858 * start. 12859 * 12860 * @param animation The next animation, or null. 12861 */ 12862 public void setAnimation(Animation animation) { 12863 mCurrentAnimation = animation; 12864 if (animation != null) { 12865 animation.reset(); 12866 } 12867 } 12868 12869 /** 12870 * Invoked by a parent ViewGroup to notify the start of the animation 12871 * currently associated with this view. If you override this method, 12872 * always call super.onAnimationStart(); 12873 * 12874 * @see #setAnimation(android.view.animation.Animation) 12875 * @see #getAnimation() 12876 */ 12877 protected void onAnimationStart() { 12878 mPrivateFlags |= ANIMATION_STARTED; 12879 } 12880 12881 /** 12882 * Invoked by a parent ViewGroup to notify the end of the animation 12883 * currently associated with this view. If you override this method, 12884 * always call super.onAnimationEnd(); 12885 * 12886 * @see #setAnimation(android.view.animation.Animation) 12887 * @see #getAnimation() 12888 */ 12889 protected void onAnimationEnd() { 12890 mPrivateFlags &= ~ANIMATION_STARTED; 12891 } 12892 12893 /** 12894 * Invoked if there is a Transform that involves alpha. Subclass that can 12895 * draw themselves with the specified alpha should return true, and then 12896 * respect that alpha when their onDraw() is called. If this returns false 12897 * then the view may be redirected to draw into an offscreen buffer to 12898 * fulfill the request, which will look fine, but may be slower than if the 12899 * subclass handles it internally. The default implementation returns false. 12900 * 12901 * @param alpha The alpha (0..255) to apply to the view's drawing 12902 * @return true if the view can draw with the specified alpha. 12903 */ 12904 protected boolean onSetAlpha(int alpha) { 12905 return false; 12906 } 12907 12908 /** 12909 * This is used by the RootView to perform an optimization when 12910 * the view hierarchy contains one or several SurfaceView. 12911 * SurfaceView is always considered transparent, but its children are not, 12912 * therefore all View objects remove themselves from the global transparent 12913 * region (passed as a parameter to this function). 12914 * 12915 * @param region The transparent region for this ViewAncestor (window). 12916 * 12917 * @return Returns true if the effective visibility of the view at this 12918 * point is opaque, regardless of the transparent region; returns false 12919 * if it is possible for underlying windows to be seen behind the view. 12920 * 12921 * {@hide} 12922 */ 12923 public boolean gatherTransparentRegion(Region region) { 12924 final AttachInfo attachInfo = mAttachInfo; 12925 if (region != null && attachInfo != null) { 12926 final int pflags = mPrivateFlags; 12927 if ((pflags & SKIP_DRAW) == 0) { 12928 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 12929 // remove it from the transparent region. 12930 final int[] location = attachInfo.mTransparentLocation; 12931 getLocationInWindow(location); 12932 region.op(location[0], location[1], location[0] + mRight - mLeft, 12933 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 12934 } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) { 12935 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable 12936 // exists, so we remove the background drawable's non-transparent 12937 // parts from this transparent region. 12938 applyDrawableToTransparentRegion(mBGDrawable, region); 12939 } 12940 } 12941 return true; 12942 } 12943 12944 /** 12945 * Play a sound effect for this view. 12946 * 12947 * <p>The framework will play sound effects for some built in actions, such as 12948 * clicking, but you may wish to play these effects in your widget, 12949 * for instance, for internal navigation. 12950 * 12951 * <p>The sound effect will only be played if sound effects are enabled by the user, and 12952 * {@link #isSoundEffectsEnabled()} is true. 12953 * 12954 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 12955 */ 12956 public void playSoundEffect(int soundConstant) { 12957 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 12958 return; 12959 } 12960 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 12961 } 12962 12963 /** 12964 * BZZZTT!!1! 12965 * 12966 * <p>Provide haptic feedback to the user for this view. 12967 * 12968 * <p>The framework will provide haptic feedback for some built in actions, 12969 * such as long presses, but you may wish to provide feedback for your 12970 * own widget. 12971 * 12972 * <p>The feedback will only be performed if 12973 * {@link #isHapticFeedbackEnabled()} is true. 12974 * 12975 * @param feedbackConstant One of the constants defined in 12976 * {@link HapticFeedbackConstants} 12977 */ 12978 public boolean performHapticFeedback(int feedbackConstant) { 12979 return performHapticFeedback(feedbackConstant, 0); 12980 } 12981 12982 /** 12983 * BZZZTT!!1! 12984 * 12985 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 12986 * 12987 * @param feedbackConstant One of the constants defined in 12988 * {@link HapticFeedbackConstants} 12989 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 12990 */ 12991 public boolean performHapticFeedback(int feedbackConstant, int flags) { 12992 if (mAttachInfo == null) { 12993 return false; 12994 } 12995 //noinspection SimplifiableIfStatement 12996 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 12997 && !isHapticFeedbackEnabled()) { 12998 return false; 12999 } 13000 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 13001 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 13002 } 13003 13004 /** 13005 * Request that the visibility of the status bar be changed. 13006 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or 13007 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. 13008 */ 13009 public void setSystemUiVisibility(int visibility) { 13010 if (visibility != mSystemUiVisibility) { 13011 mSystemUiVisibility = visibility; 13012 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 13013 mParent.recomputeViewAttributes(this); 13014 } 13015 } 13016 } 13017 13018 /** 13019 * Returns the status bar visibility that this view has requested. 13020 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or 13021 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. 13022 */ 13023 public int getSystemUiVisibility() { 13024 return mSystemUiVisibility; 13025 } 13026 13027 /** 13028 * Set a listener to receive callbacks when the visibility of the system bar changes. 13029 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 13030 */ 13031 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 13032 mOnSystemUiVisibilityChangeListener = l; 13033 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 13034 mParent.recomputeViewAttributes(this); 13035 } 13036 } 13037 13038 /** 13039 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 13040 * the view hierarchy. 13041 */ 13042 public void dispatchSystemUiVisibilityChanged(int visibility) { 13043 if (mOnSystemUiVisibilityChangeListener != null) { 13044 mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 13045 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 13046 } 13047 } 13048 13049 void updateLocalSystemUiVisibility(int localValue, int localChanges) { 13050 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 13051 if (val != mSystemUiVisibility) { 13052 setSystemUiVisibility(val); 13053 } 13054 } 13055 13056 /** 13057 * Creates an image that the system displays during the drag and drop 13058 * operation. This is called a "drag shadow". The default implementation 13059 * for a DragShadowBuilder based on a View returns an image that has exactly the same 13060 * appearance as the given View. The default also positions the center of the drag shadow 13061 * directly under the touch point. If no View is provided (the constructor with no parameters 13062 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 13063 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the 13064 * default is an invisible drag shadow. 13065 * <p> 13066 * You are not required to use the View you provide to the constructor as the basis of the 13067 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 13068 * anything you want as the drag shadow. 13069 * </p> 13070 * <p> 13071 * You pass a DragShadowBuilder object to the system when you start the drag. The system 13072 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 13073 * size and position of the drag shadow. It uses this data to construct a 13074 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 13075 * so that your application can draw the shadow image in the Canvas. 13076 * </p> 13077 */ 13078 public static class DragShadowBuilder { 13079 private final WeakReference<View> mView; 13080 13081 /** 13082 * Constructs a shadow image builder based on a View. By default, the resulting drag 13083 * shadow will have the same appearance and dimensions as the View, with the touch point 13084 * over the center of the View. 13085 * @param view A View. Any View in scope can be used. 13086 */ 13087 public DragShadowBuilder(View view) { 13088 mView = new WeakReference<View>(view); 13089 } 13090 13091 /** 13092 * Construct a shadow builder object with no associated View. This 13093 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 13094 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 13095 * to supply the drag shadow's dimensions and appearance without 13096 * reference to any View object. If they are not overridden, then the result is an 13097 * invisible drag shadow. 13098 */ 13099 public DragShadowBuilder() { 13100 mView = new WeakReference<View>(null); 13101 } 13102 13103 /** 13104 * Returns the View object that had been passed to the 13105 * {@link #View.DragShadowBuilder(View)} 13106 * constructor. If that View parameter was {@code null} or if the 13107 * {@link #View.DragShadowBuilder()} 13108 * constructor was used to instantiate the builder object, this method will return 13109 * null. 13110 * 13111 * @return The View object associate with this builder object. 13112 */ 13113 @SuppressWarnings({"JavadocReference"}) 13114 final public View getView() { 13115 return mView.get(); 13116 } 13117 13118 /** 13119 * Provides the metrics for the shadow image. These include the dimensions of 13120 * the shadow image, and the point within that shadow that should 13121 * be centered under the touch location while dragging. 13122 * <p> 13123 * The default implementation sets the dimensions of the shadow to be the 13124 * same as the dimensions of the View itself and centers the shadow under 13125 * the touch point. 13126 * </p> 13127 * 13128 * @param shadowSize A {@link android.graphics.Point} containing the width and height 13129 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 13130 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 13131 * image. 13132 * 13133 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the 13134 * shadow image that should be underneath the touch point during the drag and drop 13135 * operation. Your application must set {@link android.graphics.Point#x} to the 13136 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 13137 */ 13138 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 13139 final View view = mView.get(); 13140 if (view != null) { 13141 shadowSize.set(view.getWidth(), view.getHeight()); 13142 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 13143 } else { 13144 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 13145 } 13146 } 13147 13148 /** 13149 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 13150 * based on the dimensions it received from the 13151 * {@link #onProvideShadowMetrics(Point, Point)} callback. 13152 * 13153 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 13154 */ 13155 public void onDrawShadow(Canvas canvas) { 13156 final View view = mView.get(); 13157 if (view != null) { 13158 view.draw(canvas); 13159 } else { 13160 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 13161 } 13162 } 13163 } 13164 13165 /** 13166 * Starts a drag and drop operation. When your application calls this method, it passes a 13167 * {@link android.view.View.DragShadowBuilder} object to the system. The 13168 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 13169 * to get metrics for the drag shadow, and then calls the object's 13170 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 13171 * <p> 13172 * Once the system has the drag shadow, it begins the drag and drop operation by sending 13173 * drag events to all the View objects in your application that are currently visible. It does 13174 * this either by calling the View object's drag listener (an implementation of 13175 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 13176 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 13177 * Both are passed a {@link android.view.DragEvent} object that has a 13178 * {@link android.view.DragEvent#getAction()} value of 13179 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 13180 * </p> 13181 * <p> 13182 * Your application can invoke startDrag() on any attached View object. The View object does not 13183 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to 13184 * be related to the View the user selected for dragging. 13185 * </p> 13186 * @param data A {@link android.content.ClipData} object pointing to the data to be 13187 * transferred by the drag and drop operation. 13188 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 13189 * drag shadow. 13190 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 13191 * drop operation. This Object is put into every DragEvent object sent by the system during the 13192 * current drag. 13193 * <p> 13194 * myLocalState is a lightweight mechanism for the sending information from the dragged View 13195 * to the target Views. For example, it can contain flags that differentiate between a 13196 * a copy operation and a move operation. 13197 * </p> 13198 * @param flags Flags that control the drag and drop operation. No flags are currently defined, 13199 * so the parameter should be set to 0. 13200 * @return {@code true} if the method completes successfully, or 13201 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 13202 * do a drag, and so no drag operation is in progress. 13203 */ 13204 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 13205 Object myLocalState, int flags) { 13206 if (ViewDebug.DEBUG_DRAG) { 13207 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags); 13208 } 13209 boolean okay = false; 13210 13211 Point shadowSize = new Point(); 13212 Point shadowTouchPoint = new Point(); 13213 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 13214 13215 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 13216 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 13217 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 13218 } 13219 13220 if (ViewDebug.DEBUG_DRAG) { 13221 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 13222 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 13223 } 13224 Surface surface = new Surface(); 13225 try { 13226 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 13227 flags, shadowSize.x, shadowSize.y, surface); 13228 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token 13229 + " surface=" + surface); 13230 if (token != null) { 13231 Canvas canvas = surface.lockCanvas(null); 13232 try { 13233 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 13234 shadowBuilder.onDrawShadow(canvas); 13235 } finally { 13236 surface.unlockCanvasAndPost(canvas); 13237 } 13238 13239 final ViewRootImpl root = getViewRootImpl(); 13240 13241 // Cache the local state object for delivery with DragEvents 13242 root.setLocalDragState(myLocalState); 13243 13244 // repurpose 'shadowSize' for the last touch point 13245 root.getLastTouchPoint(shadowSize); 13246 13247 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token, 13248 shadowSize.x, shadowSize.y, 13249 shadowTouchPoint.x, shadowTouchPoint.y, data); 13250 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 13251 13252 // Off and running! Release our local surface instance; the drag 13253 // shadow surface is now managed by the system process. 13254 surface.release(); 13255 } 13256 } catch (Exception e) { 13257 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 13258 surface.destroy(); 13259 } 13260 13261 return okay; 13262 } 13263 13264 /** 13265 * Handles drag events sent by the system following a call to 13266 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}. 13267 *<p> 13268 * When the system calls this method, it passes a 13269 * {@link android.view.DragEvent} object. A call to 13270 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 13271 * in DragEvent. The method uses these to determine what is happening in the drag and drop 13272 * operation. 13273 * @param event The {@link android.view.DragEvent} sent by the system. 13274 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 13275 * in DragEvent, indicating the type of drag event represented by this object. 13276 * @return {@code true} if the method was successful, otherwise {@code false}. 13277 * <p> 13278 * The method should return {@code true} in response to an action type of 13279 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 13280 * operation. 13281 * </p> 13282 * <p> 13283 * The method should also return {@code true} in response to an action type of 13284 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 13285 * {@code false} if it didn't. 13286 * </p> 13287 */ 13288 public boolean onDragEvent(DragEvent event) { 13289 return false; 13290 } 13291 13292 /** 13293 * Detects if this View is enabled and has a drag event listener. 13294 * If both are true, then it calls the drag event listener with the 13295 * {@link android.view.DragEvent} it received. If the drag event listener returns 13296 * {@code true}, then dispatchDragEvent() returns {@code true}. 13297 * <p> 13298 * For all other cases, the method calls the 13299 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 13300 * method and returns its result. 13301 * </p> 13302 * <p> 13303 * This ensures that a drag event is always consumed, even if the View does not have a drag 13304 * event listener. However, if the View has a listener and the listener returns true, then 13305 * onDragEvent() is not called. 13306 * </p> 13307 */ 13308 public boolean dispatchDragEvent(DragEvent event) { 13309 //noinspection SimplifiableIfStatement 13310 if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 13311 && mOnDragListener.onDrag(this, event)) { 13312 return true; 13313 } 13314 return onDragEvent(event); 13315 } 13316 13317 boolean canAcceptDrag() { 13318 return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0; 13319 } 13320 13321 /** 13322 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 13323 * it is ever exposed at all. 13324 * @hide 13325 */ 13326 public void onCloseSystemDialogs(String reason) { 13327 } 13328 13329 /** 13330 * Given a Drawable whose bounds have been set to draw into this view, 13331 * update a Region being computed for 13332 * {@link #gatherTransparentRegion(android.graphics.Region)} so 13333 * that any non-transparent parts of the Drawable are removed from the 13334 * given transparent region. 13335 * 13336 * @param dr The Drawable whose transparency is to be applied to the region. 13337 * @param region A Region holding the current transparency information, 13338 * where any parts of the region that are set are considered to be 13339 * transparent. On return, this region will be modified to have the 13340 * transparency information reduced by the corresponding parts of the 13341 * Drawable that are not transparent. 13342 * {@hide} 13343 */ 13344 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 13345 if (DBG) { 13346 Log.i("View", "Getting transparent region for: " + this); 13347 } 13348 final Region r = dr.getTransparentRegion(); 13349 final Rect db = dr.getBounds(); 13350 final AttachInfo attachInfo = mAttachInfo; 13351 if (r != null && attachInfo != null) { 13352 final int w = getRight()-getLeft(); 13353 final int h = getBottom()-getTop(); 13354 if (db.left > 0) { 13355 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 13356 r.op(0, 0, db.left, h, Region.Op.UNION); 13357 } 13358 if (db.right < w) { 13359 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 13360 r.op(db.right, 0, w, h, Region.Op.UNION); 13361 } 13362 if (db.top > 0) { 13363 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 13364 r.op(0, 0, w, db.top, Region.Op.UNION); 13365 } 13366 if (db.bottom < h) { 13367 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 13368 r.op(0, db.bottom, w, h, Region.Op.UNION); 13369 } 13370 final int[] location = attachInfo.mTransparentLocation; 13371 getLocationInWindow(location); 13372 r.translate(location[0], location[1]); 13373 region.op(r, Region.Op.INTERSECT); 13374 } else { 13375 region.op(db, Region.Op.DIFFERENCE); 13376 } 13377 } 13378 13379 private void checkForLongClick(int delayOffset) { 13380 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 13381 mHasPerformedLongPress = false; 13382 13383 if (mPendingCheckForLongPress == null) { 13384 mPendingCheckForLongPress = new CheckForLongPress(); 13385 } 13386 mPendingCheckForLongPress.rememberWindowAttachCount(); 13387 postDelayed(mPendingCheckForLongPress, 13388 ViewConfiguration.getLongPressTimeout() - delayOffset); 13389 } 13390 } 13391 13392 /** 13393 * Inflate a view from an XML resource. This convenience method wraps the {@link 13394 * LayoutInflater} class, which provides a full range of options for view inflation. 13395 * 13396 * @param context The Context object for your activity or application. 13397 * @param resource The resource ID to inflate 13398 * @param root A view group that will be the parent. Used to properly inflate the 13399 * layout_* parameters. 13400 * @see LayoutInflater 13401 */ 13402 public static View inflate(Context context, int resource, ViewGroup root) { 13403 LayoutInflater factory = LayoutInflater.from(context); 13404 return factory.inflate(resource, root); 13405 } 13406 13407 /** 13408 * Scroll the view with standard behavior for scrolling beyond the normal 13409 * content boundaries. Views that call this method should override 13410 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 13411 * results of an over-scroll operation. 13412 * 13413 * Views can use this method to handle any touch or fling-based scrolling. 13414 * 13415 * @param deltaX Change in X in pixels 13416 * @param deltaY Change in Y in pixels 13417 * @param scrollX Current X scroll value in pixels before applying deltaX 13418 * @param scrollY Current Y scroll value in pixels before applying deltaY 13419 * @param scrollRangeX Maximum content scroll range along the X axis 13420 * @param scrollRangeY Maximum content scroll range along the Y axis 13421 * @param maxOverScrollX Number of pixels to overscroll by in either direction 13422 * along the X axis. 13423 * @param maxOverScrollY Number of pixels to overscroll by in either direction 13424 * along the Y axis. 13425 * @param isTouchEvent true if this scroll operation is the result of a touch event. 13426 * @return true if scrolling was clamped to an over-scroll boundary along either 13427 * axis, false otherwise. 13428 */ 13429 @SuppressWarnings({"UnusedParameters"}) 13430 protected boolean overScrollBy(int deltaX, int deltaY, 13431 int scrollX, int scrollY, 13432 int scrollRangeX, int scrollRangeY, 13433 int maxOverScrollX, int maxOverScrollY, 13434 boolean isTouchEvent) { 13435 final int overScrollMode = mOverScrollMode; 13436 final boolean canScrollHorizontal = 13437 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 13438 final boolean canScrollVertical = 13439 computeVerticalScrollRange() > computeVerticalScrollExtent(); 13440 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 13441 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 13442 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 13443 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 13444 13445 int newScrollX = scrollX + deltaX; 13446 if (!overScrollHorizontal) { 13447 maxOverScrollX = 0; 13448 } 13449 13450 int newScrollY = scrollY + deltaY; 13451 if (!overScrollVertical) { 13452 maxOverScrollY = 0; 13453 } 13454 13455 // Clamp values if at the limits and record 13456 final int left = -maxOverScrollX; 13457 final int right = maxOverScrollX + scrollRangeX; 13458 final int top = -maxOverScrollY; 13459 final int bottom = maxOverScrollY + scrollRangeY; 13460 13461 boolean clampedX = false; 13462 if (newScrollX > right) { 13463 newScrollX = right; 13464 clampedX = true; 13465 } else if (newScrollX < left) { 13466 newScrollX = left; 13467 clampedX = true; 13468 } 13469 13470 boolean clampedY = false; 13471 if (newScrollY > bottom) { 13472 newScrollY = bottom; 13473 clampedY = true; 13474 } else if (newScrollY < top) { 13475 newScrollY = top; 13476 clampedY = true; 13477 } 13478 13479 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 13480 13481 return clampedX || clampedY; 13482 } 13483 13484 /** 13485 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 13486 * respond to the results of an over-scroll operation. 13487 * 13488 * @param scrollX New X scroll value in pixels 13489 * @param scrollY New Y scroll value in pixels 13490 * @param clampedX True if scrollX was clamped to an over-scroll boundary 13491 * @param clampedY True if scrollY was clamped to an over-scroll boundary 13492 */ 13493 protected void onOverScrolled(int scrollX, int scrollY, 13494 boolean clampedX, boolean clampedY) { 13495 // Intentionally empty. 13496 } 13497 13498 /** 13499 * Returns the over-scroll mode for this view. The result will be 13500 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 13501 * (allow over-scrolling only if the view content is larger than the container), 13502 * or {@link #OVER_SCROLL_NEVER}. 13503 * 13504 * @return This view's over-scroll mode. 13505 */ 13506 public int getOverScrollMode() { 13507 return mOverScrollMode; 13508 } 13509 13510 /** 13511 * Set the over-scroll mode for this view. Valid over-scroll modes are 13512 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 13513 * (allow over-scrolling only if the view content is larger than the container), 13514 * or {@link #OVER_SCROLL_NEVER}. 13515 * 13516 * Setting the over-scroll mode of a view will have an effect only if the 13517 * view is capable of scrolling. 13518 * 13519 * @param overScrollMode The new over-scroll mode for this view. 13520 */ 13521 public void setOverScrollMode(int overScrollMode) { 13522 if (overScrollMode != OVER_SCROLL_ALWAYS && 13523 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 13524 overScrollMode != OVER_SCROLL_NEVER) { 13525 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 13526 } 13527 mOverScrollMode = overScrollMode; 13528 } 13529 13530 /** 13531 * Gets a scale factor that determines the distance the view should scroll 13532 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 13533 * @return The vertical scroll scale factor. 13534 * @hide 13535 */ 13536 protected float getVerticalScrollFactor() { 13537 if (mVerticalScrollFactor == 0) { 13538 TypedValue outValue = new TypedValue(); 13539 if (!mContext.getTheme().resolveAttribute( 13540 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 13541 throw new IllegalStateException( 13542 "Expected theme to define listPreferredItemHeight."); 13543 } 13544 mVerticalScrollFactor = outValue.getDimension( 13545 mContext.getResources().getDisplayMetrics()); 13546 } 13547 return mVerticalScrollFactor; 13548 } 13549 13550 /** 13551 * Gets a scale factor that determines the distance the view should scroll 13552 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 13553 * @return The horizontal scroll scale factor. 13554 * @hide 13555 */ 13556 protected float getHorizontalScrollFactor() { 13557 // TODO: Should use something else. 13558 return getVerticalScrollFactor(); 13559 } 13560 13561 /** 13562 * Return the value specifying the text direction or policy that was set with 13563 * {@link #setTextDirection(int)}. 13564 * 13565 * @return the defined text direction. It can be one of: 13566 * 13567 * {@link #TEXT_DIRECTION_INHERIT}, 13568 * {@link #TEXT_DIRECTION_FIRST_STRONG} 13569 * {@link #TEXT_DIRECTION_ANY_RTL}, 13570 * {@link #TEXT_DIRECTION_LTR}, 13571 * {@link #TEXT_DIRECTION_RTL}, 13572 * 13573 * @hide 13574 */ 13575 public int getTextDirection() { 13576 return mTextDirection; 13577 } 13578 13579 /** 13580 * Set the text direction. 13581 * 13582 * @param textDirection the direction to set. Should be one of: 13583 * 13584 * {@link #TEXT_DIRECTION_INHERIT}, 13585 * {@link #TEXT_DIRECTION_FIRST_STRONG} 13586 * {@link #TEXT_DIRECTION_ANY_RTL}, 13587 * {@link #TEXT_DIRECTION_LTR}, 13588 * {@link #TEXT_DIRECTION_RTL}, 13589 * 13590 * @hide 13591 */ 13592 public void setTextDirection(int textDirection) { 13593 if (textDirection != mTextDirection) { 13594 mTextDirection = textDirection; 13595 resetResolvedTextDirection(); 13596 requestLayout(); 13597 } 13598 } 13599 13600 /** 13601 * Return the resolved text direction. 13602 * 13603 * @return the resolved text direction. Return one of: 13604 * 13605 * {@link #TEXT_DIRECTION_FIRST_STRONG} 13606 * {@link #TEXT_DIRECTION_ANY_RTL}, 13607 * {@link #TEXT_DIRECTION_LTR}, 13608 * {@link #TEXT_DIRECTION_RTL}, 13609 * 13610 * @hide 13611 */ 13612 public int getResolvedTextDirection() { 13613 if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) { 13614 resolveTextDirection(); 13615 } 13616 return mResolvedTextDirection; 13617 } 13618 13619 /** 13620 * Resolve the text direction. 13621 * 13622 * @hide 13623 */ 13624 protected void resolveTextDirection() { 13625 if (mTextDirection != TEXT_DIRECTION_INHERIT) { 13626 mResolvedTextDirection = mTextDirection; 13627 return; 13628 } 13629 if (mParent != null && mParent instanceof ViewGroup) { 13630 mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection(); 13631 return; 13632 } 13633 mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG; 13634 } 13635 13636 /** 13637 * Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection(). 13638 * 13639 * @hide 13640 */ 13641 protected void resetResolvedTextDirection() { 13642 mResolvedTextDirection = TEXT_DIRECTION_INHERIT; 13643 } 13644 13645 // 13646 // Properties 13647 // 13648 /** 13649 * A Property wrapper around the <code>alpha</code> functionality handled by the 13650 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 13651 */ 13652 public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 13653 @Override 13654 public void setValue(View object, float value) { 13655 object.setAlpha(value); 13656 } 13657 13658 @Override 13659 public Float get(View object) { 13660 return object.getAlpha(); 13661 } 13662 }; 13663 13664 /** 13665 * A Property wrapper around the <code>translationX</code> functionality handled by the 13666 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 13667 */ 13668 public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 13669 @Override 13670 public void setValue(View object, float value) { 13671 object.setTranslationX(value); 13672 } 13673 13674 @Override 13675 public Float get(View object) { 13676 return object.getTranslationX(); 13677 } 13678 }; 13679 13680 /** 13681 * A Property wrapper around the <code>translationY</code> functionality handled by the 13682 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 13683 */ 13684 public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 13685 @Override 13686 public void setValue(View object, float value) { 13687 object.setTranslationY(value); 13688 } 13689 13690 @Override 13691 public Float get(View object) { 13692 return object.getTranslationY(); 13693 } 13694 }; 13695 13696 /** 13697 * A Property wrapper around the <code>x</code> functionality handled by the 13698 * {@link View#setX(float)} and {@link View#getX()} methods. 13699 */ 13700 public static Property<View, Float> X = new FloatProperty<View>("x") { 13701 @Override 13702 public void setValue(View object, float value) { 13703 object.setX(value); 13704 } 13705 13706 @Override 13707 public Float get(View object) { 13708 return object.getX(); 13709 } 13710 }; 13711 13712 /** 13713 * A Property wrapper around the <code>y</code> functionality handled by the 13714 * {@link View#setY(float)} and {@link View#getY()} methods. 13715 */ 13716 public static Property<View, Float> Y = new FloatProperty<View>("y") { 13717 @Override 13718 public void setValue(View object, float value) { 13719 object.setY(value); 13720 } 13721 13722 @Override 13723 public Float get(View object) { 13724 return object.getY(); 13725 } 13726 }; 13727 13728 /** 13729 * A Property wrapper around the <code>rotation</code> functionality handled by the 13730 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 13731 */ 13732 public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 13733 @Override 13734 public void setValue(View object, float value) { 13735 object.setRotation(value); 13736 } 13737 13738 @Override 13739 public Float get(View object) { 13740 return object.getRotation(); 13741 } 13742 }; 13743 13744 /** 13745 * A Property wrapper around the <code>rotationX</code> functionality handled by the 13746 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 13747 */ 13748 public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 13749 @Override 13750 public void setValue(View object, float value) { 13751 object.setRotationX(value); 13752 } 13753 13754 @Override 13755 public Float get(View object) { 13756 return object.getRotationX(); 13757 } 13758 }; 13759 13760 /** 13761 * A Property wrapper around the <code>rotationY</code> functionality handled by the 13762 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 13763 */ 13764 public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 13765 @Override 13766 public void setValue(View object, float value) { 13767 object.setRotationY(value); 13768 } 13769 13770 @Override 13771 public Float get(View object) { 13772 return object.getRotationY(); 13773 } 13774 }; 13775 13776 /** 13777 * A Property wrapper around the <code>scaleX</code> functionality handled by the 13778 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 13779 */ 13780 public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 13781 @Override 13782 public void setValue(View object, float value) { 13783 object.setScaleX(value); 13784 } 13785 13786 @Override 13787 public Float get(View object) { 13788 return object.getScaleX(); 13789 } 13790 }; 13791 13792 /** 13793 * A Property wrapper around the <code>scaleY</code> functionality handled by the 13794 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 13795 */ 13796 public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 13797 @Override 13798 public void setValue(View object, float value) { 13799 object.setScaleY(value); 13800 } 13801 13802 @Override 13803 public Float get(View object) { 13804 return object.getScaleY(); 13805 } 13806 }; 13807 13808 /** 13809 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 13810 * Each MeasureSpec represents a requirement for either the width or the height. 13811 * A MeasureSpec is comprised of a size and a mode. There are three possible 13812 * modes: 13813 * <dl> 13814 * <dt>UNSPECIFIED</dt> 13815 * <dd> 13816 * The parent has not imposed any constraint on the child. It can be whatever size 13817 * it wants. 13818 * </dd> 13819 * 13820 * <dt>EXACTLY</dt> 13821 * <dd> 13822 * The parent has determined an exact size for the child. The child is going to be 13823 * given those bounds regardless of how big it wants to be. 13824 * </dd> 13825 * 13826 * <dt>AT_MOST</dt> 13827 * <dd> 13828 * The child can be as large as it wants up to the specified size. 13829 * </dd> 13830 * </dl> 13831 * 13832 * MeasureSpecs are implemented as ints to reduce object allocation. This class 13833 * is provided to pack and unpack the <size, mode> tuple into the int. 13834 */ 13835 public static class MeasureSpec { 13836 private static final int MODE_SHIFT = 30; 13837 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 13838 13839 /** 13840 * Measure specification mode: The parent has not imposed any constraint 13841 * on the child. It can be whatever size it wants. 13842 */ 13843 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 13844 13845 /** 13846 * Measure specification mode: The parent has determined an exact size 13847 * for the child. The child is going to be given those bounds regardless 13848 * of how big it wants to be. 13849 */ 13850 public static final int EXACTLY = 1 << MODE_SHIFT; 13851 13852 /** 13853 * Measure specification mode: The child can be as large as it wants up 13854 * to the specified size. 13855 */ 13856 public static final int AT_MOST = 2 << MODE_SHIFT; 13857 13858 /** 13859 * Creates a measure specification based on the supplied size and mode. 13860 * 13861 * The mode must always be one of the following: 13862 * <ul> 13863 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 13864 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 13865 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 13866 * </ul> 13867 * 13868 * @param size the size of the measure specification 13869 * @param mode the mode of the measure specification 13870 * @return the measure specification based on size and mode 13871 */ 13872 public static int makeMeasureSpec(int size, int mode) { 13873 return size + mode; 13874 } 13875 13876 /** 13877 * Extracts the mode from the supplied measure specification. 13878 * 13879 * @param measureSpec the measure specification to extract the mode from 13880 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 13881 * {@link android.view.View.MeasureSpec#AT_MOST} or 13882 * {@link android.view.View.MeasureSpec#EXACTLY} 13883 */ 13884 public static int getMode(int measureSpec) { 13885 return (measureSpec & MODE_MASK); 13886 } 13887 13888 /** 13889 * Extracts the size from the supplied measure specification. 13890 * 13891 * @param measureSpec the measure specification to extract the size from 13892 * @return the size in pixels defined in the supplied measure specification 13893 */ 13894 public static int getSize(int measureSpec) { 13895 return (measureSpec & ~MODE_MASK); 13896 } 13897 13898 /** 13899 * Returns a String representation of the specified measure 13900 * specification. 13901 * 13902 * @param measureSpec the measure specification to convert to a String 13903 * @return a String with the following format: "MeasureSpec: MODE SIZE" 13904 */ 13905 public static String toString(int measureSpec) { 13906 int mode = getMode(measureSpec); 13907 int size = getSize(measureSpec); 13908 13909 StringBuilder sb = new StringBuilder("MeasureSpec: "); 13910 13911 if (mode == UNSPECIFIED) 13912 sb.append("UNSPECIFIED "); 13913 else if (mode == EXACTLY) 13914 sb.append("EXACTLY "); 13915 else if (mode == AT_MOST) 13916 sb.append("AT_MOST "); 13917 else 13918 sb.append(mode).append(" "); 13919 13920 sb.append(size); 13921 return sb.toString(); 13922 } 13923 } 13924 13925 class CheckForLongPress implements Runnable { 13926 13927 private int mOriginalWindowAttachCount; 13928 13929 public void run() { 13930 if (isPressed() && (mParent != null) 13931 && mOriginalWindowAttachCount == mWindowAttachCount) { 13932 if (performLongClick()) { 13933 mHasPerformedLongPress = true; 13934 } 13935 } 13936 } 13937 13938 public void rememberWindowAttachCount() { 13939 mOriginalWindowAttachCount = mWindowAttachCount; 13940 } 13941 } 13942 13943 private final class CheckForTap implements Runnable { 13944 public void run() { 13945 mPrivateFlags &= ~PREPRESSED; 13946 mPrivateFlags |= PRESSED; 13947 refreshDrawableState(); 13948 checkForLongClick(ViewConfiguration.getTapTimeout()); 13949 } 13950 } 13951 13952 private final class PerformClick implements Runnable { 13953 public void run() { 13954 performClick(); 13955 } 13956 } 13957 13958 /** @hide */ 13959 public void hackTurnOffWindowResizeAnim(boolean off) { 13960 mAttachInfo.mTurnOffWindowResizeAnim = off; 13961 } 13962 13963 /** 13964 * This method returns a ViewPropertyAnimator object, which can be used to animate 13965 * specific properties on this View. 13966 * 13967 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 13968 */ 13969 public ViewPropertyAnimator animate() { 13970 if (mAnimator == null) { 13971 mAnimator = new ViewPropertyAnimator(this); 13972 } 13973 return mAnimator; 13974 } 13975 13976 /** 13977 * Interface definition for a callback to be invoked when a key event is 13978 * dispatched to this view. The callback will be invoked before the key 13979 * event is given to the view. 13980 */ 13981 public interface OnKeyListener { 13982 /** 13983 * Called when a key is dispatched to a view. This allows listeners to 13984 * get a chance to respond before the target view. 13985 * 13986 * @param v The view the key has been dispatched to. 13987 * @param keyCode The code for the physical key that was pressed 13988 * @param event The KeyEvent object containing full information about 13989 * the event. 13990 * @return True if the listener has consumed the event, false otherwise. 13991 */ 13992 boolean onKey(View v, int keyCode, KeyEvent event); 13993 } 13994 13995 /** 13996 * Interface definition for a callback to be invoked when a touch event is 13997 * dispatched to this view. The callback will be invoked before the touch 13998 * event is given to the view. 13999 */ 14000 public interface OnTouchListener { 14001 /** 14002 * Called when a touch event is dispatched to a view. This allows listeners to 14003 * get a chance to respond before the target view. 14004 * 14005 * @param v The view the touch event has been dispatched to. 14006 * @param event The MotionEvent object containing full information about 14007 * the event. 14008 * @return True if the listener has consumed the event, false otherwise. 14009 */ 14010 boolean onTouch(View v, MotionEvent event); 14011 } 14012 14013 /** 14014 * Interface definition for a callback to be invoked when a hover event is 14015 * dispatched to this view. The callback will be invoked before the hover 14016 * event is given to the view. 14017 */ 14018 public interface OnHoverListener { 14019 /** 14020 * Called when a hover event is dispatched to a view. This allows listeners to 14021 * get a chance to respond before the target view. 14022 * 14023 * @param v The view the hover event has been dispatched to. 14024 * @param event The MotionEvent object containing full information about 14025 * the event. 14026 * @return True if the listener has consumed the event, false otherwise. 14027 */ 14028 boolean onHover(View v, MotionEvent event); 14029 } 14030 14031 /** 14032 * Interface definition for a callback to be invoked when a generic motion event is 14033 * dispatched to this view. The callback will be invoked before the generic motion 14034 * event is given to the view. 14035 */ 14036 public interface OnGenericMotionListener { 14037 /** 14038 * Called when a generic motion event is dispatched to a view. This allows listeners to 14039 * get a chance to respond before the target view. 14040 * 14041 * @param v The view the generic motion event has been dispatched to. 14042 * @param event The MotionEvent object containing full information about 14043 * the event. 14044 * @return True if the listener has consumed the event, false otherwise. 14045 */ 14046 boolean onGenericMotion(View v, MotionEvent event); 14047 } 14048 14049 /** 14050 * Interface definition for a callback to be invoked when a view has been clicked and held. 14051 */ 14052 public interface OnLongClickListener { 14053 /** 14054 * Called when a view has been clicked and held. 14055 * 14056 * @param v The view that was clicked and held. 14057 * 14058 * @return true if the callback consumed the long click, false otherwise. 14059 */ 14060 boolean onLongClick(View v); 14061 } 14062 14063 /** 14064 * Interface definition for a callback to be invoked when a drag is being dispatched 14065 * to this view. The callback will be invoked before the hosting view's own 14066 * onDrag(event) method. If the listener wants to fall back to the hosting view's 14067 * onDrag(event) behavior, it should return 'false' from this callback. 14068 */ 14069 public interface OnDragListener { 14070 /** 14071 * Called when a drag event is dispatched to a view. This allows listeners 14072 * to get a chance to override base View behavior. 14073 * 14074 * @param v The View that received the drag event. 14075 * @param event The {@link android.view.DragEvent} object for the drag event. 14076 * @return {@code true} if the drag event was handled successfully, or {@code false} 14077 * if the drag event was not handled. Note that {@code false} will trigger the View 14078 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 14079 */ 14080 boolean onDrag(View v, DragEvent event); 14081 } 14082 14083 /** 14084 * Interface definition for a callback to be invoked when the focus state of 14085 * a view changed. 14086 */ 14087 public interface OnFocusChangeListener { 14088 /** 14089 * Called when the focus state of a view has changed. 14090 * 14091 * @param v The view whose state has changed. 14092 * @param hasFocus The new focus state of v. 14093 */ 14094 void onFocusChange(View v, boolean hasFocus); 14095 } 14096 14097 /** 14098 * Interface definition for a callback to be invoked when a view is clicked. 14099 */ 14100 public interface OnClickListener { 14101 /** 14102 * Called when a view has been clicked. 14103 * 14104 * @param v The view that was clicked. 14105 */ 14106 void onClick(View v); 14107 } 14108 14109 /** 14110 * Interface definition for a callback to be invoked when the context menu 14111 * for this view is being built. 14112 */ 14113 public interface OnCreateContextMenuListener { 14114 /** 14115 * Called when the context menu for this view is being built. It is not 14116 * safe to hold onto the menu after this method returns. 14117 * 14118 * @param menu The context menu that is being built 14119 * @param v The view for which the context menu is being built 14120 * @param menuInfo Extra information about the item for which the 14121 * context menu should be shown. This information will vary 14122 * depending on the class of v. 14123 */ 14124 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 14125 } 14126 14127 /** 14128 * Interface definition for a callback to be invoked when the status bar changes 14129 * visibility. This reports <strong>global</strong> changes to the system UI 14130 * state, not just what the application is requesting. 14131 * 14132 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 14133 */ 14134 public interface OnSystemUiVisibilityChangeListener { 14135 /** 14136 * Called when the status bar changes visibility because of a call to 14137 * {@link View#setSystemUiVisibility(int)}. 14138 * 14139 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or 14140 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. This tells you the 14141 * <strong>global</strong> state of the UI visibility flags, not what your 14142 * app is currently applying. 14143 */ 14144 public void onSystemUiVisibilityChange(int visibility); 14145 } 14146 14147 /** 14148 * Interface definition for a callback to be invoked when this view is attached 14149 * or detached from its window. 14150 */ 14151 public interface OnAttachStateChangeListener { 14152 /** 14153 * Called when the view is attached to a window. 14154 * @param v The view that was attached 14155 */ 14156 public void onViewAttachedToWindow(View v); 14157 /** 14158 * Called when the view is detached from a window. 14159 * @param v The view that was detached 14160 */ 14161 public void onViewDetachedFromWindow(View v); 14162 } 14163 14164 private final class UnsetPressedState implements Runnable { 14165 public void run() { 14166 setPressed(false); 14167 } 14168 } 14169 14170 /** 14171 * Base class for derived classes that want to save and restore their own 14172 * state in {@link android.view.View#onSaveInstanceState()}. 14173 */ 14174 public static class BaseSavedState extends AbsSavedState { 14175 /** 14176 * Constructor used when reading from a parcel. Reads the state of the superclass. 14177 * 14178 * @param source 14179 */ 14180 public BaseSavedState(Parcel source) { 14181 super(source); 14182 } 14183 14184 /** 14185 * Constructor called by derived classes when creating their SavedState objects 14186 * 14187 * @param superState The state of the superclass of this view 14188 */ 14189 public BaseSavedState(Parcelable superState) { 14190 super(superState); 14191 } 14192 14193 public static final Parcelable.Creator<BaseSavedState> CREATOR = 14194 new Parcelable.Creator<BaseSavedState>() { 14195 public BaseSavedState createFromParcel(Parcel in) { 14196 return new BaseSavedState(in); 14197 } 14198 14199 public BaseSavedState[] newArray(int size) { 14200 return new BaseSavedState[size]; 14201 } 14202 }; 14203 } 14204 14205 /** 14206 * A set of information given to a view when it is attached to its parent 14207 * window. 14208 */ 14209 static class AttachInfo { 14210 interface Callbacks { 14211 void playSoundEffect(int effectId); 14212 boolean performHapticFeedback(int effectId, boolean always); 14213 } 14214 14215 /** 14216 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 14217 * to a Handler. This class contains the target (View) to invalidate and 14218 * the coordinates of the dirty rectangle. 14219 * 14220 * For performance purposes, this class also implements a pool of up to 14221 * POOL_LIMIT objects that get reused. This reduces memory allocations 14222 * whenever possible. 14223 */ 14224 static class InvalidateInfo implements Poolable<InvalidateInfo> { 14225 private static final int POOL_LIMIT = 10; 14226 private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool( 14227 Pools.finitePool(new PoolableManager<InvalidateInfo>() { 14228 public InvalidateInfo newInstance() { 14229 return new InvalidateInfo(); 14230 } 14231 14232 public void onAcquired(InvalidateInfo element) { 14233 } 14234 14235 public void onReleased(InvalidateInfo element) { 14236 element.target = null; 14237 } 14238 }, POOL_LIMIT) 14239 ); 14240 14241 private InvalidateInfo mNext; 14242 private boolean mIsPooled; 14243 14244 View target; 14245 14246 int left; 14247 int top; 14248 int right; 14249 int bottom; 14250 14251 public void setNextPoolable(InvalidateInfo element) { 14252 mNext = element; 14253 } 14254 14255 public InvalidateInfo getNextPoolable() { 14256 return mNext; 14257 } 14258 14259 static InvalidateInfo acquire() { 14260 return sPool.acquire(); 14261 } 14262 14263 void release() { 14264 sPool.release(this); 14265 } 14266 14267 public boolean isPooled() { 14268 return mIsPooled; 14269 } 14270 14271 public void setPooled(boolean isPooled) { 14272 mIsPooled = isPooled; 14273 } 14274 } 14275 14276 final IWindowSession mSession; 14277 14278 final IWindow mWindow; 14279 14280 final IBinder mWindowToken; 14281 14282 final Callbacks mRootCallbacks; 14283 14284 HardwareCanvas mHardwareCanvas; 14285 14286 /** 14287 * The top view of the hierarchy. 14288 */ 14289 View mRootView; 14290 14291 IBinder mPanelParentWindowToken; 14292 Surface mSurface; 14293 14294 boolean mHardwareAccelerated; 14295 boolean mHardwareAccelerationRequested; 14296 HardwareRenderer mHardwareRenderer; 14297 14298 /** 14299 * Scale factor used by the compatibility mode 14300 */ 14301 float mApplicationScale; 14302 14303 /** 14304 * Indicates whether the application is in compatibility mode 14305 */ 14306 boolean mScalingRequired; 14307 14308 /** 14309 * If set, ViewAncestor doesn't use its lame animation for when the window resizes. 14310 */ 14311 boolean mTurnOffWindowResizeAnim; 14312 14313 /** 14314 * Left position of this view's window 14315 */ 14316 int mWindowLeft; 14317 14318 /** 14319 * Top position of this view's window 14320 */ 14321 int mWindowTop; 14322 14323 /** 14324 * Indicates whether views need to use 32-bit drawing caches 14325 */ 14326 boolean mUse32BitDrawingCache; 14327 14328 /** 14329 * For windows that are full-screen but using insets to layout inside 14330 * of the screen decorations, these are the current insets for the 14331 * content of the window. 14332 */ 14333 final Rect mContentInsets = new Rect(); 14334 14335 /** 14336 * For windows that are full-screen but using insets to layout inside 14337 * of the screen decorations, these are the current insets for the 14338 * actual visible parts of the window. 14339 */ 14340 final Rect mVisibleInsets = new Rect(); 14341 14342 /** 14343 * The internal insets given by this window. This value is 14344 * supplied by the client (through 14345 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 14346 * be given to the window manager when changed to be used in laying 14347 * out windows behind it. 14348 */ 14349 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 14350 = new ViewTreeObserver.InternalInsetsInfo(); 14351 14352 /** 14353 * All views in the window's hierarchy that serve as scroll containers, 14354 * used to determine if the window can be resized or must be panned 14355 * to adjust for a soft input area. 14356 */ 14357 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 14358 14359 final KeyEvent.DispatcherState mKeyDispatchState 14360 = new KeyEvent.DispatcherState(); 14361 14362 /** 14363 * Indicates whether the view's window currently has the focus. 14364 */ 14365 boolean mHasWindowFocus; 14366 14367 /** 14368 * The current visibility of the window. 14369 */ 14370 int mWindowVisibility; 14371 14372 /** 14373 * Indicates the time at which drawing started to occur. 14374 */ 14375 long mDrawingTime; 14376 14377 /** 14378 * Indicates whether or not ignoring the DIRTY_MASK flags. 14379 */ 14380 boolean mIgnoreDirtyState; 14381 14382 /** 14383 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 14384 * to avoid clearing that flag prematurely. 14385 */ 14386 boolean mSetIgnoreDirtyState = false; 14387 14388 /** 14389 * Indicates whether the view's window is currently in touch mode. 14390 */ 14391 boolean mInTouchMode; 14392 14393 /** 14394 * Indicates that ViewAncestor should trigger a global layout change 14395 * the next time it performs a traversal 14396 */ 14397 boolean mRecomputeGlobalAttributes; 14398 14399 /** 14400 * Always report new attributes at next traversal. 14401 */ 14402 boolean mForceReportNewAttributes; 14403 14404 /** 14405 * Set during a traveral if any views want to keep the screen on. 14406 */ 14407 boolean mKeepScreenOn; 14408 14409 /** 14410 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 14411 */ 14412 int mSystemUiVisibility; 14413 14414 /** 14415 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 14416 * attached. 14417 */ 14418 boolean mHasSystemUiListeners; 14419 14420 /** 14421 * Set if the visibility of any views has changed. 14422 */ 14423 boolean mViewVisibilityChanged; 14424 14425 /** 14426 * Set to true if a view has been scrolled. 14427 */ 14428 boolean mViewScrollChanged; 14429 14430 /** 14431 * Global to the view hierarchy used as a temporary for dealing with 14432 * x/y points in the transparent region computations. 14433 */ 14434 final int[] mTransparentLocation = new int[2]; 14435 14436 /** 14437 * Global to the view hierarchy used as a temporary for dealing with 14438 * x/y points in the ViewGroup.invalidateChild implementation. 14439 */ 14440 final int[] mInvalidateChildLocation = new int[2]; 14441 14442 14443 /** 14444 * Global to the view hierarchy used as a temporary for dealing with 14445 * x/y location when view is transformed. 14446 */ 14447 final float[] mTmpTransformLocation = new float[2]; 14448 14449 /** 14450 * The view tree observer used to dispatch global events like 14451 * layout, pre-draw, touch mode change, etc. 14452 */ 14453 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 14454 14455 /** 14456 * A Canvas used by the view hierarchy to perform bitmap caching. 14457 */ 14458 Canvas mCanvas; 14459 14460 /** 14461 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 14462 * handler can be used to pump events in the UI events queue. 14463 */ 14464 final Handler mHandler; 14465 14466 /** 14467 * Identifier for messages requesting the view to be invalidated. 14468 * Such messages should be sent to {@link #mHandler}. 14469 */ 14470 static final int INVALIDATE_MSG = 0x1; 14471 14472 /** 14473 * Identifier for messages requesting the view to invalidate a region. 14474 * Such messages should be sent to {@link #mHandler}. 14475 */ 14476 static final int INVALIDATE_RECT_MSG = 0x2; 14477 14478 /** 14479 * Temporary for use in computing invalidate rectangles while 14480 * calling up the hierarchy. 14481 */ 14482 final Rect mTmpInvalRect = new Rect(); 14483 14484 /** 14485 * Temporary for use in computing hit areas with transformed views 14486 */ 14487 final RectF mTmpTransformRect = new RectF(); 14488 14489 /** 14490 * Temporary list for use in collecting focusable descendents of a view. 14491 */ 14492 final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24); 14493 14494 /** 14495 * The id of the window for accessibility purposes. 14496 */ 14497 int mAccessibilityWindowId = View.NO_ID; 14498 14499 /** 14500 * Creates a new set of attachment information with the specified 14501 * events handler and thread. 14502 * 14503 * @param handler the events handler the view must use 14504 */ 14505 AttachInfo(IWindowSession session, IWindow window, 14506 Handler handler, Callbacks effectPlayer) { 14507 mSession = session; 14508 mWindow = window; 14509 mWindowToken = window.asBinder(); 14510 mHandler = handler; 14511 mRootCallbacks = effectPlayer; 14512 } 14513 } 14514 14515 /** 14516 * <p>ScrollabilityCache holds various fields used by a View when scrolling 14517 * is supported. This avoids keeping too many unused fields in most 14518 * instances of View.</p> 14519 */ 14520 private static class ScrollabilityCache implements Runnable { 14521 14522 /** 14523 * Scrollbars are not visible 14524 */ 14525 public static final int OFF = 0; 14526 14527 /** 14528 * Scrollbars are visible 14529 */ 14530 public static final int ON = 1; 14531 14532 /** 14533 * Scrollbars are fading away 14534 */ 14535 public static final int FADING = 2; 14536 14537 public boolean fadeScrollBars; 14538 14539 public int fadingEdgeLength; 14540 public int scrollBarDefaultDelayBeforeFade; 14541 public int scrollBarFadeDuration; 14542 14543 public int scrollBarSize; 14544 public ScrollBarDrawable scrollBar; 14545 public float[] interpolatorValues; 14546 public View host; 14547 14548 public final Paint paint; 14549 public final Matrix matrix; 14550 public Shader shader; 14551 14552 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 14553 14554 private static final float[] OPAQUE = { 255 }; 14555 private static final float[] TRANSPARENT = { 0.0f }; 14556 14557 /** 14558 * When fading should start. This time moves into the future every time 14559 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 14560 */ 14561 public long fadeStartTime; 14562 14563 14564 /** 14565 * The current state of the scrollbars: ON, OFF, or FADING 14566 */ 14567 public int state = OFF; 14568 14569 private int mLastColor; 14570 14571 public ScrollabilityCache(ViewConfiguration configuration, View host) { 14572 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 14573 scrollBarSize = configuration.getScaledScrollBarSize(); 14574 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 14575 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 14576 14577 paint = new Paint(); 14578 matrix = new Matrix(); 14579 // use use a height of 1, and then wack the matrix each time we 14580 // actually use it. 14581 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 14582 14583 paint.setShader(shader); 14584 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 14585 this.host = host; 14586 } 14587 14588 public void setFadeColor(int color) { 14589 if (color != 0 && color != mLastColor) { 14590 mLastColor = color; 14591 color |= 0xFF000000; 14592 14593 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 14594 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 14595 14596 paint.setShader(shader); 14597 // Restore the default transfer mode (src_over) 14598 paint.setXfermode(null); 14599 } 14600 } 14601 14602 public void run() { 14603 long now = AnimationUtils.currentAnimationTimeMillis(); 14604 if (now >= fadeStartTime) { 14605 14606 // the animation fades the scrollbars out by changing 14607 // the opacity (alpha) from fully opaque to fully 14608 // transparent 14609 int nextFrame = (int) now; 14610 int framesCount = 0; 14611 14612 Interpolator interpolator = scrollBarInterpolator; 14613 14614 // Start opaque 14615 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 14616 14617 // End transparent 14618 nextFrame += scrollBarFadeDuration; 14619 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 14620 14621 state = FADING; 14622 14623 // Kick off the fade animation 14624 host.invalidate(true); 14625 } 14626 } 14627 } 14628 14629 /** 14630 * Resuable callback for sending 14631 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 14632 */ 14633 private class SendViewScrolledAccessibilityEvent implements Runnable { 14634 public volatile boolean mIsPending; 14635 14636 public void run() { 14637 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 14638 mIsPending = false; 14639 } 14640 } 14641 14642 /** 14643 * <p> 14644 * This class represents a delegate that can be registered in a {@link View} 14645 * to enhance accessibility support via composition rather via inheritance. 14646 * It is specifically targeted to widget developers that extend basic View 14647 * classes i.e. classes in package android.view, that would like their 14648 * applications to be backwards compatible. 14649 * </p> 14650 * <p> 14651 * A scenario in which a developer would like to use an accessibility delegate 14652 * is overriding a method introduced in a later API version then the minimal API 14653 * version supported by the application. For example, the method 14654 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 14655 * in API version 4 when the accessibility APIs were first introduced. If a 14656 * developer would like his application to run on API version 4 devices (assuming 14657 * all other APIs used by the application are version 4 or lower) and take advantage 14658 * of this method, instead of overriding the method which would break the application's 14659 * backwards compatibility, he can override the corresponding method in this 14660 * delegate and register the delegate in the target View if the API version of 14661 * the system is high enough i.e. the API version is same or higher to the API 14662 * version that introduced 14663 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 14664 * </p> 14665 * <p> 14666 * Here is an example implementation: 14667 * </p> 14668 * <code><pre><p> 14669 * if (Build.VERSION.SDK_INT >= 14) { 14670 * // If the API version is equal of higher than the version in 14671 * // which onInitializeAccessibilityNodeInfo was introduced we 14672 * // register a delegate with a customized implementation. 14673 * View view = findViewById(R.id.view_id); 14674 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 14675 * public void onInitializeAccessibilityNodeInfo(View host, 14676 * AccessibilityNodeInfo info) { 14677 * // Let the default implementation populate the info. 14678 * super.onInitializeAccessibilityNodeInfo(host, info); 14679 * // Set some other information. 14680 * info.setEnabled(host.isEnabled()); 14681 * } 14682 * }); 14683 * } 14684 * </code></pre></p> 14685 * <p> 14686 * This delegate contains methods that correspond to the accessibility methods 14687 * in View. If a delegate has been specified the implementation in View hands 14688 * off handling to the corresponding method in this delegate. The default 14689 * implementation the delegate methods behaves exactly as the corresponding 14690 * method in View for the case of no accessibility delegate been set. Hence, 14691 * to customize the behavior of a View method, clients can override only the 14692 * corresponding delegate method without altering the behavior of the rest 14693 * accessibility related methods of the host view. 14694 * </p> 14695 */ 14696 public static class AccessibilityDelegate { 14697 14698 /** 14699 * Sends an accessibility event of the given type. If accessibility is not 14700 * enabled this method has no effect. 14701 * <p> 14702 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 14703 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 14704 * been set. 14705 * </p> 14706 * 14707 * @param host The View hosting the delegate. 14708 * @param eventType The type of the event to send. 14709 * 14710 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 14711 */ 14712 public void sendAccessibilityEvent(View host, int eventType) { 14713 host.sendAccessibilityEventInternal(eventType); 14714 } 14715 14716 /** 14717 * Sends an accessibility event. This method behaves exactly as 14718 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 14719 * empty {@link AccessibilityEvent} and does not perform a check whether 14720 * accessibility is enabled. 14721 * <p> 14722 * The default implementation behaves as 14723 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 14724 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 14725 * the case of no accessibility delegate been set. 14726 * </p> 14727 * 14728 * @param host The View hosting the delegate. 14729 * @param event The event to send. 14730 * 14731 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 14732 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 14733 */ 14734 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 14735 host.sendAccessibilityEventUncheckedInternal(event); 14736 } 14737 14738 /** 14739 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 14740 * to its children for adding their text content to the event. 14741 * <p> 14742 * The default implementation behaves as 14743 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 14744 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 14745 * the case of no accessibility delegate been set. 14746 * </p> 14747 * 14748 * @param host The View hosting the delegate. 14749 * @param event The event. 14750 * @return True if the event population was completed. 14751 * 14752 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 14753 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 14754 */ 14755 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 14756 return host.dispatchPopulateAccessibilityEventInternal(event); 14757 } 14758 14759 /** 14760 * Gives a chance to the host View to populate the accessibility event with its 14761 * text content. 14762 * <p> 14763 * The default implementation behaves as 14764 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 14765 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 14766 * the case of no accessibility delegate been set. 14767 * </p> 14768 * 14769 * @param host The View hosting the delegate. 14770 * @param event The accessibility event which to populate. 14771 * 14772 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 14773 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 14774 */ 14775 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 14776 host.onPopulateAccessibilityEventInternal(event); 14777 } 14778 14779 /** 14780 * Initializes an {@link AccessibilityEvent} with information about the 14781 * the host View which is the event source. 14782 * <p> 14783 * The default implementation behaves as 14784 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 14785 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 14786 * the case of no accessibility delegate been set. 14787 * </p> 14788 * 14789 * @param host The View hosting the delegate. 14790 * @param event The event to initialize. 14791 * 14792 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 14793 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 14794 */ 14795 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 14796 host.onInitializeAccessibilityEventInternal(event); 14797 } 14798 14799 /** 14800 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 14801 * <p> 14802 * The default implementation behaves as 14803 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 14804 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 14805 * the case of no accessibility delegate been set. 14806 * </p> 14807 * 14808 * @param host The View hosting the delegate. 14809 * @param info The instance to initialize. 14810 * 14811 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 14812 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 14813 */ 14814 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 14815 host.onInitializeAccessibilityNodeInfoInternal(info); 14816 } 14817 14818 /** 14819 * Called when a child of the host View has requested sending an 14820 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 14821 * to augment the event. 14822 * <p> 14823 * The default implementation behaves as 14824 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 14825 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 14826 * the case of no accessibility delegate been set. 14827 * </p> 14828 * 14829 * @param host The View hosting the delegate. 14830 * @param child The child which requests sending the event. 14831 * @param event The event to be sent. 14832 * @return True if the event should be sent 14833 * 14834 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 14835 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 14836 */ 14837 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 14838 AccessibilityEvent event) { 14839 return host.onRequestSendAccessibilityEventInternal(child, event); 14840 } 14841 } 14842} 14843