View.java revision c39a6e0c51e182338deb8b63d07933b585134929
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.Context; 20import android.content.res.Resources; 21import android.content.res.TypedArray; 22import android.graphics.Bitmap; 23import android.graphics.Canvas; 24import android.graphics.LinearGradient; 25import android.graphics.Matrix; 26import android.graphics.Paint; 27import android.graphics.PixelFormat; 28import android.graphics.PorterDuff; 29import android.graphics.PorterDuffXfermode; 30import android.graphics.Rect; 31import android.graphics.Region; 32import android.graphics.Shader; 33import android.graphics.Point; 34import android.graphics.drawable.ColorDrawable; 35import android.graphics.drawable.Drawable; 36import android.os.Handler; 37import android.os.IBinder; 38import android.os.Message; 39import android.os.Parcel; 40import android.os.Parcelable; 41import android.os.RemoteException; 42import android.os.SystemClock; 43import android.os.SystemProperties; 44import android.util.AttributeSet; 45import android.util.EventLog; 46import android.util.Log; 47import android.util.SparseArray; 48import android.view.ContextMenu.ContextMenuInfo; 49import android.view.animation.Animation; 50import android.view.inputmethod.InputConnection; 51import android.view.inputmethod.InputMethodManager; 52import android.view.inputmethod.EditorInfo; 53import android.widget.ScrollBarDrawable; 54 55import com.android.internal.R; 56import com.android.internal.view.menu.MenuBuilder; 57 58import java.util.ArrayList; 59import java.util.Arrays; 60import java.lang.ref.SoftReference; 61 62/** 63 * <p> 64 * This class represents the basic building block for user interface components. A View 65 * occupies a rectangular area on the screen and is responsible for drawing and 66 * event handling. View is the base class for <em>widgets</em>, which are 67 * used to create interactive UI components (buttons, text fields, etc.). The 68 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 69 * are invisible containers that hold other Views (or other ViewGroups) and define 70 * their layout properties. 71 * </p> 72 * 73 * <div class="special"> 74 * <p>For an introduction to using this class to develop your 75 * application's user interface, read the Developer Guide documentation on 76 * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics 77 * include: 78 * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> 79 * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> 80 * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a> 81 * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a> 82 * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a> 83 * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a> 84 * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a> 85 * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>. 86 * </p> 87 * </div> 88 * 89 * <a name="Using"></a> 90 * <h3>Using Views</h3> 91 * <p> 92 * All of the views in a window are arranged in a single tree. You can add views 93 * either from code or by specifying a tree of views in one or more XML layout 94 * files. There are many specialized subclasses of views that act as controls or 95 * are capable of displaying text, images, or other content. 96 * </p> 97 * <p> 98 * Once you have created a tree of views, there are typically a few types of 99 * common operations you may wish to perform: 100 * <ul> 101 * <li><strong>Set properties:</strong> for example setting the text of a 102 * {@link android.widget.TextView}. The available properties and the methods 103 * that set them will vary among the different subclasses of views. Note that 104 * properties that are known at build time can be set in the XML layout 105 * files.</li> 106 * <li><strong>Set focus:</strong> The framework will handled moving focus in 107 * response to user input. To force focus to a specific view, call 108 * {@link #requestFocus}.</li> 109 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 110 * that will be notified when something interesting happens to the view. For 111 * example, all views will let you set a listener to be notified when the view 112 * gains or loses focus. You can register such a listener using 113 * {@link #setOnFocusChangeListener}. Other view subclasses offer more 114 * specialized listeners. For example, a Button exposes a listener to notify 115 * clients when the button is clicked.</li> 116 * <li><strong>Set visibility:</strong> You can hide or show views using 117 * {@link #setVisibility}.</li> 118 * </ul> 119 * </p> 120 * <p><em> 121 * Note: The Android framework is responsible for measuring, laying out and 122 * drawing views. You should not call methods that perform these actions on 123 * views yourself unless you are actually implementing a 124 * {@link android.view.ViewGroup}. 125 * </em></p> 126 * 127 * <a name="Lifecycle"></a> 128 * <h3>Implementing a Custom View</h3> 129 * 130 * <p> 131 * To implement a custom view, you will usually begin by providing overrides for 132 * some of the standard methods that the framework calls on all views. You do 133 * not need to override all of these methods. In fact, you can start by just 134 * overriding {@link #onDraw(android.graphics.Canvas)}. 135 * <table border="2" width="85%" align="center" cellpadding="5"> 136 * <thead> 137 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 138 * </thead> 139 * 140 * <tbody> 141 * <tr> 142 * <td rowspan="2">Creation</td> 143 * <td>Constructors</td> 144 * <td>There is a form of the constructor that are called when the view 145 * is created from code and a form that is called when the view is 146 * inflated from a layout file. The second form should parse and apply 147 * any attributes defined in the layout file. 148 * </td> 149 * </tr> 150 * <tr> 151 * <td><code>{@link #onFinishInflate()}</code></td> 152 * <td>Called after a view and all of its children has been inflated 153 * from XML.</td> 154 * </tr> 155 * 156 * <tr> 157 * <td rowspan="3">Layout</td> 158 * <td><code>{@link #onMeasure}</code></td> 159 * <td>Called to determine the size requirements for this view and all 160 * of its children. 161 * </td> 162 * </tr> 163 * <tr> 164 * <td><code>{@link #onLayout}</code></td> 165 * <td>Called when this view should assign a size and position to all 166 * of its children. 167 * </td> 168 * </tr> 169 * <tr> 170 * <td><code>{@link #onSizeChanged}</code></td> 171 * <td>Called when the size of this view has changed. 172 * </td> 173 * </tr> 174 * 175 * <tr> 176 * <td>Drawing</td> 177 * <td><code>{@link #onDraw}</code></td> 178 * <td>Called when the view should render its content. 179 * </td> 180 * </tr> 181 * 182 * <tr> 183 * <td rowspan="4">Event processing</td> 184 * <td><code>{@link #onKeyDown}</code></td> 185 * <td>Called when a new key event occurs. 186 * </td> 187 * </tr> 188 * <tr> 189 * <td><code>{@link #onKeyUp}</code></td> 190 * <td>Called when a key up event occurs. 191 * </td> 192 * </tr> 193 * <tr> 194 * <td><code>{@link #onTrackballEvent}</code></td> 195 * <td>Called when a trackball motion event occurs. 196 * </td> 197 * </tr> 198 * <tr> 199 * <td><code>{@link #onTouchEvent}</code></td> 200 * <td>Called when a touch screen motion event occurs. 201 * </td> 202 * </tr> 203 * 204 * <tr> 205 * <td rowspan="2">Focus</td> 206 * <td><code>{@link #onFocusChanged}</code></td> 207 * <td>Called when the view gains or loses focus. 208 * </td> 209 * </tr> 210 * 211 * <tr> 212 * <td><code>{@link #onWindowFocusChanged}</code></td> 213 * <td>Called when the window containing the view gains or loses focus. 214 * </td> 215 * </tr> 216 * 217 * <tr> 218 * <td rowspan="3">Attaching</td> 219 * <td><code>{@link #onAttachedToWindow()}</code></td> 220 * <td>Called when the view is attached to a window. 221 * </td> 222 * </tr> 223 * 224 * <tr> 225 * <td><code>{@link #onDetachedFromWindow}</code></td> 226 * <td>Called when the view is detached from its window. 227 * </td> 228 * </tr> 229 * 230 * <tr> 231 * <td><code>{@link #onWindowVisibilityChanged}</code></td> 232 * <td>Called when the visibility of the window containing the view 233 * has changed. 234 * </td> 235 * </tr> 236 * </tbody> 237 * 238 * </table> 239 * </p> 240 * 241 * <a name="IDs"></a> 242 * <h3>IDs</h3> 243 * Views may have an integer id associated with them. These ids are typically 244 * assigned in the layout XML files, and are used to find specific views within 245 * the view tree. A common pattern is to: 246 * <ul> 247 * <li>Define a Button in the layout file and assign it a unique ID. 248 * <pre> 249 * <Button id="@+id/my_button" 250 * android:layout_width="wrap_content" 251 * android:layout_height="wrap_content" 252 * android:text="@string/my_button_text"/> 253 * </pre></li> 254 * <li>From the onCreate method of an Activity, find the Button 255 * <pre class="prettyprint"> 256 * Button myButton = (Button) findViewById(R.id.my_button); 257 * </pre></li> 258 * </ul> 259 * <p> 260 * View IDs need not be unique throughout the tree, but it is good practice to 261 * ensure that they are at least unique within the part of the tree you are 262 * searching. 263 * </p> 264 * 265 * <a name="Position"></a> 266 * <h3>Position</h3> 267 * <p> 268 * The geometry of a view is that of a rectangle. A view has a location, 269 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 270 * two dimensions, expressed as a width and a height. The unit for location 271 * and dimensions is the pixel. 272 * </p> 273 * 274 * <p> 275 * It is possible to retrieve the location of a view by invoking the methods 276 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 277 * coordinate of the rectangle representing the view. The latter returns the 278 * top, or Y, coordinate of the rectangle representing the view. These methods 279 * both return the location of the view relative to its parent. For instance, 280 * when getLeft() returns 20, that means the view is located 20 pixels to the 281 * right of the left edge of its direct parent. 282 * </p> 283 * 284 * <p> 285 * In addition, several convenience methods are offered to avoid unnecessary 286 * computations, namely {@link #getRight()} and {@link #getBottom()}. 287 * These methods return the coordinates of the right and bottom edges of the 288 * rectangle representing the view. For instance, calling {@link #getRight()} 289 * is similar to the following computation: <code>getLeft() + getWidth()</code> 290 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 291 * </p> 292 * 293 * <a name="SizePaddingMargins"></a> 294 * <h3>Size, padding and margins</h3> 295 * <p> 296 * The size of a view is expressed with a width and a height. A view actually 297 * possess two pairs of width and height values. 298 * </p> 299 * 300 * <p> 301 * The first pair is known as <em>measured width</em> and 302 * <em>measured height</em>. These dimensions define how big a view wants to be 303 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 304 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 305 * and {@link #getMeasuredHeight()}. 306 * </p> 307 * 308 * <p> 309 * The second pair is simply known as <em>width</em> and <em>height</em>, or 310 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 311 * dimensions define the actual size of the view on screen, at drawing time and 312 * after layout. These values may, but do not have to, be different from the 313 * measured width and height. The width and height can be obtained by calling 314 * {@link #getWidth()} and {@link #getHeight()}. 315 * </p> 316 * 317 * <p> 318 * To measure its dimensions, a view takes into account its padding. The padding 319 * is expressed in pixels for the left, top, right and bottom parts of the view. 320 * Padding can be used to offset the content of the view by a specific amount of 321 * pixels. For instance, a left padding of 2 will push the view's content by 322 * 2 pixels to the right of the left edge. Padding can be set using the 323 * {@link #setPadding(int, int, int, int)} method and queried by calling 324 * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 325 * {@link #getPaddingRight()} and {@link #getPaddingBottom()}. 326 * </p> 327 * 328 * <p> 329 * Even though a view can define a padding, it does not provide any support for 330 * margins. However, view groups provide such a support. Refer to 331 * {@link android.view.ViewGroup} and 332 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 333 * </p> 334 * 335 * <a name="Layout"></a> 336 * <h3>Layout</h3> 337 * <p> 338 * Layout is a two pass process: a measure pass and a layout pass. The measuring 339 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 340 * of the view tree. Each view pushes dimension specifications down the tree 341 * during the recursion. At the end of the measure pass, every view has stored 342 * its measurements. The second pass happens in 343 * {@link #layout(int,int,int,int)} and is also top-down. During 344 * this pass each parent is responsible for positioning all of its children 345 * using the sizes computed in the measure pass. 346 * </p> 347 * 348 * <p> 349 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 350 * {@link #getMeasuredHeight()} values must be set, along with those for all of 351 * that view's descendants. A view's measured width and measured height values 352 * must respect the constraints imposed by the view's parents. This guarantees 353 * that at the end of the measure pass, all parents accept all of their 354 * children's measurements. A parent view may call measure() more than once on 355 * its children. For example, the parent may measure each child once with 356 * unspecified dimensions to find out how big they want to be, then call 357 * measure() on them again with actual numbers if the sum of all the children's 358 * unconstrained sizes is too big or too small. 359 * </p> 360 * 361 * <p> 362 * The measure pass uses two classes to communicate dimensions. The 363 * {@link MeasureSpec} class is used by views to tell their parents how they 364 * want to be measured and positioned. The base LayoutParams class just 365 * describes how big the view wants to be for both width and height. For each 366 * dimension, it can specify one of: 367 * <ul> 368 * <li> an exact number 369 * <li>FILL_PARENT, which means the view wants to be as big as its parent 370 * (minus padding) 371 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 372 * enclose its content (plus padding). 373 * </ul> 374 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 375 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 376 * an X and Y value. 377 * </p> 378 * 379 * <p> 380 * MeasureSpecs are used to push requirements down the tree from parent to 381 * child. A MeasureSpec can be in one of three modes: 382 * <ul> 383 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 384 * of a child view. For example, a LinearLayout may call measure() on its child 385 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 386 * tall the child view wants to be given a width of 240 pixels. 387 * <li>EXACTLY: This is used by the parent to impose an exact size on the 388 * child. The child must use this size, and guarantee that all of its 389 * descendants will fit within this size. 390 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 391 * child. The child must gurantee that it and all of its descendants will fit 392 * within this size. 393 * </ul> 394 * </p> 395 * 396 * <p> 397 * To intiate a layout, call {@link #requestLayout}. This method is typically 398 * called by a view on itself when it believes that is can no longer fit within 399 * its current bounds. 400 * </p> 401 * 402 * <a name="Drawing"></a> 403 * <h3>Drawing</h3> 404 * <p> 405 * Drawing is handled by walking the tree and rendering each view that 406 * intersects the the invalid region. Because the tree is traversed in-order, 407 * this means that parents will draw before (i.e., behind) their children, with 408 * siblings drawn in the order they appear in the tree. 409 * If you set a background drawable for a View, then the View will draw it for you 410 * before calling back to its <code>onDraw()</code> method. 411 * </p> 412 * 413 * <p> 414 * Note that the framework will not draw views that are not in the invalid region. 415 * </p> 416 * 417 * <p> 418 * To force a view to draw, call {@link #invalidate()}. 419 * </p> 420 * 421 * <a name="EventHandlingThreading"></a> 422 * <h3>Event Handling and Threading</h3> 423 * <p> 424 * The basic cycle of a view is as follows: 425 * <ol> 426 * <li>An event comes in and is dispatched to the appropriate view. The view 427 * handles the event and notifies any listeners.</li> 428 * <li>If in the course of processing the event, the view's bounds may need 429 * to be changed, the view will call {@link #requestLayout()}.</li> 430 * <li>Similarly, if in the course of processing the event the view's appearance 431 * may need to be changed, the view will call {@link #invalidate()}.</li> 432 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 433 * the framework will take care of measuring, laying out, and drawing the tree 434 * as appropriate.</li> 435 * </ol> 436 * </p> 437 * 438 * <p><em>Note: The entire view tree is single threaded. You must always be on 439 * the UI thread when calling any method on any view.</em> 440 * If you are doing work on other threads and want to update the state of a view 441 * from that thread, you should use a {@link Handler}. 442 * </p> 443 * 444 * <a name="FocusHandling"></a> 445 * <h3>Focus Handling</h3> 446 * <p> 447 * The framework will handle routine focus movement in response to user input. 448 * This includes changing the focus as views are removed or hidden, or as new 449 * views become available. Views indicate their willingness to take focus 450 * through the {@link #isFocusable} method. To change whether a view can take 451 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 452 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 453 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 454 * </p> 455 * <p> 456 * Focus movement is based on an algorithm which finds the nearest neighbor in a 457 * given direction. In rare cases, the default algorithm may not match the 458 * intended behavior of the developer. In these situations, you can provide 459 * explicit overrides by using these XML attributes in the layout file: 460 * <pre> 461 * nextFocusDown 462 * nextFocusLeft 463 * nextFocusRight 464 * nextFocusUp 465 * </pre> 466 * </p> 467 * 468 * 469 * <p> 470 * To get a particular view to take focus, call {@link #requestFocus()}. 471 * </p> 472 * 473 * <a name="TouchMode"></a> 474 * <h3>Touch Mode</h3> 475 * <p> 476 * When a user is navigating a user interface via directional keys such as a D-pad, it is 477 * necessary to give focus to actionable items such as buttons so the user can see 478 * what will take input. If the device has touch capabilities, however, and the user 479 * begins interacting with the interface by touching it, it is no longer necessary to 480 * always highlight, or give focus to, a particular view. This motivates a mode 481 * for interaction named 'touch mode'. 482 * </p> 483 * <p> 484 * For a touch capable device, once the user touches the screen, the device 485 * will enter touch mode. From this point onward, only views for which 486 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 487 * Other views that are touchable, like buttons, will not take focus when touched; they will 488 * only fire the on click listeners. 489 * </p> 490 * <p> 491 * Any time a user hits a directional key, such as a D-pad direction, the view device will 492 * exit touch mode, and find a view to take focus, so that the user may resume interacting 493 * with the user interface without touching the screen again. 494 * </p> 495 * <p> 496 * The touch mode state is maintained across {@link android.app.Activity}s. Call 497 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 498 * </p> 499 * 500 * <a name="Scrolling"></a> 501 * <h3>Scrolling</h3> 502 * <p> 503 * The framework provides basic support for views that wish to internally 504 * scroll their content. This includes keeping track of the X and Y scroll 505 * offset as well as mechanisms for drawing scrollbars. See 506 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)} for more details. 507 * </p> 508 * 509 * <a name="Tags"></a> 510 * <h3>Tags</h3> 511 * <p> 512 * Unlike IDs, tags are not used to identify views. Tags are essentially an 513 * extra piece of information that can be associated with a view. They are most 514 * often used as a convenience to store data related to views in the views 515 * themselves rather than by putting them in a separate structure. 516 * </p> 517 * 518 * <a name="Animation"></a> 519 * <h3>Animation</h3> 520 * <p> 521 * You can attach an {@link Animation} object to a view using 522 * {@link #setAnimation(Animation)} or 523 * {@link #startAnimation(Animation)}. The animation can alter the scale, 524 * rotation, translation and alpha of a view over time. If the animation is 525 * attached to a view that has children, the animation will affect the entire 526 * subtree rooted by that node. When an animation is started, the framework will 527 * take care of redrawing the appropriate views until the animation completes. 528 * </p> 529 * 530 * @attr ref android.R.styleable#View_fitsSystemWindows 531 * @attr ref android.R.styleable#View_nextFocusDown 532 * @attr ref android.R.styleable#View_nextFocusLeft 533 * @attr ref android.R.styleable#View_nextFocusRight 534 * @attr ref android.R.styleable#View_nextFocusUp 535 * @attr ref android.R.styleable#View_scrollX 536 * @attr ref android.R.styleable#View_scrollY 537 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 538 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 539 * @attr ref android.R.styleable#View_scrollbarSize 540 * @attr ref android.R.styleable#View_scrollbars 541 * @attr ref android.R.styleable#View_scrollbarThumbVertical 542 * @attr ref android.R.styleable#View_scrollbarTrackVertical 543 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 544 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 545 * 546 * @see android.view.ViewGroup 547 */ 548public class View implements Drawable.Callback, KeyEvent.Callback { 549 private static final boolean DBG = false; 550 551 /** 552 * The logging tag used by this class with android.util.Log. 553 */ 554 protected static final String VIEW_LOG_TAG = "View"; 555 556 /** 557 * Used to mark a View that has no ID. 558 */ 559 public static final int NO_ID = -1; 560 561 /** 562 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 563 * calling setFlags. 564 */ 565 private static final int NOT_FOCUSABLE = 0x00000000; 566 567 /** 568 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 569 * setFlags. 570 */ 571 private static final int FOCUSABLE = 0x00000001; 572 573 /** 574 * Mask for use with setFlags indicating bits used for focus. 575 */ 576 private static final int FOCUSABLE_MASK = 0x00000001; 577 578 /** 579 * This view will adjust its padding to fit sytem windows (e.g. status bar) 580 */ 581 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 582 583 /** 584 * This view is visible. Use with {@link #setVisibility}. 585 */ 586 public static final int VISIBLE = 0x00000000; 587 588 /** 589 * This view is invisible, but it still takes up space for layout purposes. 590 * Use with {@link #setVisibility}. 591 */ 592 public static final int INVISIBLE = 0x00000004; 593 594 /** 595 * This view is invisible, and it doesn't take any space for layout 596 * purposes. Use with {@link #setVisibility}. 597 */ 598 public static final int GONE = 0x00000008; 599 600 /** 601 * Mask for use with setFlags indicating bits used for visibility. 602 * {@hide} 603 */ 604 static final int VISIBILITY_MASK = 0x0000000C; 605 606 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 607 608 /** 609 * This view is enabled. Intrepretation varies by subclass. 610 * Use with ENABLED_MASK when calling setFlags. 611 * {@hide} 612 */ 613 static final int ENABLED = 0x00000000; 614 615 /** 616 * This view is disabled. Intrepretation varies by subclass. 617 * Use with ENABLED_MASK when calling setFlags. 618 * {@hide} 619 */ 620 static final int DISABLED = 0x00000020; 621 622 /** 623 * Mask for use with setFlags indicating bits used for indicating whether 624 * this view is enabled 625 * {@hide} 626 */ 627 static final int ENABLED_MASK = 0x00000020; 628 629 /** 630 * This view won't draw. {@link #onDraw} won't be called and further 631 * optimizations 632 * will be performed. It is okay to have this flag set and a background. 633 * Use with DRAW_MASK when calling setFlags. 634 * {@hide} 635 */ 636 static final int WILL_NOT_DRAW = 0x00000080; 637 638 /** 639 * Mask for use with setFlags indicating bits used for indicating whether 640 * this view is will draw 641 * {@hide} 642 */ 643 static final int DRAW_MASK = 0x00000080; 644 645 /** 646 * <p>This view doesn't show scrollbars.</p> 647 * {@hide} 648 */ 649 static final int SCROLLBARS_NONE = 0x00000000; 650 651 /** 652 * <p>This view shows horizontal scrollbars.</p> 653 * {@hide} 654 */ 655 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 656 657 /** 658 * <p>This view shows vertical scrollbars.</p> 659 * {@hide} 660 */ 661 static final int SCROLLBARS_VERTICAL = 0x00000200; 662 663 /** 664 * <p>Mask for use with setFlags indicating bits used for indicating which 665 * scrollbars are enabled.</p> 666 * {@hide} 667 */ 668 static final int SCROLLBARS_MASK = 0x00000300; 669 670 // note 0x00000400 and 0x00000800 are now available for next flags... 671 672 /** 673 * <p>This view doesn't show fading edges.</p> 674 * {@hide} 675 */ 676 static final int FADING_EDGE_NONE = 0x00000000; 677 678 /** 679 * <p>This view shows horizontal fading edges.</p> 680 * {@hide} 681 */ 682 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 683 684 /** 685 * <p>This view shows vertical fading edges.</p> 686 * {@hide} 687 */ 688 static final int FADING_EDGE_VERTICAL = 0x00002000; 689 690 /** 691 * <p>Mask for use with setFlags indicating bits used for indicating which 692 * fading edges are enabled.</p> 693 * {@hide} 694 */ 695 static final int FADING_EDGE_MASK = 0x00003000; 696 697 /** 698 * <p>Indicates this view can be clicked. When clickable, a View reacts 699 * to clicks by notifying the OnClickListener.<p> 700 * {@hide} 701 */ 702 static final int CLICKABLE = 0x00004000; 703 704 /** 705 * <p>Indicates this view is caching its drawing into a bitmap.</p> 706 * {@hide} 707 */ 708 static final int DRAWING_CACHE_ENABLED = 0x00008000; 709 710 /** 711 * <p>Indicates that no icicle should be saved for this view.<p> 712 * {@hide} 713 */ 714 static final int SAVE_DISABLED = 0x000010000; 715 716 /** 717 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 718 * property.</p> 719 * {@hide} 720 */ 721 static final int SAVE_DISABLED_MASK = 0x000010000; 722 723 /** 724 * <p>Indicates that no drawing cache should ever be created for this view.<p> 725 * {@hide} 726 */ 727 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 728 729 /** 730 * <p>Indicates this view can take / keep focus when int touch mode.</p> 731 * {@hide} 732 */ 733 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 734 735 /** 736 * <p>Enables low quality mode for the drawing cache.</p> 737 */ 738 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 739 740 /** 741 * <p>Enables high quality mode for the drawing cache.</p> 742 */ 743 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 744 745 /** 746 * <p>Enables automatic quality mode for the drawing cache.</p> 747 */ 748 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 749 750 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 751 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 752 }; 753 754 /** 755 * <p>Mask for use with setFlags indicating bits used for the cache 756 * quality property.</p> 757 * {@hide} 758 */ 759 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 760 761 /** 762 * <p> 763 * Indicates this view can be long clicked. When long clickable, a View 764 * reacts to long clicks by notifying the OnLongClickListener or showing a 765 * context menu. 766 * </p> 767 * {@hide} 768 */ 769 static final int LONG_CLICKABLE = 0x00200000; 770 771 /** 772 * <p>Indicates that this view gets its drawable states from its direct parent 773 * and ignores its original internal states.</p> 774 * 775 * @hide 776 */ 777 static final int DUPLICATE_PARENT_STATE = 0x00400000; 778 779 /** 780 * The scrollbar style to display the scrollbars inside the content area, 781 * without increasing the padding. The scrollbars will be overlaid with 782 * translucency on the view's content. 783 */ 784 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 785 786 /** 787 * The scrollbar style to display the scrollbars inside the padded area, 788 * increasing the padding of the view. The scrollbars will not overlap the 789 * content area of the view. 790 */ 791 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 792 793 /** 794 * The scrollbar style to display the scrollbars at the edge of the view, 795 * without increasing the padding. The scrollbars will be overlaid with 796 * translucency. 797 */ 798 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 799 800 /** 801 * The scrollbar style to display the scrollbars at the edge of the view, 802 * increasing the padding of the view. The scrollbars will only overlap the 803 * background, if any. 804 */ 805 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 806 807 /** 808 * Mask to check if the scrollbar style is overlay or inset. 809 * {@hide} 810 */ 811 static final int SCROLLBARS_INSET_MASK = 0x01000000; 812 813 /** 814 * Mask to check if the scrollbar style is inside or outside. 815 * {@hide} 816 */ 817 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 818 819 /** 820 * Mask for scrollbar style. 821 * {@hide} 822 */ 823 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 824 825 /** 826 * View flag indicating that the screen should remain on while the 827 * window containing this view is visible to the user. This effectively 828 * takes care of automatically setting the WindowManager's 829 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 830 */ 831 public static final int KEEP_SCREEN_ON = 0x04000000; 832 833 /** 834 * View flag indicating whether this view should have sound effects enabled 835 * for events such as clicking and touching. 836 */ 837 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 838 839 /** 840 * View flag indicating whether this view should have haptic feedback 841 * enabled for events such as long presses. 842 */ 843 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 844 845 /** 846 * Use with {@link #focusSearch}. Move focus to the previous selectable 847 * item. 848 */ 849 public static final int FOCUS_BACKWARD = 0x00000001; 850 851 /** 852 * Use with {@link #focusSearch}. Move focus to the next selectable 853 * item. 854 */ 855 public static final int FOCUS_FORWARD = 0x00000002; 856 857 /** 858 * Use with {@link #focusSearch}. Move focus to the left. 859 */ 860 public static final int FOCUS_LEFT = 0x00000011; 861 862 /** 863 * Use with {@link #focusSearch}. Move focus up. 864 */ 865 public static final int FOCUS_UP = 0x00000021; 866 867 /** 868 * Use with {@link #focusSearch}. Move focus to the right. 869 */ 870 public static final int FOCUS_RIGHT = 0x00000042; 871 872 /** 873 * Use with {@link #focusSearch}. Move focus down. 874 */ 875 public static final int FOCUS_DOWN = 0x00000082; 876 877 /** 878 * Base View state sets 879 */ 880 // Singles 881 /** 882 * Indicates the view has no states set. States are used with 883 * {@link android.graphics.drawable.Drawable} to change the drawing of the 884 * view depending on its state. 885 * 886 * @see android.graphics.drawable.Drawable 887 * @see #getDrawableState() 888 */ 889 protected static final int[] EMPTY_STATE_SET = {}; 890 /** 891 * Indicates the view is enabled. States are used with 892 * {@link android.graphics.drawable.Drawable} to change the drawing of the 893 * view depending on its state. 894 * 895 * @see android.graphics.drawable.Drawable 896 * @see #getDrawableState() 897 */ 898 protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled}; 899 /** 900 * Indicates the view is focused. States are used with 901 * {@link android.graphics.drawable.Drawable} to change the drawing of the 902 * view depending on its state. 903 * 904 * @see android.graphics.drawable.Drawable 905 * @see #getDrawableState() 906 */ 907 protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused}; 908 /** 909 * Indicates the view is selected. States are used with 910 * {@link android.graphics.drawable.Drawable} to change the drawing of the 911 * view depending on its state. 912 * 913 * @see android.graphics.drawable.Drawable 914 * @see #getDrawableState() 915 */ 916 protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected}; 917 /** 918 * Indicates the view is pressed. States are used with 919 * {@link android.graphics.drawable.Drawable} to change the drawing of the 920 * view depending on its state. 921 * 922 * @see android.graphics.drawable.Drawable 923 * @see #getDrawableState() 924 * @hide 925 */ 926 protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed}; 927 /** 928 * Indicates the view's window has focus. States are used with 929 * {@link android.graphics.drawable.Drawable} to change the drawing of the 930 * view depending on its state. 931 * 932 * @see android.graphics.drawable.Drawable 933 * @see #getDrawableState() 934 */ 935 protected static final int[] WINDOW_FOCUSED_STATE_SET = 936 {R.attr.state_window_focused}; 937 // Doubles 938 /** 939 * Indicates the view is enabled and has the focus. 940 * 941 * @see #ENABLED_STATE_SET 942 * @see #FOCUSED_STATE_SET 943 */ 944 protected static final int[] ENABLED_FOCUSED_STATE_SET = 945 stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET); 946 /** 947 * Indicates the view is enabled and selected. 948 * 949 * @see #ENABLED_STATE_SET 950 * @see #SELECTED_STATE_SET 951 */ 952 protected static final int[] ENABLED_SELECTED_STATE_SET = 953 stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET); 954 /** 955 * Indicates the view is enabled and that its window has focus. 956 * 957 * @see #ENABLED_STATE_SET 958 * @see #WINDOW_FOCUSED_STATE_SET 959 */ 960 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = 961 stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 962 /** 963 * Indicates the view is focused and selected. 964 * 965 * @see #FOCUSED_STATE_SET 966 * @see #SELECTED_STATE_SET 967 */ 968 protected static final int[] FOCUSED_SELECTED_STATE_SET = 969 stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET); 970 /** 971 * Indicates the view has the focus and that its window has the focus. 972 * 973 * @see #FOCUSED_STATE_SET 974 * @see #WINDOW_FOCUSED_STATE_SET 975 */ 976 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = 977 stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 978 /** 979 * Indicates the view is selected and that its window has the focus. 980 * 981 * @see #SELECTED_STATE_SET 982 * @see #WINDOW_FOCUSED_STATE_SET 983 */ 984 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = 985 stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 986 // Triples 987 /** 988 * Indicates the view is enabled, focused and selected. 989 * 990 * @see #ENABLED_STATE_SET 991 * @see #FOCUSED_STATE_SET 992 * @see #SELECTED_STATE_SET 993 */ 994 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = 995 stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); 996 /** 997 * Indicates the view is enabled, focused and its window has the focus. 998 * 999 * @see #ENABLED_STATE_SET 1000 * @see #FOCUSED_STATE_SET 1001 * @see #WINDOW_FOCUSED_STATE_SET 1002 */ 1003 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = 1004 stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1005 /** 1006 * Indicates the view is enabled, selected and its window has the focus. 1007 * 1008 * @see #ENABLED_STATE_SET 1009 * @see #SELECTED_STATE_SET 1010 * @see #WINDOW_FOCUSED_STATE_SET 1011 */ 1012 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1013 stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1014 /** 1015 * Indicates the view is focused, selected and its window has the focus. 1016 * 1017 * @see #FOCUSED_STATE_SET 1018 * @see #SELECTED_STATE_SET 1019 * @see #WINDOW_FOCUSED_STATE_SET 1020 */ 1021 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1022 stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1023 /** 1024 * Indicates the view is enabled, focused, selected and its window 1025 * has the focus. 1026 * 1027 * @see #ENABLED_STATE_SET 1028 * @see #FOCUSED_STATE_SET 1029 * @see #SELECTED_STATE_SET 1030 * @see #WINDOW_FOCUSED_STATE_SET 1031 */ 1032 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1033 stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET, 1034 WINDOW_FOCUSED_STATE_SET); 1035 1036 /** 1037 * Indicates the view is pressed and its window has the focus. 1038 * 1039 * @see #PRESSED_STATE_SET 1040 * @see #WINDOW_FOCUSED_STATE_SET 1041 */ 1042 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = 1043 stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1044 1045 /** 1046 * Indicates the view is pressed and selected. 1047 * 1048 * @see #PRESSED_STATE_SET 1049 * @see #SELECTED_STATE_SET 1050 */ 1051 protected static final int[] PRESSED_SELECTED_STATE_SET = 1052 stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET); 1053 1054 /** 1055 * Indicates the view is pressed, selected and its window has the focus. 1056 * 1057 * @see #PRESSED_STATE_SET 1058 * @see #SELECTED_STATE_SET 1059 * @see #WINDOW_FOCUSED_STATE_SET 1060 */ 1061 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1062 stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1063 1064 /** 1065 * Indicates the view is pressed and focused. 1066 * 1067 * @see #PRESSED_STATE_SET 1068 * @see #FOCUSED_STATE_SET 1069 */ 1070 protected static final int[] PRESSED_FOCUSED_STATE_SET = 1071 stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET); 1072 1073 /** 1074 * Indicates the view is pressed, focused and its window has the focus. 1075 * 1076 * @see #PRESSED_STATE_SET 1077 * @see #FOCUSED_STATE_SET 1078 * @see #WINDOW_FOCUSED_STATE_SET 1079 */ 1080 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = 1081 stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1082 1083 /** 1084 * Indicates the view is pressed, focused and selected. 1085 * 1086 * @see #PRESSED_STATE_SET 1087 * @see #SELECTED_STATE_SET 1088 * @see #FOCUSED_STATE_SET 1089 */ 1090 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = 1091 stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET); 1092 1093 /** 1094 * Indicates the view is pressed, focused, selected and its window has the focus. 1095 * 1096 * @see #PRESSED_STATE_SET 1097 * @see #FOCUSED_STATE_SET 1098 * @see #SELECTED_STATE_SET 1099 * @see #WINDOW_FOCUSED_STATE_SET 1100 */ 1101 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1102 stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1103 1104 /** 1105 * Indicates the view is pressed and enabled. 1106 * 1107 * @see #PRESSED_STATE_SET 1108 * @see #ENABLED_STATE_SET 1109 */ 1110 protected static final int[] PRESSED_ENABLED_STATE_SET = 1111 stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET); 1112 1113 /** 1114 * Indicates the view is pressed, enabled and its window has the focus. 1115 * 1116 * @see #PRESSED_STATE_SET 1117 * @see #ENABLED_STATE_SET 1118 * @see #WINDOW_FOCUSED_STATE_SET 1119 */ 1120 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = 1121 stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1122 1123 /** 1124 * Indicates the view is pressed, enabled and selected. 1125 * 1126 * @see #PRESSED_STATE_SET 1127 * @see #ENABLED_STATE_SET 1128 * @see #SELECTED_STATE_SET 1129 */ 1130 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET = 1131 stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET); 1132 1133 /** 1134 * Indicates the view is pressed, enabled, selected and its window has the 1135 * focus. 1136 * 1137 * @see #PRESSED_STATE_SET 1138 * @see #ENABLED_STATE_SET 1139 * @see #SELECTED_STATE_SET 1140 * @see #WINDOW_FOCUSED_STATE_SET 1141 */ 1142 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1143 stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1144 1145 /** 1146 * Indicates the view is pressed, enabled and focused. 1147 * 1148 * @see #PRESSED_STATE_SET 1149 * @see #ENABLED_STATE_SET 1150 * @see #FOCUSED_STATE_SET 1151 */ 1152 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = 1153 stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET); 1154 1155 /** 1156 * Indicates the view is pressed, enabled, focused and its window has the 1157 * focus. 1158 * 1159 * @see #PRESSED_STATE_SET 1160 * @see #ENABLED_STATE_SET 1161 * @see #FOCUSED_STATE_SET 1162 * @see #WINDOW_FOCUSED_STATE_SET 1163 */ 1164 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = 1165 stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1166 1167 /** 1168 * Indicates the view is pressed, enabled, focused and selected. 1169 * 1170 * @see #PRESSED_STATE_SET 1171 * @see #ENABLED_STATE_SET 1172 * @see #SELECTED_STATE_SET 1173 * @see #FOCUSED_STATE_SET 1174 */ 1175 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = 1176 stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); 1177 1178 /** 1179 * Indicates the view is pressed, enabled, focused, selected and its window 1180 * has the focus. 1181 * 1182 * @see #PRESSED_STATE_SET 1183 * @see #ENABLED_STATE_SET 1184 * @see #SELECTED_STATE_SET 1185 * @see #FOCUSED_STATE_SET 1186 * @see #WINDOW_FOCUSED_STATE_SET 1187 */ 1188 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = 1189 stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); 1190 1191 /** 1192 * The order here is very important to {@link #getDrawableState()} 1193 */ 1194 private static final int[][] VIEW_STATE_SETS = { 1195 EMPTY_STATE_SET, // 0 0 0 0 0 1196 WINDOW_FOCUSED_STATE_SET, // 0 0 0 0 1 1197 SELECTED_STATE_SET, // 0 0 0 1 0 1198 SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 0 1 1 1199 FOCUSED_STATE_SET, // 0 0 1 0 0 1200 FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 0 1 1201 FOCUSED_SELECTED_STATE_SET, // 0 0 1 1 0 1202 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 0 1 1 1 1203 ENABLED_STATE_SET, // 0 1 0 0 0 1204 ENABLED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 0 1 1205 ENABLED_SELECTED_STATE_SET, // 0 1 0 1 0 1206 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 0 1 1 1207 ENABLED_FOCUSED_STATE_SET, // 0 1 1 0 0 1208 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 0 1 1209 ENABLED_FOCUSED_SELECTED_STATE_SET, // 0 1 1 1 0 1210 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 0 1 1 1 1 1211 PRESSED_STATE_SET, // 1 0 0 0 0 1212 PRESSED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 0 1 1213 PRESSED_SELECTED_STATE_SET, // 1 0 0 1 0 1214 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 0 1 1 1215 PRESSED_FOCUSED_STATE_SET, // 1 0 1 0 0 1216 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 0 1 1217 PRESSED_FOCUSED_SELECTED_STATE_SET, // 1 0 1 1 0 1218 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 0 1 1 1 1219 PRESSED_ENABLED_STATE_SET, // 1 1 0 0 0 1220 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 0 1 1221 PRESSED_ENABLED_SELECTED_STATE_SET, // 1 1 0 1 0 1222 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 0 1 1 1223 PRESSED_ENABLED_FOCUSED_STATE_SET, // 1 1 1 0 0 1224 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 0 1 1225 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, // 1 1 1 1 0 1226 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1 1227 }; 1228 1229 /** 1230 * Used by views that contain lists of items. This state indicates that 1231 * the view is showing the last item. 1232 * @hide 1233 */ 1234 protected static final int[] LAST_STATE_SET = {R.attr.state_last}; 1235 /** 1236 * Used by views that contain lists of items. This state indicates that 1237 * the view is showing the first item. 1238 * @hide 1239 */ 1240 protected static final int[] FIRST_STATE_SET = {R.attr.state_first}; 1241 /** 1242 * Used by views that contain lists of items. This state indicates that 1243 * the view is showing the middle item. 1244 * @hide 1245 */ 1246 protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle}; 1247 /** 1248 * Used by views that contain lists of items. This state indicates that 1249 * the view is showing only one item. 1250 * @hide 1251 */ 1252 protected static final int[] SINGLE_STATE_SET = {R.attr.state_single}; 1253 /** 1254 * Used by views that contain lists of items. This state indicates that 1255 * the view is pressed and showing the last item. 1256 * @hide 1257 */ 1258 protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed}; 1259 /** 1260 * Used by views that contain lists of items. This state indicates that 1261 * the view is pressed and showing the first item. 1262 * @hide 1263 */ 1264 protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed}; 1265 /** 1266 * Used by views that contain lists of items. This state indicates that 1267 * the view is pressed and showing the middle item. 1268 * @hide 1269 */ 1270 protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed}; 1271 /** 1272 * Used by views that contain lists of items. This state indicates that 1273 * the view is pressed and showing only one item. 1274 * @hide 1275 */ 1276 protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed}; 1277 1278 /** 1279 * Temporary Rect currently for use in setBackground(). This will probably 1280 * be extended in the future to hold our own class with more than just 1281 * a Rect. :) 1282 */ 1283 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1284 1285 /** 1286 * The animation currently associated with this view. 1287 * @hide 1288 */ 1289 protected Animation mCurrentAnimation = null; 1290 1291 /** 1292 * Width as measured during measure pass. 1293 * {@hide} 1294 */ 1295 @ViewDebug.ExportedProperty 1296 protected int mMeasuredWidth; 1297 1298 /** 1299 * Height as measured during measure pass. 1300 * {@hide} 1301 */ 1302 @ViewDebug.ExportedProperty 1303 protected int mMeasuredHeight; 1304 1305 /** 1306 * The view's identifier. 1307 * {@hide} 1308 * 1309 * @see #setId(int) 1310 * @see #getId() 1311 */ 1312 @ViewDebug.ExportedProperty(resolveId = true) 1313 int mID = NO_ID; 1314 1315 /** 1316 * The view's tag. 1317 * {@hide} 1318 * 1319 * @see #setTag(Object) 1320 * @see #getTag() 1321 */ 1322 protected Object mTag; 1323 1324 // for mPrivateFlags: 1325 /** {@hide} */ 1326 static final int WANTS_FOCUS = 0x00000001; 1327 /** {@hide} */ 1328 static final int FOCUSED = 0x00000002; 1329 /** {@hide} */ 1330 static final int SELECTED = 0x00000004; 1331 /** {@hide} */ 1332 static final int IS_ROOT_NAMESPACE = 0x00000008; 1333 /** {@hide} */ 1334 static final int HAS_BOUNDS = 0x00000010; 1335 /** {@hide} */ 1336 static final int DRAWN = 0x00000020; 1337 /** 1338 * When this flag is set, this view is running an animation on behalf of its 1339 * children and should therefore not cancel invalidate requests, even if they 1340 * lie outside of this view's bounds. 1341 * 1342 * {@hide} 1343 */ 1344 static final int DRAW_ANIMATION = 0x00000040; 1345 /** {@hide} */ 1346 static final int SKIP_DRAW = 0x00000080; 1347 /** {@hide} */ 1348 static final int ONLY_DRAWS_BACKGROUND = 0x00000100; 1349 /** {@hide} */ 1350 static final int REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1351 /** {@hide} */ 1352 static final int DRAWABLE_STATE_DIRTY = 0x00000400; 1353 /** {@hide} */ 1354 static final int MEASURED_DIMENSION_SET = 0x00000800; 1355 /** {@hide} */ 1356 static final int FORCE_LAYOUT = 0x00001000; 1357 1358 private static final int LAYOUT_REQUIRED = 0x00002000; 1359 1360 private static final int PRESSED = 0x00004000; 1361 1362 /** {@hide} */ 1363 static final int DRAWING_CACHE_VALID = 0x00008000; 1364 /** 1365 * Flag used to indicate that this view should be drawn once more (and only once 1366 * more) after its animation has completed. 1367 * {@hide} 1368 */ 1369 static final int ANIMATION_STARTED = 0x00010000; 1370 1371 private static final int SAVE_STATE_CALLED = 0x00020000; 1372 1373 /** 1374 * Indicates that the View returned true when onSetAlpha() was called and that 1375 * the alpha must be restored. 1376 * {@hide} 1377 */ 1378 static final int ALPHA_SET = 0x00040000; 1379 1380 /** 1381 * Set by {@link #setScrollContainer(boolean)}. 1382 */ 1383 static final int SCROLL_CONTAINER = 0x00080000; 1384 1385 /** 1386 * Set by {@link #setScrollContainer(boolean)}. 1387 */ 1388 static final int SCROLL_CONTAINER_ADDED = 0x00100000; 1389 1390 /** 1391 * The parent this view is attached to. 1392 * {@hide} 1393 * 1394 * @see #getParent() 1395 */ 1396 protected ViewParent mParent; 1397 1398 /** 1399 * {@hide} 1400 */ 1401 AttachInfo mAttachInfo; 1402 1403 /** 1404 * {@hide} 1405 */ 1406 @ViewDebug.ExportedProperty 1407 int mPrivateFlags; 1408 1409 /** 1410 * Count of how many windows this view has been attached to. 1411 */ 1412 int mWindowAttachCount; 1413 1414 /** 1415 * The layout parameters associated with this view and used by the parent 1416 * {@link android.view.ViewGroup} to determine how this view should be 1417 * laid out. 1418 * {@hide} 1419 */ 1420 protected ViewGroup.LayoutParams mLayoutParams; 1421 1422 /** 1423 * The view flags hold various views states. 1424 * {@hide} 1425 */ 1426 @ViewDebug.ExportedProperty 1427 int mViewFlags; 1428 1429 /** 1430 * The distance in pixels from the left edge of this view's parent 1431 * to the left edge of this view. 1432 * {@hide} 1433 */ 1434 @ViewDebug.ExportedProperty 1435 protected int mLeft; 1436 /** 1437 * The distance in pixels from the left edge of this view's parent 1438 * to the right edge of this view. 1439 * {@hide} 1440 */ 1441 @ViewDebug.ExportedProperty 1442 protected int mRight; 1443 /** 1444 * The distance in pixels from the top edge of this view's parent 1445 * to the top edge of this view. 1446 * {@hide} 1447 */ 1448 @ViewDebug.ExportedProperty 1449 protected int mTop; 1450 /** 1451 * The distance in pixels from the top edge of this view's parent 1452 * to the bottom edge of this view. 1453 * {@hide} 1454 */ 1455 @ViewDebug.ExportedProperty 1456 protected int mBottom; 1457 1458 /** 1459 * The offset, in pixels, by which the content of this view is scrolled 1460 * horizontally. 1461 * {@hide} 1462 */ 1463 @ViewDebug.ExportedProperty 1464 protected int mScrollX; 1465 /** 1466 * The offset, in pixels, by which the content of this view is scrolled 1467 * vertically. 1468 * {@hide} 1469 */ 1470 @ViewDebug.ExportedProperty 1471 protected int mScrollY; 1472 1473 /** 1474 * The left padding in pixels, that is the distance in pixels between the 1475 * left edge of this view and the left edge of its content. 1476 * {@hide} 1477 */ 1478 @ViewDebug.ExportedProperty 1479 protected int mPaddingLeft; 1480 /** 1481 * The right padding in pixels, that is the distance in pixels between the 1482 * right edge of this view and the right edge of its content. 1483 * {@hide} 1484 */ 1485 @ViewDebug.ExportedProperty 1486 protected int mPaddingRight; 1487 /** 1488 * The top padding in pixels, that is the distance in pixels between the 1489 * top edge of this view and the top edge of its content. 1490 * {@hide} 1491 */ 1492 @ViewDebug.ExportedProperty 1493 protected int mPaddingTop; 1494 /** 1495 * The bottom padding in pixels, that is the distance in pixels between the 1496 * bottom edge of this view and the bottom edge of its content. 1497 * {@hide} 1498 */ 1499 @ViewDebug.ExportedProperty 1500 protected int mPaddingBottom; 1501 1502 /** 1503 * Cache the paddingRight set by the user to append to the scrollbar's size. 1504 */ 1505 @ViewDebug.ExportedProperty 1506 int mUserPaddingRight; 1507 1508 /** 1509 * Cache the paddingBottom set by the user to append to the scrollbar's size. 1510 */ 1511 @ViewDebug.ExportedProperty 1512 int mUserPaddingBottom; 1513 1514 /** 1515 * @hide 1516 */ 1517 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 1518 /** 1519 * @hide 1520 */ 1521 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 1522 1523 private Resources mResources = null; 1524 1525 private Drawable mBGDrawable; 1526 1527 private int mBackgroundResource; 1528 private boolean mBackgroundSizeChanged; 1529 1530 /** 1531 * Listener used to dispatch focus change events. 1532 * This field should be made private, so it is hidden from the SDK. 1533 * {@hide} 1534 */ 1535 protected OnFocusChangeListener mOnFocusChangeListener; 1536 1537 /** 1538 * Listener used to dispatch click events. 1539 * This field should be made private, so it is hidden from the SDK. 1540 * {@hide} 1541 */ 1542 protected OnClickListener mOnClickListener; 1543 1544 /** 1545 * Listener used to dispatch long click events. 1546 * This field should be made private, so it is hidden from the SDK. 1547 * {@hide} 1548 */ 1549 protected OnLongClickListener mOnLongClickListener; 1550 1551 /** 1552 * Listener used to build the context menu. 1553 * This field should be made private, so it is hidden from the SDK. 1554 * {@hide} 1555 */ 1556 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 1557 1558 private OnKeyListener mOnKeyListener; 1559 1560 private OnTouchListener mOnTouchListener; 1561 1562 /** 1563 * The application environment this view lives in. 1564 * This field should be made private, so it is hidden from the SDK. 1565 * {@hide} 1566 */ 1567 protected Context mContext; 1568 1569 private ScrollabilityCache mScrollCache; 1570 1571 private int[] mDrawableState = null; 1572 1573 private SoftReference<Bitmap> mDrawingCache; 1574 1575 /** 1576 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 1577 * the user may specify which view to go to next. 1578 */ 1579 private int mNextFocusLeftId = View.NO_ID; 1580 1581 /** 1582 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 1583 * the user may specify which view to go to next. 1584 */ 1585 private int mNextFocusRightId = View.NO_ID; 1586 1587 /** 1588 * When this view has focus and the next focus is {@link #FOCUS_UP}, 1589 * the user may specify which view to go to next. 1590 */ 1591 private int mNextFocusUpId = View.NO_ID; 1592 1593 /** 1594 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 1595 * the user may specify which view to go to next. 1596 */ 1597 private int mNextFocusDownId = View.NO_ID; 1598 1599 private CheckForLongPress mPendingCheckForLongPress; 1600 private UnsetPressedState mUnsetPressedState; 1601 1602 /** 1603 * Whether the long press's action has been invoked. The tap's action is invoked on the 1604 * up event while a long press is invoked as soon as the long press duration is reached, so 1605 * a long press could be performed before the tap is checked, in which case the tap's action 1606 * should not be invoked. 1607 */ 1608 private boolean mHasPerformedLongPress; 1609 1610 /** 1611 * The minimum height of the view. We'll try our best to have the height 1612 * of this view to at least this amount. 1613 */ 1614 @ViewDebug.ExportedProperty 1615 private int mMinHeight; 1616 1617 /** 1618 * The minimum width of the view. We'll try our best to have the width 1619 * of this view to at least this amount. 1620 */ 1621 @ViewDebug.ExportedProperty 1622 private int mMinWidth; 1623 1624 /** 1625 * The delegate to handle touch events that are physically in this view 1626 * but should be handled by another view. 1627 */ 1628 private TouchDelegate mTouchDelegate = null; 1629 1630 /** 1631 * Solid color to use as a background when creating the drawing cache. Enables 1632 * the cache to use 16 bit bitmaps instead of 32 bit. 1633 */ 1634 private int mDrawingCacheBackgroundColor = 0; 1635 1636 /** 1637 * Special tree observer used when mAttachInfo is null. 1638 */ 1639 private ViewTreeObserver mFloatingTreeObserver; 1640 1641 // Used for debug only 1642 static long sInstanceCount = 0; 1643 1644 /** 1645 * Simple constructor to use when creating a view from code. 1646 * 1647 * @param context The Context the view is running in, through which it can 1648 * access the current theme, resources, etc. 1649 */ 1650 public View(Context context) { 1651 mContext = context; 1652 mResources = context != null ? context.getResources() : null; 1653 mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED; 1654 ++sInstanceCount; 1655 } 1656 1657 /** 1658 * Constructor that is called when inflating a view from XML. This is called 1659 * when a view is being constructed from an XML file, supplying attributes 1660 * that were specified in the XML file. This version uses a default style of 1661 * 0, so the only attribute values applied are those in the Context's Theme 1662 * and the given AttributeSet. 1663 * 1664 * <p> 1665 * The method onFinishInflate() will be called after all children have been 1666 * added. 1667 * 1668 * @param context The Context the view is running in, through which it can 1669 * access the current theme, resources, etc. 1670 * @param attrs The attributes of the XML tag that is inflating the view. 1671 * @see #View(Context, AttributeSet, int) 1672 */ 1673 public View(Context context, AttributeSet attrs) { 1674 this(context, attrs, 0); 1675 } 1676 1677 /** 1678 * Perform inflation from XML and apply a class-specific base style. This 1679 * constructor of View allows subclasses to use their own base style when 1680 * they are inflating. For example, a Button class's constructor would call 1681 * this version of the super class constructor and supply 1682 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows 1683 * the theme's button style to modify all of the base view attributes (in 1684 * particular its background) as well as the Button class's attributes. 1685 * 1686 * @param context The Context the view is running in, through which it can 1687 * access the current theme, resources, etc. 1688 * @param attrs The attributes of the XML tag that is inflating the view. 1689 * @param defStyle The default style to apply to this view. If 0, no style 1690 * will be applied (beyond what is included in the theme). This may 1691 * either be an attribute resource, whose value will be retrieved 1692 * from the current theme, or an explicit style resource. 1693 * @see #View(Context, AttributeSet) 1694 */ 1695 public View(Context context, AttributeSet attrs, int defStyle) { 1696 this(context); 1697 1698 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View, 1699 defStyle, 0); 1700 1701 Drawable background = null; 1702 1703 int leftPadding = -1; 1704 int topPadding = -1; 1705 int rightPadding = -1; 1706 int bottomPadding = -1; 1707 1708 int padding = -1; 1709 1710 int viewFlagValues = 0; 1711 int viewFlagMasks = 0; 1712 1713 boolean setScrollContainer = false; 1714 1715 int x = 0; 1716 int y = 0; 1717 1718 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 1719 1720 final int N = a.getIndexCount(); 1721 for (int i = 0; i < N; i++) { 1722 int attr = a.getIndex(i); 1723 switch (attr) { 1724 case com.android.internal.R.styleable.View_background: 1725 background = a.getDrawable(attr); 1726 break; 1727 case com.android.internal.R.styleable.View_padding: 1728 padding = a.getDimensionPixelSize(attr, -1); 1729 break; 1730 case com.android.internal.R.styleable.View_paddingLeft: 1731 leftPadding = a.getDimensionPixelSize(attr, -1); 1732 break; 1733 case com.android.internal.R.styleable.View_paddingTop: 1734 topPadding = a.getDimensionPixelSize(attr, -1); 1735 break; 1736 case com.android.internal.R.styleable.View_paddingRight: 1737 rightPadding = a.getDimensionPixelSize(attr, -1); 1738 break; 1739 case com.android.internal.R.styleable.View_paddingBottom: 1740 bottomPadding = a.getDimensionPixelSize(attr, -1); 1741 break; 1742 case com.android.internal.R.styleable.View_scrollX: 1743 x = a.getDimensionPixelOffset(attr, 0); 1744 break; 1745 case com.android.internal.R.styleable.View_scrollY: 1746 y = a.getDimensionPixelOffset(attr, 0); 1747 break; 1748 case com.android.internal.R.styleable.View_id: 1749 mID = a.getResourceId(attr, NO_ID); 1750 break; 1751 case com.android.internal.R.styleable.View_tag: 1752 mTag = a.getText(attr); 1753 break; 1754 case com.android.internal.R.styleable.View_fitsSystemWindows: 1755 if (a.getBoolean(attr, false)) { 1756 viewFlagValues |= FITS_SYSTEM_WINDOWS; 1757 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 1758 } 1759 break; 1760 case com.android.internal.R.styleable.View_focusable: 1761 if (a.getBoolean(attr, false)) { 1762 viewFlagValues |= FOCUSABLE; 1763 viewFlagMasks |= FOCUSABLE_MASK; 1764 } 1765 break; 1766 case com.android.internal.R.styleable.View_focusableInTouchMode: 1767 if (a.getBoolean(attr, false)) { 1768 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 1769 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 1770 } 1771 break; 1772 case com.android.internal.R.styleable.View_clickable: 1773 if (a.getBoolean(attr, false)) { 1774 viewFlagValues |= CLICKABLE; 1775 viewFlagMasks |= CLICKABLE; 1776 } 1777 break; 1778 case com.android.internal.R.styleable.View_longClickable: 1779 if (a.getBoolean(attr, false)) { 1780 viewFlagValues |= LONG_CLICKABLE; 1781 viewFlagMasks |= LONG_CLICKABLE; 1782 } 1783 break; 1784 case com.android.internal.R.styleable.View_saveEnabled: 1785 if (!a.getBoolean(attr, true)) { 1786 viewFlagValues |= SAVE_DISABLED; 1787 viewFlagMasks |= SAVE_DISABLED_MASK; 1788 } 1789 break; 1790 case com.android.internal.R.styleable.View_duplicateParentState: 1791 if (a.getBoolean(attr, false)) { 1792 viewFlagValues |= DUPLICATE_PARENT_STATE; 1793 viewFlagMasks |= DUPLICATE_PARENT_STATE; 1794 } 1795 break; 1796 case com.android.internal.R.styleable.View_visibility: 1797 final int visibility = a.getInt(attr, 0); 1798 if (visibility != 0) { 1799 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 1800 viewFlagMasks |= VISIBILITY_MASK; 1801 } 1802 break; 1803 case com.android.internal.R.styleable.View_drawingCacheQuality: 1804 final int cacheQuality = a.getInt(attr, 0); 1805 if (cacheQuality != 0) { 1806 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 1807 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 1808 } 1809 break; 1810 case com.android.internal.R.styleable.View_soundEffectsEnabled: 1811 if (!a.getBoolean(attr, true)) { 1812 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 1813 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 1814 } 1815 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 1816 if (!a.getBoolean(attr, true)) { 1817 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 1818 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 1819 } 1820 case R.styleable.View_scrollbars: 1821 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 1822 if (scrollbars != SCROLLBARS_NONE) { 1823 viewFlagValues |= scrollbars; 1824 viewFlagMasks |= SCROLLBARS_MASK; 1825 initializeScrollbars(a); 1826 } 1827 break; 1828 case R.styleable.View_fadingEdge: 1829 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 1830 if (fadingEdge != FADING_EDGE_NONE) { 1831 viewFlagValues |= fadingEdge; 1832 viewFlagMasks |= FADING_EDGE_MASK; 1833 initializeFadingEdge(a); 1834 } 1835 break; 1836 case R.styleable.View_scrollbarStyle: 1837 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 1838 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 1839 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 1840 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 1841 } 1842 break; 1843 case R.styleable.View_isScrollContainer: 1844 setScrollContainer = true; 1845 if (a.getBoolean(attr, false)) { 1846 setScrollContainer(true); 1847 } 1848 break; 1849 case com.android.internal.R.styleable.View_keepScreenOn: 1850 if (a.getBoolean(attr, false)) { 1851 viewFlagValues |= KEEP_SCREEN_ON; 1852 viewFlagMasks |= KEEP_SCREEN_ON; 1853 } 1854 break; 1855 case R.styleable.View_nextFocusLeft: 1856 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 1857 break; 1858 case R.styleable.View_nextFocusRight: 1859 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 1860 break; 1861 case R.styleable.View_nextFocusUp: 1862 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 1863 break; 1864 case R.styleable.View_nextFocusDown: 1865 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 1866 break; 1867 case R.styleable.View_minWidth: 1868 mMinWidth = a.getDimensionPixelSize(attr, 0); 1869 break; 1870 case R.styleable.View_minHeight: 1871 mMinHeight = a.getDimensionPixelSize(attr, 0); 1872 break; 1873 } 1874 } 1875 1876 if (background != null) { 1877 setBackgroundDrawable(background); 1878 } 1879 1880 if (padding >= 0) { 1881 leftPadding = padding; 1882 topPadding = padding; 1883 rightPadding = padding; 1884 bottomPadding = padding; 1885 } 1886 1887 // If the user specified the padding (either with android:padding or 1888 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise 1889 // use the default padding or the padding from the background drawable 1890 // (stored at this point in mPadding*) 1891 setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft, 1892 topPadding >= 0 ? topPadding : mPaddingTop, 1893 rightPadding >= 0 ? rightPadding : mPaddingRight, 1894 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 1895 1896 if (viewFlagMasks != 0) { 1897 setFlags(viewFlagValues, viewFlagMasks); 1898 } 1899 1900 // Needs to be called after mViewFlags is set 1901 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 1902 recomputePadding(); 1903 } 1904 1905 if (x != 0 || y != 0) { 1906 scrollTo(x, y); 1907 } 1908 1909 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 1910 setScrollContainer(true); 1911 } 1912 1913 a.recycle(); 1914 } 1915 1916 /** 1917 * Non-public constructor for use in testing 1918 */ 1919 View() { 1920 } 1921 1922 @Override 1923 protected void finalize() throws Throwable { 1924 super.finalize(); 1925 --sInstanceCount; 1926 } 1927 1928 /** 1929 * <p> 1930 * Initializes the fading edges from a given set of styled attributes. This 1931 * method should be called by subclasses that need fading edges and when an 1932 * instance of these subclasses is created programmatically rather than 1933 * being inflated from XML. This method is automatically called when the XML 1934 * is inflated. 1935 * </p> 1936 * 1937 * @param a the styled attributes set to initialize the fading edges from 1938 */ 1939 protected void initializeFadingEdge(TypedArray a) { 1940 initScrollCache(); 1941 1942 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 1943 R.styleable.View_fadingEdgeLength, 1944 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 1945 } 1946 1947 /** 1948 * Returns the size of the vertical faded edges used to indicate that more 1949 * content in this view is visible. 1950 * 1951 * @return The size in pixels of the vertical faded edge or 0 if vertical 1952 * faded edges are not enabled for this view. 1953 * @attr ref android.R.styleable#View_fadingEdgeLength 1954 */ 1955 public int getVerticalFadingEdgeLength() { 1956 if (isVerticalFadingEdgeEnabled()) { 1957 ScrollabilityCache cache = mScrollCache; 1958 if (cache != null) { 1959 return cache.fadingEdgeLength; 1960 } 1961 } 1962 return 0; 1963 } 1964 1965 /** 1966 * Set the size of the faded edge used to indicate that more content in this 1967 * view is available. Will not change whether the fading edge is enabled; use 1968 * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled} 1969 * to enable the fading edge for the vertical or horizontal fading edges. 1970 * 1971 * @param length The size in pixels of the faded edge used to indicate that more 1972 * content in this view is visible. 1973 */ 1974 public void setFadingEdgeLength(int length) { 1975 initScrollCache(); 1976 mScrollCache.fadingEdgeLength = length; 1977 } 1978 1979 /** 1980 * Returns the size of the horizontal faded edges used to indicate that more 1981 * content in this view is visible. 1982 * 1983 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 1984 * faded edges are not enabled for this view. 1985 * @attr ref android.R.styleable#View_fadingEdgeLength 1986 */ 1987 public int getHorizontalFadingEdgeLength() { 1988 if (isHorizontalFadingEdgeEnabled()) { 1989 ScrollabilityCache cache = mScrollCache; 1990 if (cache != null) { 1991 return cache.fadingEdgeLength; 1992 } 1993 } 1994 return 0; 1995 } 1996 1997 /** 1998 * Returns the width of the vertical scrollbar. 1999 * 2000 * @return The width in pixels of the vertical scrollbar or 0 if there 2001 * is no vertical scrollbar. 2002 */ 2003 public int getVerticalScrollbarWidth() { 2004 ScrollabilityCache cache = mScrollCache; 2005 if (cache != null) { 2006 ScrollBarDrawable scrollBar = cache.scrollBar; 2007 if (scrollBar != null) { 2008 int size = scrollBar.getSize(true); 2009 if (size <= 0) { 2010 size = cache.scrollBarSize; 2011 } 2012 return size; 2013 } 2014 return 0; 2015 } 2016 return 0; 2017 } 2018 2019 /** 2020 * Returns the height of the horizontal scrollbar. 2021 * 2022 * @return The height in pixels of the horizontal scrollbar or 0 if 2023 * there is no horizontal scrollbar. 2024 */ 2025 protected int getHorizontalScrollbarHeight() { 2026 ScrollabilityCache cache = mScrollCache; 2027 if (cache != null) { 2028 ScrollBarDrawable scrollBar = cache.scrollBar; 2029 if (scrollBar != null) { 2030 int size = scrollBar.getSize(false); 2031 if (size <= 0) { 2032 size = cache.scrollBarSize; 2033 } 2034 return size; 2035 } 2036 return 0; 2037 } 2038 return 0; 2039 } 2040 2041 /** 2042 * <p> 2043 * Initializes the scrollbars from a given set of styled attributes. This 2044 * method should be called by subclasses that need scrollbars and when an 2045 * instance of these subclasses is created programmatically rather than 2046 * being inflated from XML. This method is automatically called when the XML 2047 * is inflated. 2048 * </p> 2049 * 2050 * @param a the styled attributes set to initialize the scrollbars from 2051 */ 2052 protected void initializeScrollbars(TypedArray a) { 2053 initScrollCache(); 2054 2055 if (mScrollCache.scrollBar == null) { 2056 mScrollCache.scrollBar = new ScrollBarDrawable(); 2057 } 2058 2059 final ScrollabilityCache scrollabilityCache = mScrollCache; 2060 2061 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 2062 com.android.internal.R.styleable.View_scrollbarSize, 2063 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 2064 2065 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 2066 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 2067 2068 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 2069 if (thumb != null) { 2070 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 2071 } 2072 2073 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 2074 false); 2075 if (alwaysDraw) { 2076 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 2077 } 2078 2079 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 2080 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 2081 2082 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 2083 if (thumb != null) { 2084 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 2085 } 2086 2087 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 2088 false); 2089 if (alwaysDraw) { 2090 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 2091 } 2092 2093 // Re-apply user/background padding so that scrollbar(s) get added 2094 recomputePadding(); 2095 } 2096 2097 /** 2098 * <p> 2099 * Initalizes the scrollability cache if necessary. 2100 * </p> 2101 */ 2102 private void initScrollCache() { 2103 if (mScrollCache == null) { 2104 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext)); 2105 } 2106 } 2107 2108 /** 2109 * Register a callback to be invoked when focus of this view changed. 2110 * 2111 * @param l The callback that will run. 2112 */ 2113 public void setOnFocusChangeListener(OnFocusChangeListener l) { 2114 mOnFocusChangeListener = l; 2115 } 2116 2117 /** 2118 * Returns the focus-change callback registered for this view. 2119 * 2120 * @return The callback, or null if one is not registered. 2121 */ 2122 public OnFocusChangeListener getOnFocusChangeListener() { 2123 return mOnFocusChangeListener; 2124 } 2125 2126 /** 2127 * Register a callback to be invoked when this view is clicked. If this view is not 2128 * clickable, it becomes clickable. 2129 * 2130 * @param l The callback that will run 2131 * 2132 * @see #setClickable(boolean) 2133 */ 2134 public void setOnClickListener(OnClickListener l) { 2135 if (!isClickable()) { 2136 setClickable(true); 2137 } 2138 mOnClickListener = l; 2139 } 2140 2141 /** 2142 * Register a callback to be invoked when this view is clicked and held. If this view is not 2143 * long clickable, it becomes long clickable. 2144 * 2145 * @param l The callback that will run 2146 * 2147 * @see #setLongClickable(boolean) 2148 */ 2149 public void setOnLongClickListener(OnLongClickListener l) { 2150 if (!isLongClickable()) { 2151 setLongClickable(true); 2152 } 2153 mOnLongClickListener = l; 2154 } 2155 2156 /** 2157 * Register a callback to be invoked when the context menu for this view is 2158 * being built. If this view is not long clickable, it becomes long clickable. 2159 * 2160 * @param l The callback that will run 2161 * 2162 */ 2163 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 2164 if (!isLongClickable()) { 2165 setLongClickable(true); 2166 } 2167 mOnCreateContextMenuListener = l; 2168 } 2169 2170 /** 2171 * Call this view's OnClickListener, if it is defined. 2172 * 2173 * @return True there was an assigned OnClickListener that was called, false 2174 * otherwise is returned. 2175 */ 2176 public boolean performClick() { 2177 if (mOnClickListener != null) { 2178 playSoundEffect(SoundEffectConstants.CLICK); 2179 mOnClickListener.onClick(this); 2180 return true; 2181 } 2182 2183 return false; 2184 } 2185 2186 /** 2187 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu 2188 * if the OnLongClickListener did not consume the event. 2189 * 2190 * @return True there was an assigned OnLongClickListener that was called, false 2191 * otherwise is returned. 2192 */ 2193 public boolean performLongClick() { 2194 boolean handled = false; 2195 if (mOnLongClickListener != null) { 2196 handled = mOnLongClickListener.onLongClick(View.this); 2197 } 2198 if (!handled) { 2199 handled = showContextMenu(); 2200 } 2201 if (handled) { 2202 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 2203 } 2204 return handled; 2205 } 2206 2207 /** 2208 * Bring up the context menu for this view. 2209 * 2210 * @return Whether a context menu was displayed. 2211 */ 2212 public boolean showContextMenu() { 2213 return getParent().showContextMenuForChild(this); 2214 } 2215 2216 /** 2217 * Register a callback to be invoked when a key is pressed in this view. 2218 * @param l the key listener to attach to this view 2219 */ 2220 public void setOnKeyListener(OnKeyListener l) { 2221 mOnKeyListener = l; 2222 } 2223 2224 /** 2225 * Register a callback to be invoked when a touch event is sent to this view. 2226 * @param l the touch listener to attach to this view 2227 */ 2228 public void setOnTouchListener(OnTouchListener l) { 2229 mOnTouchListener = l; 2230 } 2231 2232 /** 2233 * Give this view focus. This will cause {@link #onFocusChanged} to be called. 2234 * 2235 * Note: this does not check whether this {@link View} should get focus, it just 2236 * gives it focus no matter what. It should only be called internally by framework 2237 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 2238 * 2239 * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN, 2240 * View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which 2241 * focus moved when requestFocus() is called. It may not always 2242 * apply, in which case use the default View.FOCUS_DOWN. 2243 * @param previouslyFocusedRect The rectangle of the view that had focus 2244 * prior in this View's coordinate system. 2245 */ 2246 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) { 2247 if (DBG) { 2248 System.out.println(this + " requestFocus()"); 2249 } 2250 2251 if ((mPrivateFlags & FOCUSED) == 0) { 2252 mPrivateFlags |= FOCUSED; 2253 2254 if (mParent != null) { 2255 mParent.requestChildFocus(this, this); 2256 } 2257 2258 onFocusChanged(true, direction, previouslyFocusedRect); 2259 refreshDrawableState(); 2260 } 2261 } 2262 2263 /** 2264 * Request that a rectangle of this view be visible on the screen, 2265 * scrolling if necessary just enough. 2266 * 2267 * <p>A View should call this if it maintains some notion of which part 2268 * of its content is interesting. For example, a text editing view 2269 * should call this when its cursor moves. 2270 * 2271 * @param rectangle The rectangle. 2272 * @return Whether any parent scrolled. 2273 */ 2274 public boolean requestRectangleOnScreen(Rect rectangle) { 2275 return requestRectangleOnScreen(rectangle, false); 2276 } 2277 2278 /** 2279 * Request that a rectangle of this view be visible on the screen, 2280 * scrolling if necessary just enough. 2281 * 2282 * <p>A View should call this if it maintains some notion of which part 2283 * of its content is interesting. For example, a text editing view 2284 * should call this when its cursor moves. 2285 * 2286 * <p>When <code>immediate</code> is set to true, scrolling will not be 2287 * animated. 2288 * 2289 * @param rectangle The rectangle. 2290 * @param immediate True to forbid animated scrolling, false otherwise 2291 * @return Whether any parent scrolled. 2292 */ 2293 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 2294 View child = this; 2295 ViewParent parent = mParent; 2296 boolean scrolled = false; 2297 while (parent != null) { 2298 scrolled |= parent.requestChildRectangleOnScreen(child, 2299 rectangle, immediate); 2300 2301 // offset rect so next call has the rectangle in the 2302 // coordinate system of its direct child. 2303 rectangle.offset(child.getLeft(), child.getTop()); 2304 rectangle.offset(-child.getScrollX(), -child.getScrollY()); 2305 2306 if (!(parent instanceof View)) { 2307 break; 2308 } 2309 2310 child = (View) parent; 2311 parent = child.getParent(); 2312 } 2313 return scrolled; 2314 } 2315 2316 /** 2317 * Called when this view wants to give up focus. This will cause 2318 * {@link #onFocusChanged} to be called. 2319 */ 2320 public void clearFocus() { 2321 if (DBG) { 2322 System.out.println(this + " clearFocus()"); 2323 } 2324 2325 if ((mPrivateFlags & FOCUSED) != 0) { 2326 mPrivateFlags &= ~FOCUSED; 2327 2328 if (mParent != null) { 2329 mParent.clearChildFocus(this); 2330 } 2331 2332 onFocusChanged(false, 0, null); 2333 refreshDrawableState(); 2334 } 2335 } 2336 2337 /** 2338 * Called to clear the focus of a view that is about to be removed. 2339 * Doesn't call clearChildFocus, which prevents this view from taking 2340 * focus again before it has been removed from the parent 2341 */ 2342 void clearFocusForRemoval() { 2343 if ((mPrivateFlags & FOCUSED) != 0) { 2344 mPrivateFlags &= ~FOCUSED; 2345 2346 onFocusChanged(false, 0, null); 2347 refreshDrawableState(); 2348 } 2349 } 2350 2351 /** 2352 * Called internally by the view system when a new view is getting focus. 2353 * This is what clears the old focus. 2354 */ 2355 void unFocus() { 2356 if (DBG) { 2357 System.out.println(this + " unFocus()"); 2358 } 2359 2360 if ((mPrivateFlags & FOCUSED) != 0) { 2361 mPrivateFlags &= ~FOCUSED; 2362 2363 onFocusChanged(false, 0, null); 2364 refreshDrawableState(); 2365 } 2366 } 2367 2368 /** 2369 * Returns true if this view has focus iteself, or is the ancestor of the 2370 * view that has focus. 2371 * 2372 * @return True if this view has or contains focus, false otherwise. 2373 */ 2374 @ViewDebug.ExportedProperty 2375 public boolean hasFocus() { 2376 return (mPrivateFlags & FOCUSED) != 0; 2377 } 2378 2379 /** 2380 * Returns true if this view is focusable or if it contains a reachable View 2381 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 2382 * is a View whose parents do not block descendants focus. 2383 * 2384 * Only {@link #VISIBLE} views are considered focusable. 2385 * 2386 * @return True if the view is focusable or if the view contains a focusable 2387 * View, false otherwise. 2388 * 2389 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 2390 */ 2391 public boolean hasFocusable() { 2392 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 2393 } 2394 2395 /** 2396 * Called by the view system when the focus state of this view changes. 2397 * When the focus change event is caused by directional navigation, direction 2398 * and previouslyFocusedRect provide insight into where the focus is coming from. 2399 * When overriding, be sure to call up through to the super class so that 2400 * the standard focus handling will occur. 2401 * 2402 * @param gainFocus True if the View has focus; false otherwise. 2403 * @param direction The direction focus has moved when requestFocus() 2404 * is called to give this view focus. Values are 2405 * View.FOCUS_UP, View.FOCUS_DOWN, View.FOCUS_LEFT or 2406 * View.FOCUS_RIGHT. It may not always apply, in which 2407 * case use the default. 2408 * @param previouslyFocusedRect The rectangle, in this view's coordinate 2409 * system, of the previously focused view. If applicable, this will be 2410 * passed in as finer grained information about where the focus is coming 2411 * from (in addition to direction). Will be <code>null</code> otherwise. 2412 */ 2413 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 2414 InputMethodManager imm = InputMethodManager.peekInstance(); 2415 if (!gainFocus) { 2416 if (isPressed()) { 2417 setPressed(false); 2418 } 2419 if (imm != null && mAttachInfo != null 2420 && mAttachInfo.mHasWindowFocus) { 2421 imm.focusOut(this); 2422 } 2423 } else if (imm != null && mAttachInfo != null 2424 && mAttachInfo.mHasWindowFocus) { 2425 imm.focusIn(this); 2426 } 2427 2428 invalidate(); 2429 if (mOnFocusChangeListener != null) { 2430 mOnFocusChangeListener.onFocusChange(this, gainFocus); 2431 } 2432 } 2433 2434 /** 2435 * Returns true if this view has focus 2436 * 2437 * @return True if this view has focus, false otherwise. 2438 */ 2439 @ViewDebug.ExportedProperty 2440 public boolean isFocused() { 2441 return (mPrivateFlags & FOCUSED) != 0; 2442 } 2443 2444 /** 2445 * Find the view in the hierarchy rooted at this view that currently has 2446 * focus. 2447 * 2448 * @return The view that currently has focus, or null if no focused view can 2449 * be found. 2450 */ 2451 public View findFocus() { 2452 return (mPrivateFlags & FOCUSED) != 0 ? this : null; 2453 } 2454 2455 /** 2456 * Change whether this view is one of the set of scrollable containers in 2457 * its window. This will be used to determine whether the window can 2458 * resize or must pan when a soft input area is open -- scrollable 2459 * containers allow the window to use resize mode since the container 2460 * will appropriately shrink. 2461 */ 2462 public void setScrollContainer(boolean isScrollContainer) { 2463 if (isScrollContainer) { 2464 if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) { 2465 mAttachInfo.mScrollContainers.add(this); 2466 mPrivateFlags |= SCROLL_CONTAINER_ADDED; 2467 } 2468 mPrivateFlags |= SCROLL_CONTAINER; 2469 } else { 2470 if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { 2471 mAttachInfo.mScrollContainers.remove(this); 2472 } 2473 mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED); 2474 } 2475 } 2476 2477 /** 2478 * Returns the quality of the drawing cache. 2479 * 2480 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 2481 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 2482 * 2483 * @see #setDrawingCacheQuality(int) 2484 * @see #setDrawingCacheEnabled(boolean) 2485 * @see #isDrawingCacheEnabled() 2486 * 2487 * @attr ref android.R.styleable#View_drawingCacheQuality 2488 */ 2489 public int getDrawingCacheQuality() { 2490 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 2491 } 2492 2493 /** 2494 * Set the drawing cache quality of this view. This value is used only when the 2495 * drawing cache is enabled 2496 * 2497 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 2498 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 2499 * 2500 * @see #getDrawingCacheQuality() 2501 * @see #setDrawingCacheEnabled(boolean) 2502 * @see #isDrawingCacheEnabled() 2503 * 2504 * @attr ref android.R.styleable#View_drawingCacheQuality 2505 */ 2506 public void setDrawingCacheQuality(int quality) { 2507 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 2508 } 2509 2510 /** 2511 * Returns whether the screen should remain on, corresponding to the current 2512 * value of {@link #KEEP_SCREEN_ON}. 2513 * 2514 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 2515 * 2516 * @see #setKeepScreenOn(boolean) 2517 * 2518 * @attr ref android.R.styleable#View_keepScreenOn 2519 */ 2520 public boolean getKeepScreenOn() { 2521 return (mViewFlags & KEEP_SCREEN_ON) != 0; 2522 } 2523 2524 /** 2525 * Controls whether the screen should remain on, modifying the 2526 * value of {@link #KEEP_SCREEN_ON}. 2527 * 2528 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 2529 * 2530 * @see #getKeepScreenOn() 2531 * 2532 * @attr ref android.R.styleable#View_keepScreenOn 2533 */ 2534 public void setKeepScreenOn(boolean keepScreenOn) { 2535 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 2536 } 2537 2538 /** 2539 * @return The user specified next focus ID. 2540 * 2541 * @attr ref android.R.styleable#View_nextFocusLeft 2542 */ 2543 public int getNextFocusLeftId() { 2544 return mNextFocusLeftId; 2545 } 2546 2547 /** 2548 * Set the id of the view to use for the next focus 2549 * 2550 * @param nextFocusLeftId 2551 * 2552 * @attr ref android.R.styleable#View_nextFocusLeft 2553 */ 2554 public void setNextFocusLeftId(int nextFocusLeftId) { 2555 mNextFocusLeftId = nextFocusLeftId; 2556 } 2557 2558 /** 2559 * @return The user specified next focus ID. 2560 * 2561 * @attr ref android.R.styleable#View_nextFocusRight 2562 */ 2563 public int getNextFocusRightId() { 2564 return mNextFocusRightId; 2565 } 2566 2567 /** 2568 * Set the id of the view to use for the next focus 2569 * 2570 * @param nextFocusRightId 2571 * 2572 * @attr ref android.R.styleable#View_nextFocusRight 2573 */ 2574 public void setNextFocusRightId(int nextFocusRightId) { 2575 mNextFocusRightId = nextFocusRightId; 2576 } 2577 2578 /** 2579 * @return The user specified next focus ID. 2580 * 2581 * @attr ref android.R.styleable#View_nextFocusUp 2582 */ 2583 public int getNextFocusUpId() { 2584 return mNextFocusUpId; 2585 } 2586 2587 /** 2588 * Set the id of the view to use for the next focus 2589 * 2590 * @param nextFocusUpId 2591 * 2592 * @attr ref android.R.styleable#View_nextFocusUp 2593 */ 2594 public void setNextFocusUpId(int nextFocusUpId) { 2595 mNextFocusUpId = nextFocusUpId; 2596 } 2597 2598 /** 2599 * @return The user specified next focus ID. 2600 * 2601 * @attr ref android.R.styleable#View_nextFocusDown 2602 */ 2603 public int getNextFocusDownId() { 2604 return mNextFocusDownId; 2605 } 2606 2607 /** 2608 * Set the id of the view to use for the next focus 2609 * 2610 * @param nextFocusDownId 2611 * 2612 * @attr ref android.R.styleable#View_nextFocusDown 2613 */ 2614 public void setNextFocusDownId(int nextFocusDownId) { 2615 mNextFocusDownId = nextFocusDownId; 2616 } 2617 2618 /** 2619 * Returns the visibility of this view and all of its ancestors 2620 * 2621 * @return True if this view and all of its ancestors are {@link #VISIBLE} 2622 */ 2623 public boolean isShown() { 2624 View current = this; 2625 //noinspection ConstantConditions 2626 do { 2627 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 2628 return false; 2629 } 2630 ViewParent parent = current.mParent; 2631 if (parent == null) { 2632 return false; // We are not attached to the view root 2633 } 2634 if (!(parent instanceof View)) { 2635 return true; 2636 } 2637 current = (View) parent; 2638 } while (current != null); 2639 2640 return false; 2641 } 2642 2643 /** 2644 * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag 2645 * is set 2646 * 2647 * @param insets Insets for system windows 2648 * 2649 * @return True if this view applied the insets, false otherwise 2650 */ 2651 protected boolean fitSystemWindows(Rect insets) { 2652 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 2653 mPaddingLeft = insets.left; 2654 mPaddingTop = insets.top; 2655 mPaddingRight = insets.right; 2656 mPaddingBottom = insets.bottom; 2657 requestLayout(); 2658 return true; 2659 } 2660 return false; 2661 } 2662 2663 /** 2664 * Returns the visibility status for this view. 2665 * 2666 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 2667 * @attr ref android.R.styleable#View_visibility 2668 */ 2669 @ViewDebug.ExportedProperty(mapping = { 2670 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 2671 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 2672 @ViewDebug.IntToString(from = GONE, to = "GONE") 2673 }) 2674 public int getVisibility() { 2675 return mViewFlags & VISIBILITY_MASK; 2676 } 2677 2678 /** 2679 * Set the enabled state of this view. 2680 * 2681 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 2682 * @attr ref android.R.styleable#View_visibility 2683 */ 2684 @RemotableViewMethod 2685 public void setVisibility(int visibility) { 2686 setFlags(visibility, VISIBILITY_MASK); 2687 if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false); 2688 } 2689 2690 /** 2691 * Returns the enabled status for this view. The interpretation of the 2692 * enabled state varies by subclass. 2693 * 2694 * @return True if this view is enabled, false otherwise. 2695 */ 2696 @ViewDebug.ExportedProperty 2697 public boolean isEnabled() { 2698 return (mViewFlags & ENABLED_MASK) == ENABLED; 2699 } 2700 2701 /** 2702 * Set the enabled state of this view. The interpretation of the enabled 2703 * state varies by subclass. 2704 * 2705 * @param enabled True if this view is enabled, false otherwise. 2706 */ 2707 public void setEnabled(boolean enabled) { 2708 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 2709 2710 /* 2711 * The View most likely has to change its appearance, so refresh 2712 * the drawable state. 2713 */ 2714 refreshDrawableState(); 2715 2716 // Invalidate too, since the default behavior for views is to be 2717 // be drawn at 50% alpha rather than to change the drawable. 2718 invalidate(); 2719 } 2720 2721 /** 2722 * Set whether this view can receive the focus. 2723 * 2724 * Setting this to false will also ensure that this view is not focusable 2725 * in touch mode. 2726 * 2727 * @param focusable If true, this view can receive the focus. 2728 * 2729 * @see #setFocusableInTouchMode(boolean) 2730 * @attr ref android.R.styleable#View_focusable 2731 */ 2732 public void setFocusable(boolean focusable) { 2733 if (!focusable) { 2734 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 2735 } 2736 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 2737 } 2738 2739 /** 2740 * Set whether this view can receive focus while in touch mode. 2741 * 2742 * Setting this to true will also ensure that this view is focusable. 2743 * 2744 * @param focusableInTouchMode If true, this view can receive the focus while 2745 * in touch mode. 2746 * 2747 * @see #setFocusable(boolean) 2748 * @attr ref android.R.styleable#View_focusableInTouchMode 2749 */ 2750 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 2751 // Focusable in touch mode should always be set before the focusable flag 2752 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 2753 // which, in touch mode, will not successfully request focus on this view 2754 // because the focusable in touch mode flag is not set 2755 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 2756 if (focusableInTouchMode) { 2757 setFlags(FOCUSABLE, FOCUSABLE_MASK); 2758 } 2759 } 2760 2761 /** 2762 * Set whether this view should have sound effects enabled for events such as 2763 * clicking and touching. 2764 * 2765 * <p>You may wish to disable sound effects for a view if you already play sounds, 2766 * for instance, a dial key that plays dtmf tones. 2767 * 2768 * @param soundEffectsEnabled whether sound effects are enabled for this view. 2769 * @see #isSoundEffectsEnabled() 2770 * @see #playSoundEffect(int) 2771 * @attr ref android.R.styleable#View_soundEffectsEnabled 2772 */ 2773 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 2774 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 2775 } 2776 2777 /** 2778 * @return whether this view should have sound effects enabled for events such as 2779 * clicking and touching. 2780 * 2781 * @see #setSoundEffectsEnabled(boolean) 2782 * @see #playSoundEffect(int) 2783 * @attr ref android.R.styleable#View_soundEffectsEnabled 2784 */ 2785 @ViewDebug.ExportedProperty 2786 public boolean isSoundEffectsEnabled() { 2787 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 2788 } 2789 2790 /** 2791 * Set whether this view should have haptic feedback for events such as 2792 * long presses. 2793 * 2794 * <p>You may wish to disable haptic feedback if your view already controls 2795 * its own haptic feedback. 2796 * 2797 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 2798 * @see #isHapticFeedbackEnabled() 2799 * @see #performHapticFeedback(int) 2800 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 2801 */ 2802 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 2803 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 2804 } 2805 2806 /** 2807 * @return whether this view should have haptic feedback enabled for events 2808 * long presses. 2809 * 2810 * @see #setHapticFeedbackEnabled(boolean) 2811 * @see #performHapticFeedback(int) 2812 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 2813 */ 2814 @ViewDebug.ExportedProperty 2815 public boolean isHapticFeedbackEnabled() { 2816 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 2817 } 2818 2819 /** 2820 * If this view doesn't do any drawing on its own, set this flag to 2821 * allow further optimizations. By default, this flag is not set on 2822 * View, but could be set on some View subclasses such as ViewGroup. 2823 * 2824 * Typically, if you override {@link #onDraw} you should clear this flag. 2825 * 2826 * @param willNotDraw whether or not this View draw on its own 2827 */ 2828 public void setWillNotDraw(boolean willNotDraw) { 2829 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 2830 } 2831 2832 /** 2833 * Returns whether or not this View draws on its own. 2834 * 2835 * @return true if this view has nothing to draw, false otherwise 2836 */ 2837 @ViewDebug.ExportedProperty 2838 public boolean willNotDraw() { 2839 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 2840 } 2841 2842 /** 2843 * When a View's drawing cache is enabled, drawing is redirected to an 2844 * offscreen bitmap. Some views, like an ImageView, must be able to 2845 * bypass this mechanism if they already draw a single bitmap, to avoid 2846 * unnecessary usage of the memory. 2847 * 2848 * @param willNotCacheDrawing true if this view does not cache its 2849 * drawing, false otherwise 2850 */ 2851 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 2852 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 2853 } 2854 2855 /** 2856 * Returns whether or not this View can cache its drawing or not. 2857 * 2858 * @return true if this view does not cache its drawing, false otherwise 2859 */ 2860 @ViewDebug.ExportedProperty 2861 public boolean willNotCacheDrawing() { 2862 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 2863 } 2864 2865 /** 2866 * Indicates whether this view reacts to click events or not. 2867 * 2868 * @return true if the view is clickable, false otherwise 2869 * 2870 * @see #setClickable(boolean) 2871 * @attr ref android.R.styleable#View_clickable 2872 */ 2873 @ViewDebug.ExportedProperty 2874 public boolean isClickable() { 2875 return (mViewFlags & CLICKABLE) == CLICKABLE; 2876 } 2877 2878 /** 2879 * Enables or disables click events for this view. When a view 2880 * is clickable it will change its state to "pressed" on every click. 2881 * Subclasses should set the view clickable to visually react to 2882 * user's clicks. 2883 * 2884 * @param clickable true to make the view clickable, false otherwise 2885 * 2886 * @see #isClickable() 2887 * @attr ref android.R.styleable#View_clickable 2888 */ 2889 public void setClickable(boolean clickable) { 2890 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 2891 } 2892 2893 /** 2894 * Indicates whether this view reacts to long click events or not. 2895 * 2896 * @return true if the view is long clickable, false otherwise 2897 * 2898 * @see #setLongClickable(boolean) 2899 * @attr ref android.R.styleable#View_longClickable 2900 */ 2901 public boolean isLongClickable() { 2902 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 2903 } 2904 2905 /** 2906 * Enables or disables long click events for this view. When a view is long 2907 * clickable it reacts to the user holding down the button for a longer 2908 * duration than a tap. This event can either launch the listener or a 2909 * context menu. 2910 * 2911 * @param longClickable true to make the view long clickable, false otherwise 2912 * @see #isLongClickable() 2913 * @attr ref android.R.styleable#View_longClickable 2914 */ 2915 public void setLongClickable(boolean longClickable) { 2916 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 2917 } 2918 2919 /** 2920 * Sets the pressed that for this view. 2921 * 2922 * @see #isClickable() 2923 * @see #setClickable(boolean) 2924 * 2925 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 2926 * the View's internal state from a previously set "pressed" state. 2927 */ 2928 public void setPressed(boolean pressed) { 2929 if (pressed) { 2930 mPrivateFlags |= PRESSED; 2931 } else { 2932 mPrivateFlags &= ~PRESSED; 2933 } 2934 refreshDrawableState(); 2935 dispatchSetPressed(pressed); 2936 } 2937 2938 /** 2939 * Dispatch setPressed to all of this View's children. 2940 * 2941 * @see #setPressed(boolean) 2942 * 2943 * @param pressed The new pressed state 2944 */ 2945 protected void dispatchSetPressed(boolean pressed) { 2946 } 2947 2948 /** 2949 * Indicates whether the view is currently in pressed state. Unless 2950 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 2951 * the pressed state. 2952 * 2953 * @see #setPressed 2954 * @see #isClickable() 2955 * @see #setClickable(boolean) 2956 * 2957 * @return true if the view is currently pressed, false otherwise 2958 */ 2959 public boolean isPressed() { 2960 return (mPrivateFlags & PRESSED) == PRESSED; 2961 } 2962 2963 /** 2964 * Indicates whether this view will save its state (that is, 2965 * whether its {@link #onSaveInstanceState} method will be called). 2966 * 2967 * @return Returns true if the view state saving is enabled, else false. 2968 * 2969 * @see #setSaveEnabled(boolean) 2970 * @attr ref android.R.styleable#View_saveEnabled 2971 */ 2972 public boolean isSaveEnabled() { 2973 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 2974 } 2975 2976 /** 2977 * Controls whether the saving of this view's state is 2978 * enabled (that is, whether its {@link #onSaveInstanceState} method 2979 * will be called). Note that even if freezing is enabled, the 2980 * view still must have an id assigned to it (via {@link #setId setId()}) 2981 * for its state to be saved. This flag can only disable the 2982 * saving of this view; any child views may still have their state saved. 2983 * 2984 * @param enabled Set to false to <em>disable</em> state saving, or true 2985 * (the default) to allow it. 2986 * 2987 * @see #isSaveEnabled() 2988 * @see #setId(int) 2989 * @see #onSaveInstanceState() 2990 * @attr ref android.R.styleable#View_saveEnabled 2991 */ 2992 public void setSaveEnabled(boolean enabled) { 2993 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 2994 } 2995 2996 2997 /** 2998 * Returns whether this View is able to take focus. 2999 * 3000 * @return True if this view can take focus, or false otherwise. 3001 * @attr ref android.R.styleable#View_focusable 3002 */ 3003 @ViewDebug.ExportedProperty 3004 public final boolean isFocusable() { 3005 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 3006 } 3007 3008 /** 3009 * When a view is focusable, it may not want to take focus when in touch mode. 3010 * For example, a button would like focus when the user is navigating via a D-pad 3011 * so that the user can click on it, but once the user starts touching the screen, 3012 * the button shouldn't take focus 3013 * @return Whether the view is focusable in touch mode. 3014 * @attr ref android.R.styleable#View_focusableInTouchMode 3015 */ 3016 @ViewDebug.ExportedProperty 3017 public final boolean isFocusableInTouchMode() { 3018 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 3019 } 3020 3021 /** 3022 * Find the nearest view in the specified direction that can take focus. 3023 * This does not actually give focus to that view. 3024 * 3025 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 3026 * 3027 * @return The nearest focusable in the specified direction, or null if none 3028 * can be found. 3029 */ 3030 public View focusSearch(int direction) { 3031 if (mParent != null) { 3032 return mParent.focusSearch(this, direction); 3033 } else { 3034 return null; 3035 } 3036 } 3037 3038 /** 3039 * This method is the last chance for the focused view and its ancestors to 3040 * respond to an arrow key. This is called when the focused view did not 3041 * consume the key internally, nor could the view system find a new view in 3042 * the requested direction to give focus to. 3043 * 3044 * @param focused The currently focused view. 3045 * @param direction The direction focus wants to move. One of FOCUS_UP, 3046 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 3047 * @return True if the this view consumed this unhandled move. 3048 */ 3049 public boolean dispatchUnhandledMove(View focused, int direction) { 3050 return false; 3051 } 3052 3053 /** 3054 * If a user manually specified the next view id for a particular direction, 3055 * use the root to look up the view. Once a view is found, it is cached 3056 * for future lookups. 3057 * @param root The root view of the hierarchy containing this view. 3058 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 3059 * @return The user specified next view, or null if there is none. 3060 */ 3061 View findUserSetNextFocus(View root, int direction) { 3062 switch (direction) { 3063 case FOCUS_LEFT: 3064 if (mNextFocusLeftId == View.NO_ID) return null; 3065 return findViewShouldExist(root, mNextFocusLeftId); 3066 case FOCUS_RIGHT: 3067 if (mNextFocusRightId == View.NO_ID) return null; 3068 return findViewShouldExist(root, mNextFocusRightId); 3069 case FOCUS_UP: 3070 if (mNextFocusUpId == View.NO_ID) return null; 3071 return findViewShouldExist(root, mNextFocusUpId); 3072 case FOCUS_DOWN: 3073 if (mNextFocusDownId == View.NO_ID) return null; 3074 return findViewShouldExist(root, mNextFocusDownId); 3075 } 3076 return null; 3077 } 3078 3079 private static View findViewShouldExist(View root, int childViewId) { 3080 View result = root.findViewById(childViewId); 3081 if (result == null) { 3082 Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified " 3083 + "by user for id " + childViewId); 3084 } 3085 return result; 3086 } 3087 3088 /** 3089 * Find and return all focusable views that are descendants of this view, 3090 * possibly including this view if it is focusable itself. 3091 * 3092 * @param direction The direction of the focus 3093 * @return A list of focusable views 3094 */ 3095 public ArrayList<View> getFocusables(int direction) { 3096 ArrayList<View> result = new ArrayList<View>(24); 3097 addFocusables(result, direction); 3098 return result; 3099 } 3100 3101 /** 3102 * Add any focusable views that are descendants of this view (possibly 3103 * including this view if it is focusable itself) to views. If we are in touch mode, 3104 * only add views that are also focusable in touch mode. 3105 * 3106 * @param views Focusable views found so far 3107 * @param direction The direction of the focus 3108 */ 3109 public void addFocusables(ArrayList<View> views, int direction) { 3110 if (!isFocusable()) return; 3111 3112 if (isInTouchMode() && !isFocusableInTouchMode()) return; 3113 3114 views.add(this); 3115 } 3116 3117 /** 3118 * Find and return all touchable views that are descendants of this view, 3119 * possibly including this view if it is touchable itself. 3120 * 3121 * @return A list of touchable views 3122 */ 3123 public ArrayList<View> getTouchables() { 3124 ArrayList<View> result = new ArrayList<View>(); 3125 addTouchables(result); 3126 return result; 3127 } 3128 3129 /** 3130 * Add any touchable views that are descendants of this view (possibly 3131 * including this view if it is touchable itself) to views. 3132 * 3133 * @param views Touchable views found so far 3134 */ 3135 public void addTouchables(ArrayList<View> views) { 3136 final int viewFlags = mViewFlags; 3137 3138 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 3139 && (viewFlags & ENABLED_MASK) == ENABLED) { 3140 views.add(this); 3141 } 3142 } 3143 3144 /** 3145 * Call this to try to give focus to a specific view or to one of its 3146 * descendants. 3147 * 3148 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), 3149 * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) 3150 * while the device is in touch mode. 3151 * 3152 * See also {@link #focusSearch}, which is what you call to say that you 3153 * have focus, and you want your parent to look for the next one. 3154 * 3155 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 3156 * {@link #FOCUS_DOWN} and <code>null</code>. 3157 * 3158 * @return Whether this view or one of its descendants actually took focus. 3159 */ 3160 public final boolean requestFocus() { 3161 return requestFocus(View.FOCUS_DOWN); 3162 } 3163 3164 3165 /** 3166 * Call this to try to give focus to a specific view or to one of its 3167 * descendants and give it a hint about what direction focus is heading. 3168 * 3169 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), 3170 * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) 3171 * while the device is in touch mode. 3172 * 3173 * See also {@link #focusSearch}, which is what you call to say that you 3174 * have focus, and you want your parent to look for the next one. 3175 * 3176 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 3177 * <code>null</code> set for the previously focused rectangle. 3178 * 3179 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 3180 * @return Whether this view or one of its descendants actually took focus. 3181 */ 3182 public final boolean requestFocus(int direction) { 3183 return requestFocus(direction, null); 3184 } 3185 3186 /** 3187 * Call this to try to give focus to a specific view or to one of its descendants 3188 * and give it hints about the direction and a specific rectangle that the focus 3189 * is coming from. The rectangle can help give larger views a finer grained hint 3190 * about where focus is coming from, and therefore, where to show selection, or 3191 * forward focus change internally. 3192 * 3193 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false), 3194 * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode}) 3195 * while the device is in touch mode. 3196 * 3197 * A View will not take focus if it is not visible. 3198 * 3199 * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()} 3200 * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 3201 * 3202 * See also {@link #focusSearch}, which is what you call to say that you 3203 * have focus, and you want your parent to look for the next one. 3204 * 3205 * You may wish to override this method if your custom {@link View} has an internal 3206 * {@link View} that it wishes to forward the request to. 3207 * 3208 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 3209 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 3210 * to give a finer grained hint about where focus is coming from. May be null 3211 * if there is no hint. 3212 * @return Whether this view or one of its descendants actually took focus. 3213 */ 3214 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 3215 // need to be focusable 3216 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 3217 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 3218 return false; 3219 } 3220 3221 // need to be focusable in touch mode if in touch mode 3222 if (isInTouchMode() && 3223 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 3224 return false; 3225 } 3226 3227 // need to not have any parents blocking us 3228 if (hasAncestorThatBlocksDescendantFocus()) { 3229 return false; 3230 } 3231 3232 handleFocusGainInternal(direction, previouslyFocusedRect); 3233 return true; 3234 } 3235 3236 /** 3237 * Call this to try to give focus to a specific view or to one of its descendants. This is a 3238 * special variant of {@link #requestFocus() } that will allow views that are not focuable in 3239 * touch mode to request focus when they are touched. 3240 * 3241 * @return Whether this view or one of its descendants actually took focus. 3242 * 3243 * @see #isInTouchMode() 3244 * 3245 */ 3246 public final boolean requestFocusFromTouch() { 3247 // Leave touch mode if we need to 3248 if (isInTouchMode()) { 3249 View root = getRootView(); 3250 if (root != null) { 3251 ViewRoot viewRoot = (ViewRoot)root.getParent(); 3252 if (viewRoot != null) { 3253 viewRoot.ensureTouchMode(false); 3254 } 3255 } 3256 } 3257 return requestFocus(View.FOCUS_DOWN); 3258 } 3259 3260 /** 3261 * @return Whether any ancestor of this view blocks descendant focus. 3262 */ 3263 private boolean hasAncestorThatBlocksDescendantFocus() { 3264 ViewParent ancestor = mParent; 3265 while (ancestor instanceof ViewGroup) { 3266 final ViewGroup vgAncestor = (ViewGroup) ancestor; 3267 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) { 3268 return true; 3269 } else { 3270 ancestor = vgAncestor.getParent(); 3271 } 3272 } 3273 return false; 3274 } 3275 3276 /** 3277 * This is called when a container is going to temporarily detach a child 3278 * that currently has focus, with 3279 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 3280 * It will either be followed by {@link #onFinishTemporaryDetach()} or 3281 * {@link #onDetachedFromWindow()} when the container is done. Generally 3282 * this is currently only done ListView for a view with focus. 3283 */ 3284 public void onStartTemporaryDetach() { 3285 } 3286 3287 /** 3288 * Called after {@link #onStartTemporaryDetach} when the container is done 3289 * changing the view. 3290 */ 3291 public void onFinishTemporaryDetach() { 3292 } 3293 3294 /** 3295 * capture information of this view for later analysis: developement only 3296 * check dynamic switch to make sure we only dump view 3297 * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set 3298 */ 3299 private static void captureViewInfo(String subTag, View v) { 3300 if (v == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) { 3301 return; 3302 } 3303 ViewDebug.dumpCapturedView(subTag, v); 3304 } 3305 3306 /** 3307 * Dispatch a key event before it is processed by any input method 3308 * associated with the view hierarchy. This can be used to intercept 3309 * key events in special situations before the IME consumes them; a 3310 * typical example would be handling the BACK key to update the application's 3311 * UI instead of allowing the IME to see it and close itself. 3312 * 3313 * @param event The key event to be dispatched. 3314 * @return True if the event was handled, false otherwise. 3315 */ 3316 public boolean dispatchKeyEventPreIme(KeyEvent event) { 3317 return onKeyPreIme(event.getKeyCode(), event); 3318 } 3319 3320 /** 3321 * Dispatch a key event to the next view on the focus path. This path runs 3322 * from the top of the view tree down to the currently focused view. If this 3323 * view has focus, it will dispatch to itself. Otherwise it will dispatch 3324 * the next node down the focus path. This method also fires any key 3325 * listeners. 3326 * 3327 * @param event The key event to be dispatched. 3328 * @return True if the event was handled, false otherwise. 3329 */ 3330 public boolean dispatchKeyEvent(KeyEvent event) { 3331 // If any attached key listener a first crack at the event. 3332 //noinspection SimplifiableIfStatement 3333 3334 if (android.util.Config.LOGV) { 3335 captureViewInfo("captureViewKeyEvent", this); 3336 } 3337 3338 if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 3339 && mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 3340 return true; 3341 } 3342 3343 return event.dispatch(this); 3344 } 3345 3346 /** 3347 * Dispatches a key shortcut event. 3348 * 3349 * @param event The key event to be dispatched. 3350 * @return True if the event was handled by the view, false otherwise. 3351 */ 3352 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 3353 return onKeyShortcut(event.getKeyCode(), event); 3354 } 3355 3356 /** 3357 * Pass the touch screen motion event down to the target view, or this 3358 * view if it is the target. 3359 * 3360 * @param event The motion event to be dispatched. 3361 * @return True if the event was handled by the view, false otherwise. 3362 */ 3363 public boolean dispatchTouchEvent(MotionEvent event) { 3364 if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && 3365 mOnTouchListener.onTouch(this, event)) { 3366 return true; 3367 } 3368 return onTouchEvent(event); 3369 } 3370 3371 /** 3372 * Pass a trackball motion event down to the focused view. 3373 * 3374 * @param event The motion event to be dispatched. 3375 * @return True if the event was handled by the view, false otherwise. 3376 */ 3377 public boolean dispatchTrackballEvent(MotionEvent event) { 3378 //Log.i("view", "view=" + this + ", " + event.toString()); 3379 return onTrackballEvent(event); 3380 } 3381 3382 /** 3383 * Called when the window containing this view gains or loses window focus. 3384 * ViewGroups should override to route to their children. 3385 * 3386 * @param hasFocus True if the window containing this view now has focus, 3387 * false otherwise. 3388 */ 3389 public void dispatchWindowFocusChanged(boolean hasFocus) { 3390 onWindowFocusChanged(hasFocus); 3391 } 3392 3393 /** 3394 * Called when the window containing this view gains or loses focus. Note 3395 * that this is separate from view focus: to receive key events, both 3396 * your view and its window must have focus. If a window is displayed 3397 * on top of yours that takes input focus, then your own window will lose 3398 * focus but the view focus will remain unchanged. 3399 * 3400 * @param hasWindowFocus True if the window containing this view now has 3401 * focus, false otherwise. 3402 */ 3403 public void onWindowFocusChanged(boolean hasWindowFocus) { 3404 InputMethodManager imm = InputMethodManager.peekInstance(); 3405 if (!hasWindowFocus) { 3406 if (isPressed()) { 3407 setPressed(false); 3408 } 3409 if (imm != null && (mPrivateFlags & FOCUSED) != 0) { 3410 imm.focusOut(this); 3411 } 3412 } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { 3413 imm.focusIn(this); 3414 } 3415 refreshDrawableState(); 3416 } 3417 3418 /** 3419 * Returns true if this view is in a window that currently has window focus. 3420 * Note that this is not the same as the view itself having focus. 3421 * 3422 * @return True if this view is in a window that currently has window focus. 3423 */ 3424 public boolean hasWindowFocus() { 3425 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 3426 } 3427 3428 /** 3429 * Dispatch a window visibility change down the view hierarchy. 3430 * ViewGroups should override to route to their children. 3431 * 3432 * @param visibility The new visibility of the window. 3433 * 3434 * @see #onWindowVisibilityChanged 3435 */ 3436 public void dispatchWindowVisibilityChanged(int visibility) { 3437 onWindowVisibilityChanged(visibility); 3438 } 3439 3440 /** 3441 * Called when the window containing has change its visibility 3442 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 3443 * that this tells you whether or not your window is being made visible 3444 * to the window manager; this does <em>not</em> tell you whether or not 3445 * your window is obscured by other windows on the screen, even if it 3446 * is itself visible. 3447 * 3448 * @param visibility The new visibility of the window. 3449 */ 3450 protected void onWindowVisibilityChanged(int visibility) { 3451 } 3452 3453 /** 3454 * Returns the current visibility of the window this view is attached to 3455 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 3456 * 3457 * @return Returns the current visibility of the view's window. 3458 */ 3459 public int getWindowVisibility() { 3460 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 3461 } 3462 3463 /** 3464 * Retrieve the overall visible display size in which the window this view is 3465 * attached to has been positioned in. This takes into account screen 3466 * decorations above the window, for both cases where the window itself 3467 * is being position inside of them or the window is being placed under 3468 * then and covered insets are used for the window to position its content 3469 * inside. In effect, this tells you the available area where content can 3470 * be placed and remain visible to users. 3471 * 3472 * <p>This function requires an IPC back to the window manager to retrieve 3473 * the requested information, so should not be used in performance critical 3474 * code like drawing. 3475 * 3476 * @param outRect Filled in with the visible display frame. If the view 3477 * is not attached to a window, this is simply the raw display size. 3478 */ 3479 public void getWindowVisibleDisplayFrame(Rect outRect) { 3480 if (mAttachInfo != null) { 3481 try { 3482 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 3483 } catch (RemoteException e) { 3484 return; 3485 } 3486 // XXX This is really broken, and probably all needs to be done 3487 // in the window manager, and we need to know more about whether 3488 // we want the area behind or in front of the IME. 3489 final Rect insets = mAttachInfo.mVisibleInsets; 3490 outRect.left += insets.left; 3491 outRect.top += insets.top; 3492 outRect.right -= insets.right; 3493 outRect.bottom -= insets.bottom; 3494 return; 3495 } 3496 Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); 3497 outRect.set(0, 0, d.getWidth(), d.getHeight()); 3498 } 3499 3500 /** 3501 * Private function to aggregate all per-view attributes in to the view 3502 * root. 3503 */ 3504 void dispatchCollectViewAttributes(int visibility) { 3505 performCollectViewAttributes(visibility); 3506 } 3507 3508 void performCollectViewAttributes(int visibility) { 3509 //noinspection PointlessBitwiseExpression 3510 if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON)) 3511 == (VISIBLE | KEEP_SCREEN_ON)) { 3512 mAttachInfo.mKeepScreenOn = true; 3513 } 3514 } 3515 3516 void needGlobalAttributesUpdate(boolean force) { 3517 AttachInfo ai = mAttachInfo; 3518 if (ai != null) { 3519 if (ai.mKeepScreenOn || force) { 3520 ai.mRecomputeGlobalAttributes = true; 3521 } 3522 } 3523 } 3524 3525 /** 3526 * Returns whether the device is currently in touch mode. Touch mode is entered 3527 * once the user begins interacting with the device by touch, and affects various 3528 * things like whether focus is always visible to the user. 3529 * 3530 * @return Whether the device is in touch mode. 3531 */ 3532 @ViewDebug.ExportedProperty 3533 public boolean isInTouchMode() { 3534 if (mAttachInfo != null) { 3535 return mAttachInfo.mInTouchMode; 3536 } else { 3537 return ViewRoot.isInTouchMode(); 3538 } 3539 } 3540 3541 /** 3542 * Returns the context the view is running in, through which it can 3543 * access the current theme, resources, etc. 3544 * 3545 * @return The view's Context. 3546 */ 3547 @ViewDebug.CapturedViewProperty 3548 public final Context getContext() { 3549 return mContext; 3550 } 3551 3552 /** 3553 * Handle a key event before it is processed by any input method 3554 * associated with the view hierarchy. This can be used to intercept 3555 * key events in special situations before the IME consumes them; a 3556 * typical example would be handling the BACK key to update the application's 3557 * UI instead of allowing the IME to see it and close itself. 3558 * 3559 * @param keyCode The value in event.getKeyCode(). 3560 * @param event Description of the key event. 3561 * @return If you handled the event, return true. If you want to allow the 3562 * event to be handled by the next receiver, return false. 3563 */ 3564 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 3565 return false; 3566 } 3567 3568 /** 3569 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3570 * KeyEvent.Callback.onKeyMultiple()}: perform press of the view 3571 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 3572 * is released, if the view is enabled and clickable. 3573 * 3574 * @param keyCode A key code that represents the button pressed, from 3575 * {@link android.view.KeyEvent}. 3576 * @param event The KeyEvent object that defines the button action. 3577 */ 3578 public boolean onKeyDown(int keyCode, KeyEvent event) { 3579 boolean result = false; 3580 3581 switch (keyCode) { 3582 case KeyEvent.KEYCODE_DPAD_CENTER: 3583 case KeyEvent.KEYCODE_ENTER: { 3584 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 3585 return true; 3586 } 3587 // Long clickable items don't necessarily have to be clickable 3588 if (((mViewFlags & CLICKABLE) == CLICKABLE || 3589 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && 3590 (event.getRepeatCount() == 0)) { 3591 setPressed(true); 3592 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 3593 postCheckForLongClick(); 3594 } 3595 return true; 3596 } 3597 break; 3598 } 3599 } 3600 return result; 3601 } 3602 3603 /** 3604 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3605 * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view 3606 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or 3607 * {@link KeyEvent#KEYCODE_ENTER} is released. 3608 * 3609 * @param keyCode A key code that represents the button pressed, from 3610 * {@link android.view.KeyEvent}. 3611 * @param event The KeyEvent object that defines the button action. 3612 */ 3613 public boolean onKeyUp(int keyCode, KeyEvent event) { 3614 boolean result = false; 3615 3616 switch (keyCode) { 3617 case KeyEvent.KEYCODE_DPAD_CENTER: 3618 case KeyEvent.KEYCODE_ENTER: { 3619 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 3620 return true; 3621 } 3622 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 3623 setPressed(false); 3624 3625 if (!mHasPerformedLongPress) { 3626 // This is a tap, so remove the longpress check 3627 if (mPendingCheckForLongPress != null) { 3628 removeCallbacks(mPendingCheckForLongPress); 3629 } 3630 3631 result = performClick(); 3632 } 3633 } 3634 break; 3635 } 3636 } 3637 return result; 3638 } 3639 3640 /** 3641 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3642 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 3643 * the event). 3644 * 3645 * @param keyCode A key code that represents the button pressed, from 3646 * {@link android.view.KeyEvent}. 3647 * @param repeatCount The number of times the action was made. 3648 * @param event The KeyEvent object that defines the button action. 3649 */ 3650 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 3651 return false; 3652 } 3653 3654 /** 3655 * Called when an unhandled key shortcut event occurs. 3656 * 3657 * @param keyCode The value in event.getKeyCode(). 3658 * @param event Description of the key event. 3659 * @return If you handled the event, return true. If you want to allow the 3660 * event to be handled by the next receiver, return false. 3661 */ 3662 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 3663 return false; 3664 } 3665 3666 /** 3667 * Check whether the called view is a text editor, in which case it 3668 * would make sense to automatically display a soft input window for 3669 * it. Subclasses should override this if they implement 3670 * {@link #onCreateInputConnection(EditorInfo)} to return true if 3671 * a call on that method would return a non-null InputConnection, and 3672 * they are really a first-class editor that the user would normally 3673 * start typing on when the go into a window containing your view. 3674 * 3675 * <p>The default implementation always returns false. This does 3676 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 3677 * will not be called or the user can not otherwise perform edits on your 3678 * view; it is just a hint to the system that this is not the primary 3679 * purpose of this view. 3680 * 3681 * @return Returns true if this view is a text editor, else false. 3682 */ 3683 public boolean onCheckIsTextEditor() { 3684 return false; 3685 } 3686 3687 /** 3688 * Create a new InputConnection for an InputMethod to interact 3689 * with the view. The default implementation returns null, since it doesn't 3690 * support input methods. You can override this to implement such support. 3691 * This is only needed for views that take focus and text input. 3692 * 3693 * <p>When implementing this, you probably also want to implement 3694 * {@link #onCheckIsTextEditor()} to indicate you will return a 3695 * non-null InputConnection. 3696 * 3697 * @param outAttrs Fill in with attribute information about the connection. 3698 */ 3699 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 3700 return null; 3701 } 3702 3703 /** 3704 * Called by the {@link android.view.inputmethod.InputMethodManager} 3705 * when a view who is not the current 3706 * input connection target is trying to make a call on the manager. The 3707 * default implementation returns false; you can override this to return 3708 * true for certain views if you are performing InputConnection proxying 3709 * to them. 3710 * @param view The View that is making the InputMethodManager call. 3711 * @return Return true to allow the call, false to reject. 3712 */ 3713 public boolean checkInputConnectionProxy(View view) { 3714 return false; 3715 } 3716 3717 /** 3718 * Show the context menu for this view. It is not safe to hold on to the 3719 * menu after returning from this method. 3720 * 3721 * @param menu The context menu to populate 3722 */ 3723 public void createContextMenu(ContextMenu menu) { 3724 ContextMenuInfo menuInfo = getContextMenuInfo(); 3725 3726 // Sets the current menu info so all items added to menu will have 3727 // my extra info set. 3728 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 3729 3730 onCreateContextMenu(menu); 3731 if (mOnCreateContextMenuListener != null) { 3732 mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 3733 } 3734 3735 // Clear the extra information so subsequent items that aren't mine don't 3736 // have my extra info. 3737 ((MenuBuilder)menu).setCurrentMenuInfo(null); 3738 3739 if (mParent != null) { 3740 mParent.createContextMenu(menu); 3741 } 3742 } 3743 3744 /** 3745 * Views should implement this if they have extra information to associate 3746 * with the context menu. The return result is supplied as a parameter to 3747 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 3748 * callback. 3749 * 3750 * @return Extra information about the item for which the context menu 3751 * should be shown. This information will vary across different 3752 * subclasses of View. 3753 */ 3754 protected ContextMenuInfo getContextMenuInfo() { 3755 return null; 3756 } 3757 3758 /** 3759 * Views should implement this if the view itself is going to add items to 3760 * the context menu. 3761 * 3762 * @param menu the context menu to populate 3763 */ 3764 protected void onCreateContextMenu(ContextMenu menu) { 3765 } 3766 3767 /** 3768 * Implement this method to handle trackball motion events. The 3769 * <em>relative</em> movement of the trackball since the last event 3770 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 3771 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 3772 * that a movement of 1 corresponds to the user pressing one DPAD key (so 3773 * they will often be fractional values, representing the more fine-grained 3774 * movement information available from a trackball). 3775 * 3776 * @param event The motion event. 3777 * @return True if the event was handled, false otherwise. 3778 */ 3779 public boolean onTrackballEvent(MotionEvent event) { 3780 return false; 3781 } 3782 3783 /** 3784 * Implement this method to handle touch screen motion events. 3785 * 3786 * @param event The motion event. 3787 * @return True if the event was handled, false otherwise. 3788 */ 3789 public boolean onTouchEvent(MotionEvent event) { 3790 final int viewFlags = mViewFlags; 3791 3792 if ((viewFlags & ENABLED_MASK) == DISABLED) { 3793 // A disabled view that is clickable still consumes the touch 3794 // events, it just doesn't respond to them. 3795 return (((viewFlags & CLICKABLE) == CLICKABLE || 3796 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 3797 } 3798 3799 if (mTouchDelegate != null) { 3800 if (mTouchDelegate.onTouchEvent(event)) { 3801 return true; 3802 } 3803 } 3804 3805 if (((viewFlags & CLICKABLE) == CLICKABLE || 3806 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 3807 switch (event.getAction()) { 3808 case MotionEvent.ACTION_UP: 3809 if ((mPrivateFlags & PRESSED) != 0) { 3810 // take focus if we don't have it already and we should in 3811 // touch mode. 3812 boolean focusTaken = false; 3813 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 3814 focusTaken = requestFocus(); 3815 } 3816 3817 if (!mHasPerformedLongPress) { 3818 // This is a tap, so remove the longpress check 3819 if (mPendingCheckForLongPress != null) { 3820 removeCallbacks(mPendingCheckForLongPress); 3821 } 3822 3823 // Only perform take click actions if we were in the pressed state 3824 if (!focusTaken) { 3825 performClick(); 3826 } 3827 } 3828 3829 if (mUnsetPressedState == null) { 3830 mUnsetPressedState = new UnsetPressedState(); 3831 } 3832 3833 if (!post(mUnsetPressedState)) { 3834 // If the post failed, unpress right now 3835 mUnsetPressedState.run(); 3836 } 3837 } 3838 break; 3839 3840 case MotionEvent.ACTION_DOWN: 3841 mPrivateFlags |= PRESSED; 3842 refreshDrawableState(); 3843 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 3844 postCheckForLongClick(); 3845 } 3846 break; 3847 3848 case MotionEvent.ACTION_CANCEL: 3849 mPrivateFlags &= ~PRESSED; 3850 refreshDrawableState(); 3851 break; 3852 3853 case MotionEvent.ACTION_MOVE: 3854 final int x = (int) event.getX(); 3855 final int y = (int) event.getY(); 3856 3857 // Be lenient about moving outside of buttons 3858 int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); 3859 if ((x < 0 - slop) || (x >= getWidth() + slop) || 3860 (y < 0 - slop) || (y >= getHeight() + slop)) { 3861 // Outside button 3862 if ((mPrivateFlags & PRESSED) != 0) { 3863 // Remove any future long press checks 3864 if (mPendingCheckForLongPress != null) { 3865 removeCallbacks(mPendingCheckForLongPress); 3866 } 3867 3868 // Need to switch from pressed to not pressed 3869 mPrivateFlags &= ~PRESSED; 3870 refreshDrawableState(); 3871 } 3872 } else { 3873 // Inside button 3874 if ((mPrivateFlags & PRESSED) == 0) { 3875 // Need to switch from not pressed to pressed 3876 mPrivateFlags |= PRESSED; 3877 refreshDrawableState(); 3878 } 3879 } 3880 break; 3881 } 3882 return true; 3883 } 3884 3885 return false; 3886 } 3887 3888 /** 3889 * Cancels a pending long press. Your subclass can use this if you 3890 * want the context menu to come up if the user presses and holds 3891 * at the same place, but you don't want it to come up if they press 3892 * and then move around enough to cause scrolling. 3893 */ 3894 public void cancelLongPress() { 3895 if (mPendingCheckForLongPress != null) { 3896 removeCallbacks(mPendingCheckForLongPress); 3897 } 3898 } 3899 3900 /** 3901 * Sets the TouchDelegate for this View. 3902 */ 3903 public void setTouchDelegate(TouchDelegate delegate) { 3904 mTouchDelegate = delegate; 3905 } 3906 3907 /** 3908 * Gets the TouchDelegate for this View. 3909 */ 3910 public TouchDelegate getTouchDelegate() { 3911 return mTouchDelegate; 3912 } 3913 3914 /** 3915 * Set flags controlling behavior of this view. 3916 * 3917 * @param flags Constant indicating the value which should be set 3918 * @param mask Constant indicating the bit range that should be changed 3919 */ 3920 void setFlags(int flags, int mask) { 3921 int old = mViewFlags; 3922 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 3923 3924 int changed = mViewFlags ^ old; 3925 if (changed == 0) { 3926 return; 3927 } 3928 int privateFlags = mPrivateFlags; 3929 3930 /* Check if the FOCUSABLE bit has changed */ 3931 if (((changed & FOCUSABLE_MASK) != 0) && 3932 ((privateFlags & HAS_BOUNDS) !=0)) { 3933 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 3934 && ((privateFlags & FOCUSED) != 0)) { 3935 /* Give up focus if we are no longer focusable */ 3936 clearFocus(); 3937 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 3938 && ((privateFlags & FOCUSED) == 0)) { 3939 /* 3940 * Tell the view system that we are now available to take focus 3941 * if no one else already has it. 3942 */ 3943 if (mParent != null) mParent.focusableViewAvailable(this); 3944 } 3945 } 3946 3947 if ((flags & VISIBILITY_MASK) == VISIBLE) { 3948 if ((changed & VISIBILITY_MASK) != 0) { 3949 /* 3950 * If this view is becoming visible, set the DRAWN flag so that 3951 * the next invalidate() will not be skipped. 3952 */ 3953 mPrivateFlags |= DRAWN; 3954 3955 needGlobalAttributesUpdate(true); 3956 3957 // a view becoming visible is worth notifying the parent 3958 // about in case nothing has focus. even if this specific view 3959 // isn't focusable, it may contain something that is, so let 3960 // the root view try to give this focus if nothing else does. 3961 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 3962 mParent.focusableViewAvailable(this); 3963 } 3964 } 3965 } 3966 3967 /* Check if the GONE bit has changed */ 3968 if ((changed & GONE) != 0) { 3969 needGlobalAttributesUpdate(false); 3970 requestLayout(); 3971 invalidate(); 3972 3973 if (((mViewFlags & VISIBILITY_MASK) == GONE) && hasFocus()) { 3974 clearFocus(); 3975 } 3976 if (mAttachInfo != null) { 3977 mAttachInfo.mViewVisibilityChanged = true; 3978 } 3979 } 3980 3981 /* Check if the VISIBLE bit has changed */ 3982 if ((changed & INVISIBLE) != 0) { 3983 needGlobalAttributesUpdate(false); 3984 invalidate(); 3985 3986 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { 3987 // root view becoming invisible shouldn't clear focus 3988 if (getRootView() != this) { 3989 clearFocus(); 3990 } 3991 } 3992 if (mAttachInfo != null) { 3993 mAttachInfo.mViewVisibilityChanged = true; 3994 } 3995 } 3996 3997 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 3998 destroyDrawingCache(); 3999 } 4000 4001 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 4002 destroyDrawingCache(); 4003 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4004 } 4005 4006 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 4007 destroyDrawingCache(); 4008 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4009 } 4010 4011 if ((changed & DRAW_MASK) != 0) { 4012 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 4013 if (mBGDrawable != null) { 4014 mPrivateFlags &= ~SKIP_DRAW; 4015 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 4016 } else { 4017 mPrivateFlags |= SKIP_DRAW; 4018 } 4019 } else { 4020 mPrivateFlags &= ~SKIP_DRAW; 4021 } 4022 requestLayout(); 4023 invalidate(); 4024 } 4025 4026 if ((changed & KEEP_SCREEN_ON) != 0) { 4027 if (mParent != null) { 4028 mParent.recomputeViewAttributes(this); 4029 } 4030 } 4031 } 4032 4033 /** 4034 * Change the view's z order in the tree, so it's on top of other sibling 4035 * views 4036 */ 4037 public void bringToFront() { 4038 if (mParent != null) { 4039 mParent.bringChildToFront(this); 4040 } 4041 } 4042 4043 /** 4044 * This is called in response to an internal scroll in this view (i.e., the 4045 * view scrolled its own contents). This is typically as a result of 4046 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 4047 * called. 4048 * 4049 * @param l Current horizontal scroll origin. 4050 * @param t Current vertical scroll origin. 4051 * @param oldl Previous horizontal scroll origin. 4052 * @param oldt Previous vertical scroll origin. 4053 */ 4054 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 4055 mBackgroundSizeChanged = true; 4056 4057 final AttachInfo ai = mAttachInfo; 4058 if (ai != null) { 4059 ai.mViewScrollChanged = true; 4060 } 4061 } 4062 4063 /** 4064 * This is called during layout when the size of this view has changed. If 4065 * you were just added to the view hierarchy, you're called with the old 4066 * values of 0. 4067 * 4068 * @param w Current width of this view. 4069 * @param h Current height of this view. 4070 * @param oldw Old width of this view. 4071 * @param oldh Old height of this view. 4072 */ 4073 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 4074 } 4075 4076 /** 4077 * Called by draw to draw the child views. This may be overridden 4078 * by derived classes to gain control just before its children are drawn 4079 * (but after its own view has been drawn). 4080 * @param canvas the canvas on which to draw the view 4081 */ 4082 protected void dispatchDraw(Canvas canvas) { 4083 } 4084 4085 /** 4086 * Gets the parent of this view. Note that the parent is a 4087 * ViewParent and not necessarily a View. 4088 * 4089 * @return Parent of this view. 4090 */ 4091 public final ViewParent getParent() { 4092 return mParent; 4093 } 4094 4095 /** 4096 * Return the scrolled left position of this view. This is the left edge of 4097 * the displayed part of your view. You do not need to draw any pixels 4098 * farther left, since those are outside of the frame of your view on 4099 * screen. 4100 * 4101 * @return The left edge of the displayed part of your view, in pixels. 4102 */ 4103 public final int getScrollX() { 4104 return mScrollX; 4105 } 4106 4107 /** 4108 * Return the scrolled top position of this view. This is the top edge of 4109 * the displayed part of your view. You do not need to draw any pixels above 4110 * it, since those are outside of the frame of your view on screen. 4111 * 4112 * @return The top edge of the displayed part of your view, in pixels. 4113 */ 4114 public final int getScrollY() { 4115 return mScrollY; 4116 } 4117 4118 /** 4119 * Return the width of the your view. 4120 * 4121 * @return The width of your view, in pixels. 4122 */ 4123 @ViewDebug.ExportedProperty 4124 public final int getWidth() { 4125 return mRight - mLeft; 4126 } 4127 4128 /** 4129 * Return the height of your view. 4130 * 4131 * @return The height of your view, in pixels. 4132 */ 4133 @ViewDebug.ExportedProperty 4134 public final int getHeight() { 4135 return mBottom - mTop; 4136 } 4137 4138 /** 4139 * Return the visible drawing bounds of your view. Fills in the output 4140 * rectangle with the values from getScrollX(), getScrollY(), 4141 * getWidth(), and getHeight(). 4142 * 4143 * @param outRect The (scrolled) drawing bounds of the view. 4144 */ 4145 public void getDrawingRect(Rect outRect) { 4146 outRect.left = mScrollX; 4147 outRect.top = mScrollY; 4148 outRect.right = mScrollX + (mRight - mLeft); 4149 outRect.bottom = mScrollY + (mBottom - mTop); 4150 } 4151 4152 /** 4153 * The width of this view as measured in the most recent call to measure(). 4154 * This should be used during measurement and layout calculations only. Use 4155 * {@link #getWidth()} to see how wide a view is after layout. 4156 * 4157 * @return The measured width of this view. 4158 */ 4159 public final int getMeasuredWidth() { 4160 return mMeasuredWidth; 4161 } 4162 4163 /** 4164 * The height of this view as measured in the most recent call to measure(). 4165 * This should be used during measurement and layout calculations only. Use 4166 * {@link #getHeight()} to see how tall a view is after layout. 4167 * 4168 * @return The measured height of this view. 4169 */ 4170 public final int getMeasuredHeight() { 4171 return mMeasuredHeight; 4172 } 4173 4174 /** 4175 * Top position of this view relative to its parent. 4176 * 4177 * @return The top of this view, in pixels. 4178 */ 4179 @ViewDebug.CapturedViewProperty 4180 public final int getTop() { 4181 return mTop; 4182 } 4183 4184 /** 4185 * Bottom position of this view relative to its parent. 4186 * 4187 * @return The bottom of this view, in pixels. 4188 */ 4189 @ViewDebug.CapturedViewProperty 4190 public final int getBottom() { 4191 return mBottom; 4192 } 4193 4194 /** 4195 * Left position of this view relative to its parent. 4196 * 4197 * @return The left edge of this view, in pixels. 4198 */ 4199 @ViewDebug.CapturedViewProperty 4200 public final int getLeft() { 4201 return mLeft; 4202 } 4203 4204 /** 4205 * Right position of this view relative to its parent. 4206 * 4207 * @return The right edge of this view, in pixels. 4208 */ 4209 @ViewDebug.CapturedViewProperty 4210 public final int getRight() { 4211 return mRight; 4212 } 4213 4214 /** 4215 * Hit rectangle in parent's coordinates 4216 * 4217 * @param outRect The hit rectangle of the view. 4218 */ 4219 public void getHitRect(Rect outRect) { 4220 outRect.set(mLeft, mTop, mRight, mBottom); 4221 } 4222 4223 /** 4224 * When a view has focus and the user navigates away from it, the next view is searched for 4225 * starting from the rectangle filled in by this method. 4226 * 4227 * By default, the rectange is the {@link #getDrawingRect})of the view. However, if your 4228 * view maintains some idea of internal selection, such as a cursor, or a selected row 4229 * or column, you should override this method and fill in a more specific rectangle. 4230 * 4231 * @param r The rectangle to fill in, in this view's coordinates. 4232 */ 4233 public void getFocusedRect(Rect r) { 4234 getDrawingRect(r); 4235 } 4236 4237 /** 4238 * If some part of this view is not clipped by any of its parents, then 4239 * return that area in r in global (root) coordinates. To convert r to local 4240 * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x, 4241 * -globalOffset.y)) If the view is completely clipped or translated out, 4242 * return false. 4243 * 4244 * @param r If true is returned, r holds the global coordinates of the 4245 * visible portion of this view. 4246 * @param globalOffset If true is returned, globalOffset holds the dx,dy 4247 * between this view and its root. globalOffet may be null. 4248 * @return true if r is non-empty (i.e. part of the view is visible at the 4249 * root level. 4250 */ 4251 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 4252 int width = mRight - mLeft; 4253 int height = mBottom - mTop; 4254 if (width > 0 && height > 0) { 4255 r.set(0, 0, width, height); 4256 if (globalOffset != null) { 4257 globalOffset.set(-mScrollX, -mScrollY); 4258 } 4259 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 4260 } 4261 return false; 4262 } 4263 4264 public final boolean getGlobalVisibleRect(Rect r) { 4265 return getGlobalVisibleRect(r, null); 4266 } 4267 4268 public final boolean getLocalVisibleRect(Rect r) { 4269 Point offset = new Point(); 4270 if (getGlobalVisibleRect(r, offset)) { 4271 r.offset(-offset.x, -offset.y); // make r local 4272 return true; 4273 } 4274 return false; 4275 } 4276 4277 /** 4278 * Offset this view's vertical location by the specified number of pixels. 4279 * 4280 * @param offset the number of pixels to offset the view by 4281 */ 4282 public void offsetTopAndBottom(int offset) { 4283 mTop += offset; 4284 mBottom += offset; 4285 } 4286 4287 /** 4288 * Offset this view's horizontal location by the specified amount of pixels. 4289 * 4290 * @param offset the numer of pixels to offset the view by 4291 */ 4292 public void offsetLeftAndRight(int offset) { 4293 mLeft += offset; 4294 mRight += offset; 4295 } 4296 4297 /** 4298 * Get the LayoutParams associated with this view. All views should have 4299 * layout parameters. These supply parameters to the <i>parent</i> of this 4300 * view specifying how it should be arranged. There are many subclasses of 4301 * ViewGroup.LayoutParams, and these correspond to the different subclasses 4302 * of ViewGroup that are responsible for arranging their children. 4303 * @return The LayoutParams associated with this view 4304 */ 4305 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 4306 public ViewGroup.LayoutParams getLayoutParams() { 4307 return mLayoutParams; 4308 } 4309 4310 /** 4311 * Set the layout parameters associated with this view. These supply 4312 * parameters to the <i>parent</i> of this view specifying how it should be 4313 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 4314 * correspond to the different subclasses of ViewGroup that are responsible 4315 * for arranging their children. 4316 * 4317 * @param params the layout parameters for this view 4318 */ 4319 public void setLayoutParams(ViewGroup.LayoutParams params) { 4320 if (params == null) { 4321 throw new NullPointerException("params == null"); 4322 } 4323 mLayoutParams = params; 4324 requestLayout(); 4325 } 4326 4327 /** 4328 * Set the scrolled position of your view. This will cause a call to 4329 * {@link #onScrollChanged(int, int, int, int)} and the view will be 4330 * invalidated. 4331 * @param x the x position to scroll to 4332 * @param y the y position to scroll to 4333 */ 4334 public void scrollTo(int x, int y) { 4335 if (mScrollX != x || mScrollY != y) { 4336 int oldX = mScrollX; 4337 int oldY = mScrollY; 4338 mScrollX = x; 4339 mScrollY = y; 4340 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 4341 invalidate(); 4342 } 4343 } 4344 4345 /** 4346 * Move the scrolled position of your view. This will cause a call to 4347 * {@link #onScrollChanged(int, int, int, int)} and the view will be 4348 * invalidated. 4349 * @param x the amount of pixels to scroll by horizontally 4350 * @param y the amount of pixels to scroll by vertically 4351 */ 4352 public void scrollBy(int x, int y) { 4353 scrollTo(mScrollX + x, mScrollY + y); 4354 } 4355 4356 /** 4357 * Mark the the area defined by dirty as needing to be drawn. If the view is 4358 * visible, {@link #onDraw} will be called at some point in the future. 4359 * This must be called from a UI thread. To call from a non-UI thread, call 4360 * {@link #postInvalidate()}. 4361 * 4362 * WARNING: This method is destructive to dirty. 4363 * @param dirty the rectangle representing the bounds of the dirty region 4364 */ 4365 public void invalidate(Rect dirty) { 4366 if (ViewDebug.TRACE_HIERARCHY) { 4367 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4368 } 4369 4370 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4371 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4372 final ViewParent p = mParent; 4373 final AttachInfo ai = mAttachInfo; 4374 if (p != null && ai != null) { 4375 final int scrollX = mScrollX; 4376 final int scrollY = mScrollY; 4377 final Rect r = ai.mTmpInvalRect; 4378 r.set(dirty.left - scrollX, dirty.top - scrollY, 4379 dirty.right - scrollX, dirty.bottom - scrollY); 4380 mParent.invalidateChild(this, r); 4381 } 4382 } 4383 } 4384 4385 /** 4386 * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn. 4387 * The coordinates of the dirty rect are relative to the view. 4388 * If the view is visible, {@link #onDraw} will be called at some point 4389 * in the future. This must be called from a UI thread. To call 4390 * from a non-UI thread, call {@link #postInvalidate()}. 4391 * @param l the left position of the dirty region 4392 * @param t the top position of the dirty region 4393 * @param r the right position of the dirty region 4394 * @param b the bottom position of the dirty region 4395 */ 4396 public void invalidate(int l, int t, int r, int b) { 4397 if (ViewDebug.TRACE_HIERARCHY) { 4398 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4399 } 4400 4401 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4402 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4403 final ViewParent p = mParent; 4404 final AttachInfo ai = mAttachInfo; 4405 if (p != null && ai != null && l < r && t < b) { 4406 final int scrollX = mScrollX; 4407 final int scrollY = mScrollY; 4408 final Rect tmpr = ai.mTmpInvalRect; 4409 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); 4410 p.invalidateChild(this, tmpr); 4411 } 4412 } 4413 } 4414 4415 /** 4416 * Invalidate the whole view. If the view is visible, {@link #onDraw} will 4417 * be called at some point in the future. This must be called from a 4418 * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. 4419 */ 4420 public void invalidate() { 4421 if (ViewDebug.TRACE_HIERARCHY) { 4422 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4423 } 4424 4425 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4426 mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID; 4427 final ViewParent p = mParent; 4428 final AttachInfo ai = mAttachInfo; 4429 if (p != null && ai != null) { 4430 final Rect r = ai.mTmpInvalRect; 4431 r.set(0, 0, mRight - mLeft, mBottom - mTop); 4432 // Don't call invalidate -- we don't want to internally scroll 4433 // our own bounds 4434 p.invalidateChild(this, r); 4435 } 4436 } 4437 } 4438 4439 /** 4440 * @return A handler associated with the thread running the View. This 4441 * handler can be used to pump events in the UI events queue. 4442 */ 4443 public Handler getHandler() { 4444 if (mAttachInfo != null) { 4445 return mAttachInfo.mHandler; 4446 } 4447 return null; 4448 } 4449 4450 /** 4451 * Causes the Runnable to be added to the message queue. 4452 * The runnable will be run on the user interface thread. 4453 * 4454 * @param action The Runnable that will be executed. 4455 * 4456 * @return Returns true if the Runnable was successfully placed in to the 4457 * message queue. Returns false on failure, usually because the 4458 * looper processing the message queue is exiting. 4459 */ 4460 public boolean post(Runnable action) { 4461 Handler handler; 4462 if (mAttachInfo != null) { 4463 handler = mAttachInfo.mHandler; 4464 } else { 4465 // Assume that post will succeed later 4466 ViewRoot.getRunQueue().post(action); 4467 return true; 4468 } 4469 4470 return handler.post(action); 4471 } 4472 4473 /** 4474 * Causes the Runnable to be added to the message queue, to be run 4475 * after the specified amount of time elapses. 4476 * The runnable will be run on the user interface thread. 4477 * 4478 * @param action The Runnable that will be executed. 4479 * @param delayMillis The delay (in milliseconds) until the Runnable 4480 * will be executed. 4481 * 4482 * @return true if the Runnable was successfully placed in to the 4483 * message queue. Returns false on failure, usually because the 4484 * looper processing the message queue is exiting. Note that a 4485 * result of true does not mean the Runnable will be processed -- 4486 * if the looper is quit before the delivery time of the message 4487 * occurs then the message will be dropped. 4488 */ 4489 public boolean postDelayed(Runnable action, long delayMillis) { 4490 Handler handler; 4491 if (mAttachInfo != null) { 4492 handler = mAttachInfo.mHandler; 4493 } else { 4494 // Assume that post will succeed later 4495 ViewRoot.getRunQueue().postDelayed(action, delayMillis); 4496 return true; 4497 } 4498 4499 return handler.postDelayed(action, delayMillis); 4500 } 4501 4502 /** 4503 * Removes the specified Runnable from the message queue. 4504 * 4505 * @param action The Runnable to remove from the message handling queue 4506 * 4507 * @return true if this view could ask the Handler to remove the Runnable, 4508 * false otherwise. When the returned value is true, the Runnable 4509 * may or may not have been actually removed from the message queue 4510 * (for instance, if the Runnable was not in the queue already.) 4511 */ 4512 public boolean removeCallbacks(Runnable action) { 4513 Handler handler; 4514 if (mAttachInfo != null) { 4515 handler = mAttachInfo.mHandler; 4516 } else { 4517 // Assume that post will succeed later 4518 ViewRoot.getRunQueue().removeCallbacks(action); 4519 return true; 4520 } 4521 4522 handler.removeCallbacks(action); 4523 return true; 4524 } 4525 4526 /** 4527 * Cause an invalidate to happen on a subsequent cycle through the event loop. 4528 * Use this to invalidate the View from a non-UI thread. 4529 * 4530 * @see #invalidate() 4531 */ 4532 public void postInvalidate() { 4533 postInvalidateDelayed(0); 4534 } 4535 4536 /** 4537 * Cause an invalidate of the specified area to happen on a subsequent cycle 4538 * through the event loop. Use this to invalidate the View from a non-UI thread. 4539 * 4540 * @param left The left coordinate of the rectangle to invalidate. 4541 * @param top The top coordinate of the rectangle to invalidate. 4542 * @param right The right coordinate of the rectangle to invalidate. 4543 * @param bottom The bottom coordinate of the rectangle to invalidate. 4544 * 4545 * @see #invalidate(int, int, int, int) 4546 * @see #invalidate(Rect) 4547 */ 4548 public void postInvalidate(int left, int top, int right, int bottom) { 4549 postInvalidateDelayed(0, left, top, right, bottom); 4550 } 4551 4552 /** 4553 * Cause an invalidate to happen on a subsequent cycle through the event 4554 * loop. Waits for the specified amount of time. 4555 * 4556 * @param delayMilliseconds the duration in milliseconds to delay the 4557 * invalidation by 4558 */ 4559 public void postInvalidateDelayed(long delayMilliseconds) { 4560 // We try only with the AttachInfo because there's no point in invalidating 4561 // if we are not attached to our window 4562 if (mAttachInfo != null) { 4563 Message msg = Message.obtain(); 4564 msg.what = AttachInfo.INVALIDATE_MSG; 4565 msg.obj = this; 4566 mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 4567 } 4568 } 4569 4570 /** 4571 * Cause an invalidate of the specified area to happen on a subsequent cycle 4572 * through the event loop. Waits for the specified amount of time. 4573 * 4574 * @param delayMilliseconds the duration in milliseconds to delay the 4575 * invalidation by 4576 * @param left The left coordinate of the rectangle to invalidate. 4577 * @param top The top coordinate of the rectangle to invalidate. 4578 * @param right The right coordinate of the rectangle to invalidate. 4579 * @param bottom The bottom coordinate of the rectangle to invalidate. 4580 */ 4581 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 4582 int right, int bottom) { 4583 4584 // We try only with the AttachInfo because there's no point in invalidating 4585 // if we are not attached to our window 4586 if (mAttachInfo != null) { 4587 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire(); 4588 info.target = this; 4589 info.left = left; 4590 info.top = top; 4591 info.right = right; 4592 info.bottom = bottom; 4593 4594 final Message msg = Message.obtain(); 4595 msg.what = AttachInfo.INVALIDATE_RECT_MSG; 4596 msg.obj = info; 4597 mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 4598 } 4599 } 4600 4601 /** 4602 * Called by a parent to request that a child update its values for mScrollX 4603 * and mScrollY if necessary. This will typically be done if the child is 4604 * animating a scroll using a {@link android.widget.Scroller Scroller} 4605 * object. 4606 */ 4607 public void computeScroll() { 4608 } 4609 4610 /** 4611 * <p>Indicate whether the horizontal edges are faded when the view is 4612 * scrolled horizontally.</p> 4613 * 4614 * @return true if the horizontal edges should are faded on scroll, false 4615 * otherwise 4616 * 4617 * @see #setHorizontalFadingEdgeEnabled(boolean) 4618 * @attr ref android.R.styleable#View_fadingEdge 4619 */ 4620 public boolean isHorizontalFadingEdgeEnabled() { 4621 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 4622 } 4623 4624 /** 4625 * <p>Define whether the horizontal edges should be faded when this view 4626 * is scrolled horizontally.</p> 4627 * 4628 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 4629 * be faded when the view is scrolled 4630 * horizontally 4631 * 4632 * @see #isHorizontalFadingEdgeEnabled() 4633 * @attr ref android.R.styleable#View_fadingEdge 4634 */ 4635 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 4636 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 4637 if (horizontalFadingEdgeEnabled) { 4638 initScrollCache(); 4639 } 4640 4641 mViewFlags ^= FADING_EDGE_HORIZONTAL; 4642 } 4643 } 4644 4645 /** 4646 * <p>Indicate whether the vertical edges are faded when the view is 4647 * scrolled horizontally.</p> 4648 * 4649 * @return true if the vertical edges should are faded on scroll, false 4650 * otherwise 4651 * 4652 * @see #setVerticalFadingEdgeEnabled(boolean) 4653 * @attr ref android.R.styleable#View_fadingEdge 4654 */ 4655 public boolean isVerticalFadingEdgeEnabled() { 4656 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 4657 } 4658 4659 /** 4660 * <p>Define whether the vertical edges should be faded when this view 4661 * is scrolled vertically.</p> 4662 * 4663 * @param verticalFadingEdgeEnabled true if the vertical edges should 4664 * be faded when the view is scrolled 4665 * vertically 4666 * 4667 * @see #isVerticalFadingEdgeEnabled() 4668 * @attr ref android.R.styleable#View_fadingEdge 4669 */ 4670 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 4671 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 4672 if (verticalFadingEdgeEnabled) { 4673 initScrollCache(); 4674 } 4675 4676 mViewFlags ^= FADING_EDGE_VERTICAL; 4677 } 4678 } 4679 4680 /** 4681 * Returns the strength, or intensity, of the top faded edge. The strength is 4682 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4683 * returns 0.0 or 1.0 but no value in between. 4684 * 4685 * Subclasses should override this method to provide a smoother fade transition 4686 * when scrolling occurs. 4687 * 4688 * @return the intensity of the top fade as a float between 0.0f and 1.0f 4689 */ 4690 protected float getTopFadingEdgeStrength() { 4691 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 4692 } 4693 4694 /** 4695 * Returns the strength, or intensity, of the bottom faded edge. The strength is 4696 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4697 * returns 0.0 or 1.0 but no value in between. 4698 * 4699 * Subclasses should override this method to provide a smoother fade transition 4700 * when scrolling occurs. 4701 * 4702 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 4703 */ 4704 protected float getBottomFadingEdgeStrength() { 4705 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 4706 computeVerticalScrollRange() ? 1.0f : 0.0f; 4707 } 4708 4709 /** 4710 * Returns the strength, or intensity, of the left faded edge. The strength is 4711 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4712 * returns 0.0 or 1.0 but no value in between. 4713 * 4714 * Subclasses should override this method to provide a smoother fade transition 4715 * when scrolling occurs. 4716 * 4717 * @return the intensity of the left fade as a float between 0.0f and 1.0f 4718 */ 4719 protected float getLeftFadingEdgeStrength() { 4720 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 4721 } 4722 4723 /** 4724 * Returns the strength, or intensity, of the right faded edge. The strength is 4725 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4726 * returns 0.0 or 1.0 but no value in between. 4727 * 4728 * Subclasses should override this method to provide a smoother fade transition 4729 * when scrolling occurs. 4730 * 4731 * @return the intensity of the right fade as a float between 0.0f and 1.0f 4732 */ 4733 protected float getRightFadingEdgeStrength() { 4734 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 4735 computeHorizontalScrollRange() ? 1.0f : 0.0f; 4736 } 4737 4738 /** 4739 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 4740 * scrollbar is not drawn by default.</p> 4741 * 4742 * @return true if the horizontal scrollbar should be painted, false 4743 * otherwise 4744 * 4745 * @see #setHorizontalScrollBarEnabled(boolean) 4746 */ 4747 public boolean isHorizontalScrollBarEnabled() { 4748 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 4749 } 4750 4751 /** 4752 * <p>Define whether the horizontal scrollbar should be drawn or not. The 4753 * scrollbar is not drawn by default.</p> 4754 * 4755 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 4756 * be painted 4757 * 4758 * @see #isHorizontalScrollBarEnabled() 4759 */ 4760 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 4761 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 4762 mViewFlags ^= SCROLLBARS_HORIZONTAL; 4763 recomputePadding(); 4764 } 4765 } 4766 4767 /** 4768 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 4769 * scrollbar is not drawn by default.</p> 4770 * 4771 * @return true if the vertical scrollbar should be painted, false 4772 * otherwise 4773 * 4774 * @see #setVerticalScrollBarEnabled(boolean) 4775 */ 4776 public boolean isVerticalScrollBarEnabled() { 4777 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 4778 } 4779 4780 /** 4781 * <p>Define whether the vertical scrollbar should be drawn or not. The 4782 * scrollbar is not drawn by default.</p> 4783 * 4784 * @param verticalScrollBarEnabled true if the vertical scrollbar should 4785 * be painted 4786 * 4787 * @see #isVerticalScrollBarEnabled() 4788 */ 4789 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 4790 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 4791 mViewFlags ^= SCROLLBARS_VERTICAL; 4792 recomputePadding(); 4793 } 4794 } 4795 4796 private void recomputePadding() { 4797 setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 4798 } 4799 4800 /** 4801 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 4802 * inset. When inset, they add to the padding of the view. And the scrollbars 4803 * can be drawn inside the padding area or on the edge of the view. For example, 4804 * if a view has a background drawable and you want to draw the scrollbars 4805 * inside the padding specified by the drawable, you can use 4806 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 4807 * appear at the edge of the view, ignoring the padding, then you can use 4808 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 4809 * @param style the style of the scrollbars. Should be one of 4810 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 4811 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 4812 * @see #SCROLLBARS_INSIDE_OVERLAY 4813 * @see #SCROLLBARS_INSIDE_INSET 4814 * @see #SCROLLBARS_OUTSIDE_OVERLAY 4815 * @see #SCROLLBARS_OUTSIDE_INSET 4816 */ 4817 public void setScrollBarStyle(int style) { 4818 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 4819 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 4820 recomputePadding(); 4821 } 4822 } 4823 4824 /** 4825 * <p>Returns the current scrollbar style.</p> 4826 * @return the current scrollbar style 4827 * @see #SCROLLBARS_INSIDE_OVERLAY 4828 * @see #SCROLLBARS_INSIDE_INSET 4829 * @see #SCROLLBARS_OUTSIDE_OVERLAY 4830 * @see #SCROLLBARS_OUTSIDE_INSET 4831 */ 4832 public int getScrollBarStyle() { 4833 return mViewFlags & SCROLLBARS_STYLE_MASK; 4834 } 4835 4836 /** 4837 * <p>Compute the horizontal range that the horizontal scrollbar 4838 * represents.</p> 4839 * 4840 * <p>The range is expressed in arbitrary units that must be the same as the 4841 * units used by {@link #computeHorizontalScrollExtent()} and 4842 * {@link #computeHorizontalScrollOffset()}.</p> 4843 * 4844 * <p>The default range is the drawing width of this view.</p> 4845 * 4846 * @return the total horizontal range represented by the horizontal 4847 * scrollbar 4848 * 4849 * @see #computeHorizontalScrollExtent() 4850 * @see #computeHorizontalScrollOffset() 4851 * @see android.widget.ScrollBarDrawable 4852 */ 4853 protected int computeHorizontalScrollRange() { 4854 return getWidth(); 4855 } 4856 4857 /** 4858 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 4859 * within the horizontal range. This value is used to compute the position 4860 * of the thumb within the scrollbar's track.</p> 4861 * 4862 * <p>The range is expressed in arbitrary units that must be the same as the 4863 * units used by {@link #computeHorizontalScrollRange()} and 4864 * {@link #computeHorizontalScrollExtent()}.</p> 4865 * 4866 * <p>The default offset is the scroll offset of this view.</p> 4867 * 4868 * @return the horizontal offset of the scrollbar's thumb 4869 * 4870 * @see #computeHorizontalScrollRange() 4871 * @see #computeHorizontalScrollExtent() 4872 * @see android.widget.ScrollBarDrawable 4873 */ 4874 protected int computeHorizontalScrollOffset() { 4875 return mScrollX; 4876 } 4877 4878 /** 4879 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 4880 * within the horizontal range. This value is used to compute the length 4881 * of the thumb within the scrollbar's track.</p> 4882 * 4883 * <p>The range is expressed in arbitrary units that must be the same as the 4884 * units used by {@link #computeHorizontalScrollRange()} and 4885 * {@link #computeHorizontalScrollOffset()}.</p> 4886 * 4887 * <p>The default extent is the drawing width of this view.</p> 4888 * 4889 * @return the horizontal extent of the scrollbar's thumb 4890 * 4891 * @see #computeHorizontalScrollRange() 4892 * @see #computeHorizontalScrollOffset() 4893 * @see android.widget.ScrollBarDrawable 4894 */ 4895 protected int computeHorizontalScrollExtent() { 4896 return getWidth(); 4897 } 4898 4899 /** 4900 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 4901 * 4902 * <p>The range is expressed in arbitrary units that must be the same as the 4903 * units used by {@link #computeVerticalScrollExtent()} and 4904 * {@link #computeVerticalScrollOffset()}.</p> 4905 * 4906 * @return the total vertical range represented by the vertical scrollbar 4907 * 4908 * <p>The default range is the drawing height of this view.</p> 4909 * 4910 * @see #computeVerticalScrollExtent() 4911 * @see #computeVerticalScrollOffset() 4912 * @see android.widget.ScrollBarDrawable 4913 */ 4914 protected int computeVerticalScrollRange() { 4915 return getHeight(); 4916 } 4917 4918 /** 4919 * <p>Compute the vertical offset of the vertical scrollbar's thumb 4920 * within the horizontal range. This value is used to compute the position 4921 * of the thumb within the scrollbar's track.</p> 4922 * 4923 * <p>The range is expressed in arbitrary units that must be the same as the 4924 * units used by {@link #computeVerticalScrollRange()} and 4925 * {@link #computeVerticalScrollExtent()}.</p> 4926 * 4927 * <p>The default offset is the scroll offset of this view.</p> 4928 * 4929 * @return the vertical offset of the scrollbar's thumb 4930 * 4931 * @see #computeVerticalScrollRange() 4932 * @see #computeVerticalScrollExtent() 4933 * @see android.widget.ScrollBarDrawable 4934 */ 4935 protected int computeVerticalScrollOffset() { 4936 return mScrollY; 4937 } 4938 4939 /** 4940 * <p>Compute the vertical extent of the horizontal scrollbar's thumb 4941 * within the vertical range. This value is used to compute the length 4942 * of the thumb within the scrollbar's track.</p> 4943 * 4944 * <p>The range is expressed in arbitrary units that must be the same as the 4945 * units used by {@link #computeHorizontalScrollRange()} and 4946 * {@link #computeVerticalScrollOffset()}.</p> 4947 * 4948 * <p>The default extent is the drawing height of this view.</p> 4949 * 4950 * @return the vertical extent of the scrollbar's thumb 4951 * 4952 * @see #computeVerticalScrollRange() 4953 * @see #computeVerticalScrollOffset() 4954 * @see android.widget.ScrollBarDrawable 4955 */ 4956 protected int computeVerticalScrollExtent() { 4957 return getHeight(); 4958 } 4959 4960 /** 4961 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 4962 * scrollbars are painted only if they have been awakened first.</p> 4963 * 4964 * @param canvas the canvas on which to draw the scrollbars 4965 */ 4966 private void onDrawScrollBars(Canvas canvas) { 4967 // scrollbars are drawn only when the animation is running 4968 final ScrollabilityCache cache = mScrollCache; 4969 if (cache != null) { 4970 final int viewFlags = mViewFlags; 4971 4972 final boolean drawHorizontalScrollBar = 4973 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 4974 final boolean drawVerticalScrollBar = 4975 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 4976 && !isVerticalScrollBarHidden(); 4977 4978 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 4979 final int width = mRight - mLeft; 4980 final int height = mBottom - mTop; 4981 4982 final ScrollBarDrawable scrollBar = cache.scrollBar; 4983 int size = scrollBar.getSize(false); 4984 if (size <= 0) { 4985 size = cache.scrollBarSize; 4986 } 4987 4988 if (drawHorizontalScrollBar) { 4989 onDrawHorizontalScrollBar(canvas, scrollBar, width, height, size); 4990 } 4991 4992 if (drawVerticalScrollBar) { 4993 onDrawVerticalScrollBar(canvas, scrollBar, width, height, size); 4994 } 4995 } 4996 } 4997 } 4998 4999 /** 5000 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 5001 * FastScroller is visible. 5002 * @return whether to temporarily hide the vertical scrollbar 5003 * @hide 5004 */ 5005 protected boolean isVerticalScrollBarHidden() { 5006 return false; 5007 } 5008 5009 /** 5010 * <p>Draw the horizontal scrollbar if 5011 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 5012 * 5013 * <p>The length of the scrollbar and its thumb is computed according to the 5014 * values returned by {@link #computeHorizontalScrollRange()}, 5015 * {@link #computeHorizontalScrollExtent()} and 5016 * {@link #computeHorizontalScrollOffset()}. Refer to 5017 * {@link android.widget.ScrollBarDrawable} for more information about how 5018 * these values relate to each other.</p> 5019 * 5020 * @param canvas the canvas on which to draw the scrollbar 5021 * @param scrollBar the scrollbar's drawable 5022 * @param width the width of the drawing surface 5023 * @param height the height of the drawing surface 5024 * @param size the size of the scrollbar 5025 * 5026 * @see #isHorizontalScrollBarEnabled() 5027 * @see #computeHorizontalScrollRange() 5028 * @see #computeHorizontalScrollExtent() 5029 * @see #computeHorizontalScrollOffset() 5030 * @see android.widget.ScrollBarDrawable 5031 */ 5032 private void onDrawHorizontalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, 5033 int height, int size) { 5034 5035 final int viewFlags = mViewFlags; 5036 final int scrollX = mScrollX; 5037 final int scrollY = mScrollY; 5038 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 5039 final int top = scrollY + height - size - (mUserPaddingBottom & inside); 5040 5041 final int verticalScrollBarGap = 5042 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ? 5043 getVerticalScrollbarWidth() : 0; 5044 5045 scrollBar.setBounds(scrollX + (mPaddingLeft & inside), top, 5046 scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size); 5047 scrollBar.setParameters( 5048 computeHorizontalScrollRange(), 5049 computeHorizontalScrollOffset(), 5050 computeHorizontalScrollExtent(), false); 5051 scrollBar.draw(canvas); 5052 } 5053 5054 /** 5055 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 5056 * returns true.</p> 5057 * 5058 * <p>The length of the scrollbar and its thumb is computed according to the 5059 * values returned by {@link #computeVerticalScrollRange()}, 5060 * {@link #computeVerticalScrollExtent()} and 5061 * {@link #computeVerticalScrollOffset()}. Refer to 5062 * {@link android.widget.ScrollBarDrawable} for more information about how 5063 * these values relate to each other.</p> 5064 * 5065 * @param canvas the canvas on which to draw the scrollbar 5066 * @param scrollBar the scrollbar's drawable 5067 * @param width the width of the drawing surface 5068 * @param height the height of the drawing surface 5069 * @param size the size of the scrollbar 5070 * 5071 * @see #isVerticalScrollBarEnabled() 5072 * @see #computeVerticalScrollRange() 5073 * @see #computeVerticalScrollExtent() 5074 * @see #computeVerticalScrollOffset() 5075 * @see android.widget.ScrollBarDrawable 5076 */ 5077 private void onDrawVerticalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, 5078 int height, int size) { 5079 5080 final int scrollX = mScrollX; 5081 final int scrollY = mScrollY; 5082 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 5083 // TODO: Deal with RTL languages to position scrollbar on left 5084 final int left = scrollX + width - size - (mUserPaddingRight & inside); 5085 5086 scrollBar.setBounds(left, scrollY + (mPaddingTop & inside), 5087 left + size, scrollY + height - (mUserPaddingBottom & inside)); 5088 scrollBar.setParameters( 5089 computeVerticalScrollRange(), 5090 computeVerticalScrollOffset(), 5091 computeVerticalScrollExtent(), true); 5092 scrollBar.draw(canvas); 5093 } 5094 5095 /** 5096 * Implement this to do your drawing. 5097 * 5098 * @param canvas the canvas on which the background will be drawn 5099 */ 5100 protected void onDraw(Canvas canvas) { 5101 } 5102 5103 /* 5104 * Caller is responsible for calling requestLayout if necessary. 5105 * (This allows addViewInLayout to not request a new layout.) 5106 */ 5107 void assignParent(ViewParent parent) { 5108 if (mParent == null) { 5109 mParent = parent; 5110 } else if (parent == null) { 5111 mParent = null; 5112 } else { 5113 throw new RuntimeException("view " + this + " being added, but" 5114 + " it already has a parent"); 5115 } 5116 } 5117 5118 /** 5119 * This is called when the view is attached to a window. At this point it 5120 * has a Surface and will start drawing. Note that this function is 5121 * guaranteed to be called before {@link #onDraw}, however it may be called 5122 * any time before the first onDraw -- including before or after 5123 * {@link #onMeasure}. 5124 * 5125 * @see #onDetachedFromWindow() 5126 */ 5127 protected void onAttachedToWindow() { 5128 if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) { 5129 mParent.requestTransparentRegion(this); 5130 } 5131 } 5132 5133 /** 5134 * This is called when the view is detached from a window. At this point it 5135 * no longer has a surface for drawing. 5136 * 5137 * @see #onAttachedToWindow() 5138 */ 5139 protected void onDetachedFromWindow() { 5140 if (mPendingCheckForLongPress != null) { 5141 removeCallbacks(mPendingCheckForLongPress); 5142 } 5143 destroyDrawingCache(); 5144 } 5145 5146 /** 5147 * @return The number of times this view has been attached to a window 5148 */ 5149 protected int getWindowAttachCount() { 5150 return mWindowAttachCount; 5151 } 5152 5153 /** 5154 * Retrieve a unique token identifying the window this view is attached to. 5155 * @return Return the window's token for use in 5156 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 5157 */ 5158 public IBinder getWindowToken() { 5159 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 5160 } 5161 5162 /** 5163 * Retrieve a unique token identifying the top-level "real" window of 5164 * the window that this view is attached to. That is, this is like 5165 * {@link #getWindowToken}, except if the window this view in is a panel 5166 * window (attached to another containing window), then the token of 5167 * the containing window is returned instead. 5168 * 5169 * @return Returns the associated window token, either 5170 * {@link #getWindowToken()} or the containing window's token. 5171 */ 5172 public IBinder getApplicationWindowToken() { 5173 AttachInfo ai = mAttachInfo; 5174 if (ai != null) { 5175 IBinder appWindowToken = ai.mPanelParentWindowToken; 5176 if (appWindowToken == null) { 5177 appWindowToken = ai.mWindowToken; 5178 } 5179 return appWindowToken; 5180 } 5181 return null; 5182 } 5183 5184 /** 5185 * Retrieve private session object this view hierarchy is using to 5186 * communicate with the window manager. 5187 * @return the session object to communicate with the window manager 5188 */ 5189 /*package*/ IWindowSession getWindowSession() { 5190 return mAttachInfo != null ? mAttachInfo.mSession : null; 5191 } 5192 5193 /** 5194 * @param info the {@link android.view.View.AttachInfo} to associated with 5195 * this view 5196 */ 5197 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 5198 //System.out.println("Attached! " + this); 5199 mAttachInfo = info; 5200 mWindowAttachCount++; 5201 if (mFloatingTreeObserver != null) { 5202 info.mTreeObserver.merge(mFloatingTreeObserver); 5203 mFloatingTreeObserver = null; 5204 } 5205 if ((mPrivateFlags&SCROLL_CONTAINER) != 0) { 5206 mAttachInfo.mScrollContainers.add(this); 5207 mPrivateFlags |= SCROLL_CONTAINER_ADDED; 5208 } 5209 performCollectViewAttributes(visibility); 5210 onAttachedToWindow(); 5211 int vis = info.mWindowVisibility; 5212 if (vis != GONE) { 5213 onWindowVisibilityChanged(vis); 5214 } 5215 } 5216 5217 void dispatchDetachedFromWindow() { 5218 //System.out.println("Detached! " + this); 5219 AttachInfo info = mAttachInfo; 5220 if (info != null) { 5221 int vis = info.mWindowVisibility; 5222 if (vis != GONE) { 5223 onWindowVisibilityChanged(GONE); 5224 } 5225 } 5226 5227 onDetachedFromWindow(); 5228 if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { 5229 mAttachInfo.mScrollContainers.remove(this); 5230 mPrivateFlags &= ~SCROLL_CONTAINER_ADDED; 5231 } 5232 mAttachInfo = null; 5233 } 5234 5235 /** 5236 * Store this view hierarchy's frozen state into the given container. 5237 * 5238 * @param container The SparseArray in which to save the view's state. 5239 * 5240 * @see #restoreHierarchyState 5241 * @see #dispatchSaveInstanceState 5242 * @see #onSaveInstanceState 5243 */ 5244 public void saveHierarchyState(SparseArray<Parcelable> container) { 5245 dispatchSaveInstanceState(container); 5246 } 5247 5248 /** 5249 * Called by {@link #saveHierarchyState} to store the state for this view and its children. 5250 * May be overridden to modify how freezing happens to a view's children; for example, some 5251 * views may want to not store state for their children. 5252 * 5253 * @param container The SparseArray in which to save the view's state. 5254 * 5255 * @see #dispatchRestoreInstanceState 5256 * @see #saveHierarchyState 5257 * @see #onSaveInstanceState 5258 */ 5259 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 5260 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 5261 mPrivateFlags &= ~SAVE_STATE_CALLED; 5262 Parcelable state = onSaveInstanceState(); 5263 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 5264 throw new IllegalStateException( 5265 "Derived class did not call super.onSaveInstanceState()"); 5266 } 5267 if (state != null) { 5268 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 5269 // + ": " + state); 5270 container.put(mID, state); 5271 } 5272 } 5273 } 5274 5275 /** 5276 * Hook allowing a view to generate a representation of its internal state 5277 * that can later be used to create a new instance with that same state. 5278 * This state should only contain information that is not persistent or can 5279 * not be reconstructed later. For example, you will never store your 5280 * current position on screen because that will be computed again when a 5281 * new instance of the view is placed in its view hierarchy. 5282 * <p> 5283 * Some examples of things you may store here: the current cursor position 5284 * in a text view (but usually not the text itself since that is stored in a 5285 * content provider or other persistent storage), the currently selected 5286 * item in a list view. 5287 * 5288 * @return Returns a Parcelable object containing the view's current dynamic 5289 * state, or null if there is nothing interesting to save. The 5290 * default implementation returns null. 5291 * @see #onRestoreInstanceState 5292 * @see #saveHierarchyState 5293 * @see #dispatchSaveInstanceState 5294 * @see #setSaveEnabled(boolean) 5295 */ 5296 protected Parcelable onSaveInstanceState() { 5297 mPrivateFlags |= SAVE_STATE_CALLED; 5298 return BaseSavedState.EMPTY_STATE; 5299 } 5300 5301 /** 5302 * Restore this view hierarchy's frozen state from the given container. 5303 * 5304 * @param container The SparseArray which holds previously frozen states. 5305 * 5306 * @see #saveHierarchyState 5307 * @see #dispatchRestoreInstanceState 5308 * @see #onRestoreInstanceState 5309 */ 5310 public void restoreHierarchyState(SparseArray<Parcelable> container) { 5311 dispatchRestoreInstanceState(container); 5312 } 5313 5314 /** 5315 * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its 5316 * children. May be overridden to modify how restoreing happens to a view's children; for 5317 * example, some views may want to not store state for their children. 5318 * 5319 * @param container The SparseArray which holds previously saved state. 5320 * 5321 * @see #dispatchSaveInstanceState 5322 * @see #restoreHierarchyState 5323 * @see #onRestoreInstanceState 5324 */ 5325 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 5326 if (mID != NO_ID) { 5327 Parcelable state = container.get(mID); 5328 if (state != null) { 5329 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 5330 // + ": " + state); 5331 mPrivateFlags &= ~SAVE_STATE_CALLED; 5332 onRestoreInstanceState(state); 5333 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 5334 throw new IllegalStateException( 5335 "Derived class did not call super.onRestoreInstanceState()"); 5336 } 5337 } 5338 } 5339 } 5340 5341 /** 5342 * Hook allowing a view to re-apply a representation of its internal state that had previously 5343 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 5344 * null state. 5345 * 5346 * @param state The frozen state that had previously been returned by 5347 * {@link #onSaveInstanceState}. 5348 * 5349 * @see #onSaveInstanceState 5350 * @see #restoreHierarchyState 5351 * @see #dispatchRestoreInstanceState 5352 */ 5353 protected void onRestoreInstanceState(Parcelable state) { 5354 mPrivateFlags |= SAVE_STATE_CALLED; 5355 if (state != BaseSavedState.EMPTY_STATE && state != null) { 5356 throw new IllegalArgumentException("Wrong state class -- expecting View State"); 5357 } 5358 } 5359 5360 /** 5361 * <p>Return the time at which the drawing of the view hierarchy started.</p> 5362 * 5363 * @return the drawing start time in milliseconds 5364 */ 5365 public long getDrawingTime() { 5366 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 5367 } 5368 5369 /** 5370 * <p>Enables or disables the duplication of the parent's state into this view. When 5371 * duplication is enabled, this view gets its drawable state from its parent rather 5372 * than from its own internal properties.</p> 5373 * 5374 * <p>Note: in the current implementation, setting this property to true after the 5375 * view was added to a ViewGroup might have no effect at all. This property should 5376 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 5377 * 5378 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 5379 * property is enabled, an exception will be thrown.</p> 5380 * 5381 * @param enabled True to enable duplication of the parent's drawable state, false 5382 * to disable it. 5383 * 5384 * @see #getDrawableState() 5385 * @see #isDuplicateParentStateEnabled() 5386 */ 5387 public void setDuplicateParentStateEnabled(boolean enabled) { 5388 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 5389 } 5390 5391 /** 5392 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 5393 * 5394 * @return True if this view's drawable state is duplicated from the parent, 5395 * false otherwise 5396 * 5397 * @see #getDrawableState() 5398 * @see #setDuplicateParentStateEnabled(boolean) 5399 */ 5400 public boolean isDuplicateParentStateEnabled() { 5401 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 5402 } 5403 5404 /** 5405 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 5406 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 5407 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 5408 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 5409 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 5410 * null.</p> 5411 * 5412 * @param enabled true to enable the drawing cache, false otherwise 5413 * 5414 * @see #isDrawingCacheEnabled() 5415 * @see #getDrawingCache() 5416 * @see #buildDrawingCache() 5417 */ 5418 public void setDrawingCacheEnabled(boolean enabled) { 5419 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 5420 } 5421 5422 /** 5423 * <p>Indicates whether the drawing cache is enabled for this view.</p> 5424 * 5425 * @return true if the drawing cache is enabled 5426 * 5427 * @see #setDrawingCacheEnabled(boolean) 5428 * @see #getDrawingCache() 5429 */ 5430 @ViewDebug.ExportedProperty 5431 public boolean isDrawingCacheEnabled() { 5432 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 5433 } 5434 5435 /** 5436 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 5437 * is null when caching is disabled. If caching is enabled and the cache is not ready, 5438 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 5439 * draw from the cache when the cache is enabled. To benefit from the cache, you must 5440 * request the drawing cache by calling this method and draw it on screen if the 5441 * returned bitmap is not null.</p> 5442 * 5443 * @return a bitmap representing this view or null if cache is disabled 5444 * 5445 * @see #setDrawingCacheEnabled(boolean) 5446 * @see #isDrawingCacheEnabled() 5447 * @see #buildDrawingCache() 5448 * @see #destroyDrawingCache() 5449 */ 5450 public Bitmap getDrawingCache() { 5451 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 5452 return null; 5453 } 5454 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 5455 buildDrawingCache(); 5456 } 5457 return mDrawingCache == null ? null : mDrawingCache.get(); 5458 } 5459 5460 /** 5461 * <p>Frees the resources used by the drawing cache. If you call 5462 * {@link #buildDrawingCache()} manually without calling 5463 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 5464 * should cleanup the cache with this method afterwards.</p> 5465 * 5466 * @see #setDrawingCacheEnabled(boolean) 5467 * @see #buildDrawingCache() 5468 * @see #getDrawingCache() 5469 */ 5470 public void destroyDrawingCache() { 5471 if (mDrawingCache != null) { 5472 final Bitmap bitmap = mDrawingCache.get(); 5473 if (bitmap != null) bitmap.recycle(); 5474 mDrawingCache = null; 5475 } 5476 } 5477 5478 /** 5479 * Setting a solid background color for the drawing cache's bitmaps will improve 5480 * perfromance and memory usage. Note, though that this should only be used if this 5481 * view will always be drawn on top of a solid color. 5482 * 5483 * @param color The background color to use for the drawing cache's bitmap 5484 * 5485 * @see #setDrawingCacheEnabled(boolean) 5486 * @see #buildDrawingCache() 5487 * @see #getDrawingCache() 5488 */ 5489 public void setDrawingCacheBackgroundColor(int color) { 5490 mDrawingCacheBackgroundColor = color; 5491 } 5492 5493 /** 5494 * @see #setDrawingCacheBackgroundColor(int) 5495 * 5496 * @return The background color to used for the drawing cache's bitmap 5497 */ 5498 public int getDrawingCacheBackgroundColor() { 5499 return mDrawingCacheBackgroundColor; 5500 } 5501 5502 /** 5503 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 5504 * 5505 * <p>If you call {@link #buildDrawingCache()} manually without calling 5506 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 5507 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 5508 * 5509 * @see #getDrawingCache() 5510 * @see #destroyDrawingCache() 5511 */ 5512 public void buildDrawingCache() { 5513 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null || 5514 mDrawingCache.get() == null) { 5515 5516 if (ViewDebug.TRACE_HIERARCHY) { 5517 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE); 5518 } 5519 if (ViewRoot.PROFILE_DRAWING) { 5520 EventLog.writeEvent(60002, hashCode()); 5521 } 5522 5523 final int width = mRight - mLeft; 5524 final int height = mBottom - mTop; 5525 5526 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 5527 final boolean opaque = drawingCacheBackgroundColor != 0 || 5528 (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE); 5529 5530 if (width <= 0 || height <= 0 || 5531 (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes 5532 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { 5533 destroyDrawingCache(); 5534 return; 5535 } 5536 5537 boolean clear = true; 5538 Bitmap bitmap = mDrawingCache == null ? null : mDrawingCache.get(); 5539 5540 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 5541 5542 Bitmap.Config quality; 5543 if (!opaque) { 5544 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 5545 case DRAWING_CACHE_QUALITY_AUTO: 5546 quality = Bitmap.Config.ARGB_8888; 5547 break; 5548 case DRAWING_CACHE_QUALITY_LOW: 5549 quality = Bitmap.Config.ARGB_4444; 5550 break; 5551 case DRAWING_CACHE_QUALITY_HIGH: 5552 quality = Bitmap.Config.ARGB_8888; 5553 break; 5554 default: 5555 quality = Bitmap.Config.ARGB_8888; 5556 break; 5557 } 5558 } else { 5559 quality = Bitmap.Config.RGB_565; 5560 } 5561 5562 // Try to cleanup memory 5563 if (bitmap != null) bitmap.recycle(); 5564 5565 try { 5566 bitmap = Bitmap.createBitmap(width, height, quality); 5567 mDrawingCache = new SoftReference<Bitmap>(bitmap); 5568 } catch (OutOfMemoryError e) { 5569 // If there is not enough memory to create the bitmap cache, just 5570 // ignore the issue as bitmap caches are not required to draw the 5571 // view hierarchy 5572 mDrawingCache = null; 5573 return; 5574 } 5575 5576 clear = drawingCacheBackgroundColor != 0; 5577 } 5578 5579 Canvas canvas; 5580 final AttachInfo attachInfo = mAttachInfo; 5581 if (attachInfo != null) { 5582 canvas = attachInfo.mCanvas; 5583 if (canvas == null) { 5584 canvas = new Canvas(); 5585 } 5586 canvas.setBitmap(bitmap); 5587 // Temporarily clobber the cached Canvas in case one of our children 5588 // is also using a drawing cache. Without this, the children would 5589 // steal the canvas by attaching their own bitmap to it and bad, bad 5590 // thing would happen (invisible views, corrupted drawings, etc.) 5591 attachInfo.mCanvas = null; 5592 } else { 5593 // This case should hopefully never or seldom happen 5594 canvas = new Canvas(bitmap); 5595 } 5596 5597 if (clear) { 5598 bitmap.eraseColor(drawingCacheBackgroundColor); 5599 } 5600 5601 computeScroll(); 5602 final int restoreCount = canvas.save(); 5603 canvas.translate(-mScrollX, -mScrollY); 5604 5605 mPrivateFlags |= DRAWN; 5606 5607 // Fast path for layouts with no backgrounds 5608 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 5609 if (ViewDebug.TRACE_HIERARCHY) { 5610 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 5611 } 5612 dispatchDraw(canvas); 5613 } else { 5614 draw(canvas); 5615 } 5616 5617 canvas.restoreToCount(restoreCount); 5618 5619 if (attachInfo != null) { 5620 // Restore the cached Canvas for our siblings 5621 attachInfo.mCanvas = canvas; 5622 } 5623 mPrivateFlags |= DRAWING_CACHE_VALID; 5624 } 5625 } 5626 5627 /** 5628 * Indicates whether this View is currently in edit mode. A View is usually 5629 * in edit mode when displayed within a developer tool. For instance, if 5630 * this View is being drawn by a visual user interface builder, this method 5631 * should return true. 5632 * 5633 * Subclasses should check the return value of this method to provide 5634 * different behaviors if their normal behavior might interfere with the 5635 * host environment. For instance: the class spawns a thread in its 5636 * constructor, the drawing code relies on device-specific features, etc. 5637 * 5638 * This method is usually checked in the drawing code of custom widgets. 5639 * 5640 * @return True if this View is in edit mode, false otherwise. 5641 */ 5642 public boolean isInEditMode() { 5643 return false; 5644 } 5645 5646 /** 5647 * If the View draws content inside its padding and enables fading edges, 5648 * it needs to support padding offsets. Padding offsets are added to the 5649 * fading edges to extend the length of the fade so that it covers pixels 5650 * drawn inside the padding. 5651 * 5652 * Subclasses of this class should override this method if they need 5653 * to draw content inside the padding. 5654 * 5655 * @return True if padding offset must be applied, false otherwise. 5656 * 5657 * @see #getLeftPaddingOffset() 5658 * @see #getRightPaddingOffset() 5659 * @see #getTopPaddingOffset() 5660 * @see #getBottomPaddingOffset() 5661 * 5662 * @since CURRENT 5663 */ 5664 protected boolean isPaddingOffsetRequired() { 5665 return false; 5666 } 5667 5668 /** 5669 * Amount by which to extend the left fading region. Called only when 5670 * {@link #isPaddingOffsetRequired()} returns true. 5671 * 5672 * @return The left padding offset in pixels. 5673 * 5674 * @see #isPaddingOffsetRequired() 5675 * 5676 * @since CURRENT 5677 */ 5678 protected int getLeftPaddingOffset() { 5679 return 0; 5680 } 5681 5682 /** 5683 * Amount by which to extend the right fading region. Called only when 5684 * {@link #isPaddingOffsetRequired()} returns true. 5685 * 5686 * @return The right padding offset in pixels. 5687 * 5688 * @see #isPaddingOffsetRequired() 5689 * 5690 * @since CURRENT 5691 */ 5692 protected int getRightPaddingOffset() { 5693 return 0; 5694 } 5695 5696 /** 5697 * Amount by which to extend the top fading region. Called only when 5698 * {@link #isPaddingOffsetRequired()} returns true. 5699 * 5700 * @return The top padding offset in pixels. 5701 * 5702 * @see #isPaddingOffsetRequired() 5703 * 5704 * @since CURRENT 5705 */ 5706 protected int getTopPaddingOffset() { 5707 return 0; 5708 } 5709 5710 /** 5711 * Amount by which to extend the bottom fading region. Called only when 5712 * {@link #isPaddingOffsetRequired()} returns true. 5713 * 5714 * @return The bottom padding offset in pixels. 5715 * 5716 * @see #isPaddingOffsetRequired() 5717 * 5718 * @since CURRENT 5719 */ 5720 protected int getBottomPaddingOffset() { 5721 return 0; 5722 } 5723 5724 /** 5725 * Manually render this view (and all of its children) to the given Canvas. 5726 * The view must have already done a full layout before this function is 5727 * called. When implementing a view, do not override this method; instead, 5728 * you should implement {@link #onDraw}. 5729 * 5730 * @param canvas The Canvas to which the View is rendered. 5731 */ 5732 public void draw(Canvas canvas) { 5733 if (ViewDebug.TRACE_HIERARCHY) { 5734 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 5735 } 5736 5737 mPrivateFlags |= DRAWN; 5738 5739 /* 5740 * Draw traversal performs several drawing steps which must be executed 5741 * in the appropriate order: 5742 * 5743 * 1. Draw the background 5744 * 2. If necessary, save the canvas' layers to prepare for fading 5745 * 3. Draw view's content 5746 * 4. Draw children 5747 * 5. If necessary, draw the fading edges and restore layers 5748 * 6. Draw decorations (scrollbars for instance) 5749 */ 5750 5751 // Step 1, draw the background, if needed 5752 int saveCount; 5753 5754 final Drawable background = mBGDrawable; 5755 if (background != null) { 5756 final int scrollX = mScrollX; 5757 final int scrollY = mScrollY; 5758 5759 if (mBackgroundSizeChanged) { 5760 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 5761 mBackgroundSizeChanged = false; 5762 } 5763 5764 if ((scrollX | scrollY) == 0) { 5765 background.draw(canvas); 5766 } else { 5767 canvas.translate(scrollX, scrollY); 5768 background.draw(canvas); 5769 canvas.translate(-scrollX, -scrollY); 5770 } 5771 } 5772 5773 // skip step 2 & 5 if possible (common case) 5774 final int viewFlags = mViewFlags; 5775 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 5776 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 5777 if (!verticalEdges && !horizontalEdges) { 5778 // Step 3, draw the content 5779 onDraw(canvas); 5780 5781 // Step 4, draw the children 5782 dispatchDraw(canvas); 5783 5784 // Step 6, draw decorations (scrollbars) 5785 onDrawScrollBars(canvas); 5786 5787 // we're done... 5788 return; 5789 } 5790 5791 /* 5792 * Here we do the full fledged routine... 5793 * (this is an uncommon case where speed matters less, 5794 * this is why we repeat some of the tests that have been 5795 * done above) 5796 */ 5797 5798 boolean drawTop = false; 5799 boolean drawBottom = false; 5800 boolean drawLeft = false; 5801 boolean drawRight = false; 5802 5803 float topFadeStrength = 0.0f; 5804 float bottomFadeStrength = 0.0f; 5805 float leftFadeStrength = 0.0f; 5806 float rightFadeStrength = 0.0f; 5807 5808 // Step 2, save the canvas' layers 5809 int paddingLeft = mPaddingLeft; 5810 int paddingTop = mPaddingTop; 5811 5812 final boolean offsetRequired = isPaddingOffsetRequired(); 5813 if (offsetRequired) { 5814 paddingLeft += getLeftPaddingOffset(); 5815 paddingTop += getTopPaddingOffset(); 5816 } 5817 5818 int left = mScrollX + paddingLeft; 5819 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 5820 int top = mScrollY + paddingTop; 5821 int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop; 5822 5823 if (offsetRequired) { 5824 right += getRightPaddingOffset(); 5825 bottom += getBottomPaddingOffset(); 5826 } 5827 5828 final ScrollabilityCache scrollabilityCache = mScrollCache; 5829 int length = scrollabilityCache.fadingEdgeLength; 5830 5831 // clip the fade length if top and bottom fades overlap 5832 // overlapping fades produce odd-looking artifacts 5833 if (verticalEdges && (top + length > bottom - length)) { 5834 length = (bottom - top) / 2; 5835 } 5836 5837 // also clip horizontal fades if necessary 5838 if (horizontalEdges && (left + length > right - length)) { 5839 length = (right - left) / 2; 5840 } 5841 5842 if (verticalEdges) { 5843 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 5844 drawTop = topFadeStrength >= 0.0f; 5845 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 5846 drawBottom = bottomFadeStrength >= 0.0f; 5847 } 5848 5849 if (horizontalEdges) { 5850 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 5851 drawLeft = leftFadeStrength >= 0.0f; 5852 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 5853 drawRight = rightFadeStrength >= 0.0f; 5854 } 5855 5856 saveCount = canvas.getSaveCount(); 5857 5858 int solidColor = getSolidColor(); 5859 if (solidColor == 0) { 5860 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 5861 5862 if (drawTop) { 5863 canvas.saveLayer(left, top, right, top + length, null, flags); 5864 } 5865 5866 if (drawBottom) { 5867 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 5868 } 5869 5870 if (drawLeft) { 5871 canvas.saveLayer(left, top, left + length, bottom, null, flags); 5872 } 5873 5874 if (drawRight) { 5875 canvas.saveLayer(right - length, top, right, bottom, null, flags); 5876 } 5877 } else { 5878 scrollabilityCache.setFadeColor(solidColor); 5879 } 5880 5881 // Step 3, draw the content 5882 onDraw(canvas); 5883 5884 // Step 4, draw the children 5885 dispatchDraw(canvas); 5886 5887 // Step 5, draw the fade effect and restore layers 5888 final Paint p = scrollabilityCache.paint; 5889 final Matrix matrix = scrollabilityCache.matrix; 5890 final Shader fade = scrollabilityCache.shader; 5891 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 5892 5893 if (drawTop) { 5894 matrix.setScale(1, fadeHeight * topFadeStrength); 5895 matrix.postTranslate(left, top); 5896 fade.setLocalMatrix(matrix); 5897 canvas.drawRect(left, top, right, top + length, p); 5898 } 5899 5900 if (drawBottom) { 5901 matrix.setScale(1, fadeHeight * bottomFadeStrength); 5902 matrix.postRotate(180); 5903 matrix.postTranslate(left, bottom); 5904 fade.setLocalMatrix(matrix); 5905 canvas.drawRect(left, bottom - length, right, bottom, p); 5906 } 5907 5908 if (drawLeft) { 5909 matrix.setScale(1, fadeHeight * leftFadeStrength); 5910 matrix.postRotate(-90); 5911 matrix.postTranslate(left, top); 5912 fade.setLocalMatrix(matrix); 5913 canvas.drawRect(left, top, left + length, bottom, p); 5914 } 5915 5916 if (drawRight) { 5917 matrix.setScale(1, fadeHeight * rightFadeStrength); 5918 matrix.postRotate(90); 5919 matrix.postTranslate(right, top); 5920 fade.setLocalMatrix(matrix); 5921 canvas.drawRect(right - length, top, right, bottom, p); 5922 } 5923 5924 canvas.restoreToCount(saveCount); 5925 5926 // Step 6, draw decorations (scrollbars) 5927 onDrawScrollBars(canvas); 5928 } 5929 5930 /** 5931 * Override this if your view is known to always be drawn on top of a solid color background, 5932 * and needs to draw fading edges. Returning a non-zero color enables the view system to 5933 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 5934 * should be set to 0xFF. 5935 * 5936 * @see #setVerticalFadingEdgeEnabled 5937 * @see #setHorizontalFadingEdgeEnabled 5938 * 5939 * @return The known solid color background for this view, or 0 if the color may vary 5940 */ 5941 public int getSolidColor() { 5942 return 0; 5943 } 5944 5945 /** 5946 * Build a human readable string representation of the specified view flags. 5947 * 5948 * @param flags the view flags to convert to a string 5949 * @return a String representing the supplied flags 5950 */ 5951 private static String printFlags(int flags) { 5952 String output = ""; 5953 int numFlags = 0; 5954 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 5955 output += "TAKES_FOCUS"; 5956 numFlags++; 5957 } 5958 5959 switch (flags & VISIBILITY_MASK) { 5960 case INVISIBLE: 5961 if (numFlags > 0) { 5962 output += " "; 5963 } 5964 output += "INVISIBLE"; 5965 // USELESS HERE numFlags++; 5966 break; 5967 case GONE: 5968 if (numFlags > 0) { 5969 output += " "; 5970 } 5971 output += "GONE"; 5972 // USELESS HERE numFlags++; 5973 break; 5974 default: 5975 break; 5976 } 5977 return output; 5978 } 5979 5980 /** 5981 * Build a human readable string representation of the specified private 5982 * view flags. 5983 * 5984 * @param privateFlags the private view flags to convert to a string 5985 * @return a String representing the supplied flags 5986 */ 5987 private static String printPrivateFlags(int privateFlags) { 5988 String output = ""; 5989 int numFlags = 0; 5990 5991 if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) { 5992 output += "WANTS_FOCUS"; 5993 numFlags++; 5994 } 5995 5996 if ((privateFlags & FOCUSED) == FOCUSED) { 5997 if (numFlags > 0) { 5998 output += " "; 5999 } 6000 output += "FOCUSED"; 6001 numFlags++; 6002 } 6003 6004 if ((privateFlags & SELECTED) == SELECTED) { 6005 if (numFlags > 0) { 6006 output += " "; 6007 } 6008 output += "SELECTED"; 6009 numFlags++; 6010 } 6011 6012 if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) { 6013 if (numFlags > 0) { 6014 output += " "; 6015 } 6016 output += "IS_ROOT_NAMESPACE"; 6017 numFlags++; 6018 } 6019 6020 if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) { 6021 if (numFlags > 0) { 6022 output += " "; 6023 } 6024 output += "HAS_BOUNDS"; 6025 numFlags++; 6026 } 6027 6028 if ((privateFlags & DRAWN) == DRAWN) { 6029 if (numFlags > 0) { 6030 output += " "; 6031 } 6032 output += "DRAWN"; 6033 // USELESS HERE numFlags++; 6034 } 6035 return output; 6036 } 6037 6038 /** 6039 * <p>Indicates whether or not this view's layout will be requested during 6040 * the next hierarchy layout pass.</p> 6041 * 6042 * @return true if the layout will be forced during next layout pass 6043 */ 6044 public boolean isLayoutRequested() { 6045 return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT; 6046 } 6047 6048 /** 6049 * Assign a size and position to a view and all of its 6050 * descendants 6051 * 6052 * <p>This is the second phase of the layout mechanism. 6053 * (The first is measuring). In this phase, each parent calls 6054 * layout on all of its children to position them. 6055 * This is typically done using the child measurements 6056 * that were stored in the measure pass(). 6057 * 6058 * Derived classes with children should override 6059 * onLayout. In that method, they should 6060 * call layout on each of their their children. 6061 * 6062 * @param l Left position, relative to parent 6063 * @param t Top position, relative to parent 6064 * @param r Right position, relative to parent 6065 * @param b Bottom position, relative to parent 6066 */ 6067 public final void layout(int l, int t, int r, int b) { 6068 boolean changed = setFrame(l, t, r, b); 6069 if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) { 6070 if (ViewDebug.TRACE_HIERARCHY) { 6071 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT); 6072 } 6073 6074 onLayout(changed, l, t, r, b); 6075 mPrivateFlags &= ~LAYOUT_REQUIRED; 6076 } 6077 mPrivateFlags &= ~FORCE_LAYOUT; 6078 } 6079 6080 /** 6081 * Called from layout when this view should 6082 * assign a size and position to each of its children. 6083 * 6084 * Derived classes with children should override 6085 * this method and call layout on each of 6086 * their their children. 6087 * @param changed This is a new size or position for this view 6088 * @param left Left position, relative to parent 6089 * @param top Top position, relative to parent 6090 * @param right Right position, relative to parent 6091 * @param bottom Bottom position, relative to parent 6092 */ 6093 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 6094 } 6095 6096 /** 6097 * Assign a size and position to this view. 6098 * 6099 * This is called from layout. 6100 * 6101 * @param left Left position, relative to parent 6102 * @param top Top position, relative to parent 6103 * @param right Right position, relative to parent 6104 * @param bottom Bottom position, relative to parent 6105 * @return true if the new size and position are different than the 6106 * previous ones 6107 * {@hide} 6108 */ 6109 protected boolean setFrame(int left, int top, int right, int bottom) { 6110 boolean changed = false; 6111 6112 if (DBG) { 6113 System.out.println(this + " View.setFrame(" + left + "," + top + "," 6114 + right + "," + bottom + ")"); 6115 } 6116 6117 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 6118 changed = true; 6119 6120 // Remember our drawn bit 6121 int drawn = mPrivateFlags & DRAWN; 6122 6123 // Invalidate our old position 6124 invalidate(); 6125 6126 6127 int oldWidth = mRight - mLeft; 6128 int oldHeight = mBottom - mTop; 6129 6130 mLeft = left; 6131 mTop = top; 6132 mRight = right; 6133 mBottom = bottom; 6134 6135 mPrivateFlags |= HAS_BOUNDS; 6136 6137 int newWidth = right - left; 6138 int newHeight = bottom - top; 6139 6140 if (newWidth != oldWidth || newHeight != oldHeight) { 6141 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 6142 } 6143 6144 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { 6145 // If we are visible, force the DRAWN bit to on so that 6146 // this invalidate will go through (at least to our parent). 6147 // This is because someone may have invalidated this view 6148 // before this call to setFrame came in, therby clearing 6149 // the DRAWN bit. 6150 mPrivateFlags |= DRAWN; 6151 invalidate(); 6152 } 6153 6154 // Reset drawn bit to original value (invalidate turns it off) 6155 mPrivateFlags |= drawn; 6156 6157 mBackgroundSizeChanged = true; 6158 } 6159 return changed; 6160 } 6161 6162 /** 6163 * Finalize inflating a view from XML. This is called as the last phase 6164 * of inflation, after all child views have been added. 6165 * 6166 * <p>Even if the subclass overrides onFinishInflate, they should always be 6167 * sure to call the super method, so that we get called. 6168 */ 6169 protected void onFinishInflate() { 6170 } 6171 6172 /** 6173 * Returns the resources associated with this view. 6174 * 6175 * @return Resources object. 6176 */ 6177 public Resources getResources() { 6178 return mResources; 6179 } 6180 6181 /** 6182 * Invalidates the specified Drawable. 6183 * 6184 * @param drawable the drawable to invalidate 6185 */ 6186 public void invalidateDrawable(Drawable drawable) { 6187 if (verifyDrawable(drawable)) { 6188 final Rect dirty = drawable.getBounds(); 6189 final int scrollX = mScrollX; 6190 final int scrollY = mScrollY; 6191 6192 invalidate(dirty.left + scrollX, dirty.top + scrollY, 6193 dirty.right + scrollX, dirty.bottom + scrollY); 6194 } 6195 } 6196 6197 /** 6198 * Schedules an action on a drawable to occur at a specified time. 6199 * 6200 * @param who the recipient of the action 6201 * @param what the action to run on the drawable 6202 * @param when the time at which the action must occur. Uses the 6203 * {@link SystemClock#uptimeMillis} timebase. 6204 */ 6205 public void scheduleDrawable(Drawable who, Runnable what, long when) { 6206 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 6207 mAttachInfo.mHandler.postAtTime(what, who, when); 6208 } 6209 } 6210 6211 /** 6212 * Cancels a scheduled action on a drawable. 6213 * 6214 * @param who the recipient of the action 6215 * @param what the action to cancel 6216 */ 6217 public void unscheduleDrawable(Drawable who, Runnable what) { 6218 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 6219 mAttachInfo.mHandler.removeCallbacks(what, who); 6220 } 6221 } 6222 6223 /** 6224 * Unschedule any events associated with the given Drawable. This can be 6225 * used when selecting a new Drawable into a view, so that the previous 6226 * one is completely unscheduled. 6227 * 6228 * @param who The Drawable to unschedule. 6229 * 6230 * @see #drawableStateChanged 6231 */ 6232 public void unscheduleDrawable(Drawable who) { 6233 if (mAttachInfo != null) { 6234 mAttachInfo.mHandler.removeCallbacksAndMessages(who); 6235 } 6236 } 6237 6238 /** 6239 * If your view subclass is displaying its own Drawable objects, it should 6240 * override this function and return true for any Drawable it is 6241 * displaying. This allows animations for those drawables to be 6242 * scheduled. 6243 * 6244 * <p>Be sure to call through to the super class when overriding this 6245 * function. 6246 * 6247 * @param who The Drawable to verify. Return true if it is one you are 6248 * displaying, else return the result of calling through to the 6249 * super class. 6250 * 6251 * @return boolean If true than the Drawable is being displayed in the 6252 * view; else false and it is not allowed to animate. 6253 * 6254 * @see #unscheduleDrawable 6255 * @see #drawableStateChanged 6256 */ 6257 protected boolean verifyDrawable(Drawable who) { 6258 return who == mBGDrawable; 6259 } 6260 6261 /** 6262 * This function is called whenever the state of the view changes in such 6263 * a way that it impacts the state of drawables being shown. 6264 * 6265 * <p>Be sure to call through to the superclass when overriding this 6266 * function. 6267 * 6268 * @see Drawable#setState 6269 */ 6270 protected void drawableStateChanged() { 6271 Drawable d = mBGDrawable; 6272 if (d != null && d.isStateful()) { 6273 d.setState(getDrawableState()); 6274 } 6275 } 6276 6277 /** 6278 * Call this to force a view to update its drawable state. This will cause 6279 * drawableStateChanged to be called on this view. Views that are interested 6280 * in the new state should call getDrawableState. 6281 * 6282 * @see #drawableStateChanged 6283 * @see #getDrawableState 6284 */ 6285 public void refreshDrawableState() { 6286 mPrivateFlags |= DRAWABLE_STATE_DIRTY; 6287 drawableStateChanged(); 6288 6289 ViewParent parent = mParent; 6290 if (parent != null) { 6291 parent.childDrawableStateChanged(this); 6292 } 6293 } 6294 6295 /** 6296 * Return an array of resource IDs of the drawable states representing the 6297 * current state of the view. 6298 * 6299 * @return The current drawable state 6300 * 6301 * @see Drawable#setState 6302 * @see #drawableStateChanged 6303 * @see #onCreateDrawableState 6304 */ 6305 public final int[] getDrawableState() { 6306 if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) { 6307 return mDrawableState; 6308 } else { 6309 mDrawableState = onCreateDrawableState(0); 6310 mPrivateFlags &= ~DRAWABLE_STATE_DIRTY; 6311 return mDrawableState; 6312 } 6313 } 6314 6315 /** 6316 * Generate the new {@link android.graphics.drawable.Drawable} state for 6317 * this view. This is called by the view 6318 * system when the cached Drawable state is determined to be invalid. To 6319 * retrieve the current state, you should use {@link #getDrawableState}. 6320 * 6321 * @param extraSpace if non-zero, this is the number of extra entries you 6322 * would like in the returned array in which you can place your own 6323 * states. 6324 * 6325 * @return Returns an array holding the current {@link Drawable} state of 6326 * the view. 6327 * 6328 * @see #mergeDrawableStates 6329 */ 6330 protected int[] onCreateDrawableState(int extraSpace) { 6331 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 6332 mParent instanceof View) { 6333 return ((View) mParent).onCreateDrawableState(extraSpace); 6334 } 6335 6336 int[] drawableState; 6337 6338 int privateFlags = mPrivateFlags; 6339 6340 int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0); 6341 6342 viewStateIndex = (viewStateIndex << 1) 6343 + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0); 6344 6345 viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0); 6346 6347 viewStateIndex = (viewStateIndex << 1) 6348 + (((privateFlags & SELECTED) != 0) ? 1 : 0); 6349 6350 final boolean hasWindowFocus = hasWindowFocus(); 6351 viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0); 6352 6353 drawableState = VIEW_STATE_SETS[viewStateIndex]; 6354 6355 //noinspection ConstantIfStatement 6356 if (false) { 6357 Log.i("View", "drawableStateIndex=" + viewStateIndex); 6358 Log.i("View", toString() 6359 + " pressed=" + ((privateFlags & PRESSED) != 0) 6360 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 6361 + " fo=" + hasFocus() 6362 + " sl=" + ((privateFlags & SELECTED) != 0) 6363 + " wf=" + hasWindowFocus 6364 + ": " + Arrays.toString(drawableState)); 6365 } 6366 6367 if (extraSpace == 0) { 6368 return drawableState; 6369 } 6370 6371 final int[] fullState; 6372 if (drawableState != null) { 6373 fullState = new int[drawableState.length + extraSpace]; 6374 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 6375 } else { 6376 fullState = new int[extraSpace]; 6377 } 6378 6379 return fullState; 6380 } 6381 6382 /** 6383 * Merge your own state values in <var>additionalState</var> into the base 6384 * state values <var>baseState</var> that were returned by 6385 * {@link #onCreateDrawableState}. 6386 * 6387 * @param baseState The base state values returned by 6388 * {@link #onCreateDrawableState}, which will be modified to also hold your 6389 * own additional state values. 6390 * 6391 * @param additionalState The additional state values you would like 6392 * added to <var>baseState</var>; this array is not modified. 6393 * 6394 * @return As a convenience, the <var>baseState</var> array you originally 6395 * passed into the function is returned. 6396 * 6397 * @see #onCreateDrawableState 6398 */ 6399 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 6400 final int N = baseState.length; 6401 int i = N - 1; 6402 while (i >= 0 && baseState[i] == 0) { 6403 i--; 6404 } 6405 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 6406 return baseState; 6407 } 6408 6409 /** 6410 * Sets the background color for this view. 6411 * @param color the color of the background 6412 */ 6413 public void setBackgroundColor(int color) { 6414 setBackgroundDrawable(new ColorDrawable(color)); 6415 } 6416 6417 /** 6418 * Set the background to a given resource. The resource should refer to 6419 * a Drawable object. 6420 * @param resid The identifier of the resource. 6421 * @attr ref android.R.styleable#View_background 6422 */ 6423 public void setBackgroundResource(int resid) { 6424 if (resid != 0 && resid == mBackgroundResource) { 6425 return; 6426 } 6427 6428 Drawable d= null; 6429 if (resid != 0) { 6430 d = mResources.getDrawable(resid); 6431 } 6432 setBackgroundDrawable(d); 6433 6434 mBackgroundResource = resid; 6435 } 6436 6437 /** 6438 * Set the background to a given Drawable, or remove the background. If the 6439 * background has padding, this View's padding is set to the background's 6440 * padding. However, when a background is removed, this View's padding isn't 6441 * touched. If setting the padding is desired, please use 6442 * {@link #setPadding(int, int, int, int)}. 6443 * 6444 * @param d The Drawable to use as the background, or null to remove the 6445 * background 6446 */ 6447 public void setBackgroundDrawable(Drawable d) { 6448 boolean requestLayout = false; 6449 6450 mBackgroundResource = 0; 6451 6452 /* 6453 * Regardless of whether we're setting a new background or not, we want 6454 * to clear the previous drawable. 6455 */ 6456 if (mBGDrawable != null) { 6457 mBGDrawable.setCallback(null); 6458 unscheduleDrawable(mBGDrawable); 6459 } 6460 6461 if (d != null) { 6462 Rect padding = sThreadLocal.get(); 6463 if (padding == null) { 6464 padding = new Rect(); 6465 sThreadLocal.set(padding); 6466 } 6467 if (d.getPadding(padding)) { 6468 setPadding(padding.left, padding.top, padding.right, padding.bottom); 6469 } 6470 6471 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 6472 // if it has a different minimum size, we should layout again 6473 if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() || 6474 mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) { 6475 requestLayout = true; 6476 } 6477 6478 d.setCallback(this); 6479 if (d.isStateful()) { 6480 d.setState(getDrawableState()); 6481 } 6482 d.setVisible(getVisibility() == VISIBLE, false); 6483 mBGDrawable = d; 6484 6485 if ((mPrivateFlags & SKIP_DRAW) != 0) { 6486 mPrivateFlags &= ~SKIP_DRAW; 6487 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 6488 requestLayout = true; 6489 } 6490 } else { 6491 /* Remove the background */ 6492 mBGDrawable = null; 6493 6494 if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) { 6495 /* 6496 * This view ONLY drew the background before and we're removing 6497 * the background, so now it won't draw anything 6498 * (hence we SKIP_DRAW) 6499 */ 6500 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND; 6501 mPrivateFlags |= SKIP_DRAW; 6502 } 6503 6504 /* 6505 * When the background is set, we try to apply its padding to this 6506 * View. When the background is removed, we don't touch this View's 6507 * padding. This is noted in the Javadocs. Hence, we don't need to 6508 * requestLayout(), the invalidate() below is sufficient. 6509 */ 6510 6511 // The old background's minimum size could have affected this 6512 // View's layout, so let's requestLayout 6513 requestLayout = true; 6514 } 6515 6516 if (requestLayout) { 6517 requestLayout(); 6518 } 6519 6520 mBackgroundSizeChanged = true; 6521 invalidate(); 6522 } 6523 6524 /** 6525 * Gets the background drawable 6526 * @return The drawable used as the background for this view, if any. 6527 */ 6528 public Drawable getBackground() { 6529 return mBGDrawable; 6530 } 6531 6532 /** 6533 * Sets the padding. The view may add on the space required to display 6534 * the scrollbars, depending on the style and visibility of the scrollbars. 6535 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 6536 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 6537 * from the values set in this call. 6538 * 6539 * @attr ref android.R.styleable#View_padding 6540 * @attr ref android.R.styleable#View_paddingBottom 6541 * @attr ref android.R.styleable#View_paddingLeft 6542 * @attr ref android.R.styleable#View_paddingRight 6543 * @attr ref android.R.styleable#View_paddingTop 6544 * @param left the left padding in pixels 6545 * @param top the top padding in pixels 6546 * @param right the right padding in pixels 6547 * @param bottom the bottom padding in pixels 6548 */ 6549 public void setPadding(int left, int top, int right, int bottom) { 6550 boolean changed = false; 6551 6552 mUserPaddingRight = right; 6553 mUserPaddingBottom = bottom; 6554 6555 final int viewFlags = mViewFlags; 6556 6557 // Common case is there are no scroll bars. 6558 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 6559 // TODO: Deal with RTL languages to adjust left padding instead of right. 6560 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 6561 right += (viewFlags & SCROLLBARS_INSET_MASK) == 0 6562 ? 0 : getVerticalScrollbarWidth(); 6563 } 6564 if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) { 6565 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 6566 ? 0 : getHorizontalScrollbarHeight(); 6567 } 6568 } 6569 6570 if (mPaddingLeft != left) { 6571 changed = true; 6572 mPaddingLeft = left; 6573 } 6574 if (mPaddingTop != top) { 6575 changed = true; 6576 mPaddingTop = top; 6577 } 6578 if (mPaddingRight != right) { 6579 changed = true; 6580 mPaddingRight = right; 6581 } 6582 if (mPaddingBottom != bottom) { 6583 changed = true; 6584 mPaddingBottom = bottom; 6585 } 6586 6587 if (changed) { 6588 requestLayout(); 6589 } 6590 } 6591 6592 /** 6593 * Returns the top padding of this view. 6594 * 6595 * @return the top padding in pixels 6596 */ 6597 public int getPaddingTop() { 6598 return mPaddingTop; 6599 } 6600 6601 /** 6602 * Returns the bottom padding of this view. If there are inset and enabled 6603 * scrollbars, this value may include the space required to display the 6604 * scrollbars as well. 6605 * 6606 * @return the bottom padding in pixels 6607 */ 6608 public int getPaddingBottom() { 6609 return mPaddingBottom; 6610 } 6611 6612 /** 6613 * Returns the left padding of this view. If there are inset and enabled 6614 * scrollbars, this value may include the space required to display the 6615 * scrollbars as well. 6616 * 6617 * @return the left padding in pixels 6618 */ 6619 public int getPaddingLeft() { 6620 return mPaddingLeft; 6621 } 6622 6623 /** 6624 * Returns the right padding of this view. If there are inset and enabled 6625 * scrollbars, this value may include the space required to display the 6626 * scrollbars as well. 6627 * 6628 * @return the right padding in pixels 6629 */ 6630 public int getPaddingRight() { 6631 return mPaddingRight; 6632 } 6633 6634 /** 6635 * Changes the selection state of this view. A view can be selected or not. 6636 * Note that selection is not the same as focus. Views are typically 6637 * selected in the context of an AdapterView like ListView or GridView; 6638 * the selected view is the view that is highlighted. 6639 * 6640 * @param selected true if the view must be selected, false otherwise 6641 */ 6642 public void setSelected(boolean selected) { 6643 if (((mPrivateFlags & SELECTED) != 0) != selected) { 6644 mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0); 6645 invalidate(); 6646 refreshDrawableState(); 6647 dispatchSetSelected(selected); 6648 } 6649 } 6650 6651 /** 6652 * Dispatch setSelected to all of this View's children. 6653 * 6654 * @see #setSelected(boolean) 6655 * 6656 * @param selected The new selected state 6657 */ 6658 protected void dispatchSetSelected(boolean selected) { 6659 } 6660 6661 /** 6662 * Indicates the selection state of this view. 6663 * 6664 * @return true if the view is selected, false otherwise 6665 */ 6666 @ViewDebug.ExportedProperty 6667 public boolean isSelected() { 6668 return (mPrivateFlags & SELECTED) != 0; 6669 } 6670 6671 /** 6672 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 6673 * observer can be used to get notifications when global events, like 6674 * layout, happen. 6675 * 6676 * The returned ViewTreeObserver observer is not guaranteed to remain 6677 * valid for the lifetime of this View. If the caller of this method keeps 6678 * a long-lived reference to ViewTreeObserver, it should always check for 6679 * the return value of {@link ViewTreeObserver#isAlive()}. 6680 * 6681 * @return The ViewTreeObserver for this view's hierarchy. 6682 */ 6683 public ViewTreeObserver getViewTreeObserver() { 6684 if (mAttachInfo != null) { 6685 return mAttachInfo.mTreeObserver; 6686 } 6687 if (mFloatingTreeObserver == null) { 6688 mFloatingTreeObserver = new ViewTreeObserver(); 6689 } 6690 return mFloatingTreeObserver; 6691 } 6692 6693 /** 6694 * <p>Finds the topmost view in the current view hierarchy.</p> 6695 * 6696 * @return the topmost view containing this view 6697 */ 6698 public View getRootView() { 6699 if (mAttachInfo != null) { 6700 final View v = mAttachInfo.mRootView; 6701 if (v != null) { 6702 return v; 6703 } 6704 } 6705 6706 View parent = this; 6707 6708 while (parent.mParent != null && parent.mParent instanceof View) { 6709 parent = (View) parent.mParent; 6710 } 6711 6712 return parent; 6713 } 6714 6715 /** 6716 * <p>Computes the coordinates of this view on the screen. The argument 6717 * must be an array of two integers. After the method returns, the array 6718 * contains the x and y location in that order.</p> 6719 * 6720 * @param location an array of two integers in which to hold the coordinates 6721 */ 6722 public void getLocationOnScreen(int[] location) { 6723 getLocationInWindow(location); 6724 6725 final AttachInfo info = mAttachInfo; 6726 location[0] += info.mWindowLeft; 6727 location[1] += info.mWindowTop; 6728 } 6729 6730 /** 6731 * <p>Computes the coordinates of this view in its window. The argument 6732 * must be an array of two integers. After the method returns, the array 6733 * contains the x and y location in that order.</p> 6734 * 6735 * @param location an array of two integers in which to hold the coordinates 6736 */ 6737 public void getLocationInWindow(int[] location) { 6738 if (location == null || location.length < 2) { 6739 throw new IllegalArgumentException("location must be an array of " 6740 + "two integers"); 6741 } 6742 6743 location[0] = mLeft; 6744 location[1] = mTop; 6745 6746 ViewParent viewParent = mParent; 6747 while (viewParent instanceof View) { 6748 final View view = (View)viewParent; 6749 location[0] += view.mLeft - view.mScrollX; 6750 location[1] += view.mTop - view.mScrollY; 6751 viewParent = view.mParent; 6752 } 6753 6754 if (viewParent instanceof ViewRoot) { 6755 // *cough* 6756 final ViewRoot vr = (ViewRoot)viewParent; 6757 location[1] -= vr.mCurScrollY; 6758 } 6759 } 6760 6761 /** 6762 * {@hide} 6763 * @param id the id of the view to be found 6764 * @return the view of the specified id, null if cannot be found 6765 */ 6766 protected View findViewTraversal(int id) { 6767 if (id == mID) { 6768 return this; 6769 } 6770 return null; 6771 } 6772 6773 /** 6774 * {@hide} 6775 * @param tag the tag of the view to be found 6776 * @return the view of specified tag, null if cannot be found 6777 */ 6778 protected View findViewWithTagTraversal(Object tag) { 6779 if (tag != null && tag.equals(mTag)) { 6780 return this; 6781 } 6782 return null; 6783 } 6784 6785 /** 6786 * Look for a child view with the given id. If this view has the given 6787 * id, return this view. 6788 * 6789 * @param id The id to search for. 6790 * @return The view that has the given id in the hierarchy or null 6791 */ 6792 public final View findViewById(int id) { 6793 if (id < 0) { 6794 return null; 6795 } 6796 return findViewTraversal(id); 6797 } 6798 6799 /** 6800 * Look for a child view with the given tag. If this view has the given 6801 * tag, return this view. 6802 * 6803 * @param tag The tag to search for, using "tag.equals(getTag())". 6804 * @return The View that has the given tag in the hierarchy or null 6805 */ 6806 public final View findViewWithTag(Object tag) { 6807 if (tag == null) { 6808 return null; 6809 } 6810 return findViewWithTagTraversal(tag); 6811 } 6812 6813 /** 6814 * Sets the identifier for this view. The identifier does not have to be 6815 * unique in this view's hierarchy. The identifier should be a positive 6816 * number. 6817 * 6818 * @see #NO_ID 6819 * @see #getId 6820 * @see #findViewById 6821 * 6822 * @param id a number used to identify the view 6823 * 6824 * @attr ref android.R.styleable#View_id 6825 */ 6826 public void setId(int id) { 6827 mID = id; 6828 } 6829 6830 /** 6831 * {@hide} 6832 * 6833 * @param isRoot true if the view belongs to the root namespace, false 6834 * otherwise 6835 */ 6836 public void setIsRootNamespace(boolean isRoot) { 6837 if (isRoot) { 6838 mPrivateFlags |= IS_ROOT_NAMESPACE; 6839 } else { 6840 mPrivateFlags &= ~IS_ROOT_NAMESPACE; 6841 } 6842 } 6843 6844 /** 6845 * {@hide} 6846 * 6847 * @return true if the view belongs to the root namespace, false otherwise 6848 */ 6849 public boolean isRootNamespace() { 6850 return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0; 6851 } 6852 6853 /** 6854 * Returns this view's identifier. 6855 * 6856 * @return a positive integer used to identify the view or {@link #NO_ID} 6857 * if the view has no ID 6858 * 6859 * @see #setId 6860 * @see #findViewById 6861 * @attr ref android.R.styleable#View_id 6862 */ 6863 @ViewDebug.CapturedViewProperty 6864 public int getId() { 6865 return mID; 6866 } 6867 6868 /** 6869 * Returns this view's tag. 6870 * 6871 * @return the Object stored in this view as a tag 6872 */ 6873 @ViewDebug.ExportedProperty 6874 public Object getTag() { 6875 return mTag; 6876 } 6877 6878 /** 6879 * Sets the tag associated with this view. A tag can be used to mark 6880 * a view in its hierarchy and does not have to be unique within the 6881 * hierarchy. Tags can also be used to store data within a view without 6882 * resorting to another data structure. 6883 * 6884 * @param tag an Object to tag the view with 6885 */ 6886 public void setTag(final Object tag) { 6887 mTag = tag; 6888 } 6889 6890 /** 6891 * Prints information about this view in the log output, with the tag 6892 * {@link #VIEW_LOG_TAG}. 6893 * 6894 * @hide 6895 */ 6896 public void debug() { 6897 debug(0); 6898 } 6899 6900 /** 6901 * Prints information about this view in the log output, with the tag 6902 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 6903 * indentation defined by the <code>depth</code>. 6904 * 6905 * @param depth the indentation level 6906 * 6907 * @hide 6908 */ 6909 protected void debug(int depth) { 6910 String output = debugIndent(depth - 1); 6911 6912 output += "+ " + this; 6913 int id = getId(); 6914 if (id != -1) { 6915 output += " (id=" + id + ")"; 6916 } 6917 Object tag = getTag(); 6918 if (tag != null) { 6919 output += " (tag=" + tag + ")"; 6920 } 6921 Log.d(VIEW_LOG_TAG, output); 6922 6923 if ((mPrivateFlags & FOCUSED) != 0) { 6924 output = debugIndent(depth) + " FOCUSED"; 6925 Log.d(VIEW_LOG_TAG, output); 6926 } 6927 6928 output = debugIndent(depth); 6929 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 6930 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 6931 + "} "; 6932 Log.d(VIEW_LOG_TAG, output); 6933 6934 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 6935 || mPaddingBottom != 0) { 6936 output = debugIndent(depth); 6937 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 6938 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 6939 Log.d(VIEW_LOG_TAG, output); 6940 } 6941 6942 output = debugIndent(depth); 6943 output += "mMeasureWidth=" + mMeasuredWidth + 6944 " mMeasureHeight=" + mMeasuredHeight; 6945 Log.d(VIEW_LOG_TAG, output); 6946 6947 output = debugIndent(depth); 6948 if (mLayoutParams == null) { 6949 output += "BAD! no layout params"; 6950 } else { 6951 output = mLayoutParams.debug(output); 6952 } 6953 Log.d(VIEW_LOG_TAG, output); 6954 6955 output = debugIndent(depth); 6956 output += "flags={"; 6957 output += View.printFlags(mViewFlags); 6958 output += "}"; 6959 Log.d(VIEW_LOG_TAG, output); 6960 6961 output = debugIndent(depth); 6962 output += "privateFlags={"; 6963 output += View.printPrivateFlags(mPrivateFlags); 6964 output += "}"; 6965 Log.d(VIEW_LOG_TAG, output); 6966 } 6967 6968 /** 6969 * Creates an string of whitespaces used for indentation. 6970 * 6971 * @param depth the indentation level 6972 * @return a String containing (depth * 2 + 3) * 2 white spaces 6973 * 6974 * @hide 6975 */ 6976 protected static String debugIndent(int depth) { 6977 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 6978 for (int i = 0; i < (depth * 2) + 3; i++) { 6979 spaces.append(' ').append(' '); 6980 } 6981 return spaces.toString(); 6982 } 6983 6984 /** 6985 * <p>Return the offset of the widget's text baseline from the widget's top 6986 * boundary. If this widget does not support baseline alignment, this 6987 * method returns -1. </p> 6988 * 6989 * @return the offset of the baseline within the widget's bounds or -1 6990 * if baseline alignment is not supported 6991 */ 6992 @ViewDebug.ExportedProperty 6993 public int getBaseline() { 6994 return -1; 6995 } 6996 6997 /** 6998 * Call this when something has changed which has invalidated the 6999 * layout of this view. This will schedule a layout pass of the view 7000 * tree. 7001 */ 7002 public void requestLayout() { 7003 if (ViewDebug.TRACE_HIERARCHY) { 7004 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT); 7005 } 7006 7007 mPrivateFlags |= FORCE_LAYOUT; 7008 7009 if (mParent != null && !mParent.isLayoutRequested()) { 7010 mParent.requestLayout(); 7011 } 7012 } 7013 7014 /** 7015 * Forces this view to be laid out during the next layout pass. 7016 * This method does not call requestLayout() or forceLayout() 7017 * on the parent. 7018 */ 7019 public void forceLayout() { 7020 mPrivateFlags |= FORCE_LAYOUT; 7021 } 7022 7023 /** 7024 * <p> 7025 * This is called to find out how big a view should be. The parent 7026 * supplies constraint information in the width and height parameters. 7027 * </p> 7028 * 7029 * <p> 7030 * The actual mesurement work of a view is performed in 7031 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 7032 * {@link #onMeasure(int, int)} can and must be overriden by subclasses. 7033 * </p> 7034 * 7035 * 7036 * @param widthMeasureSpec Horizontal space requirements as imposed by the 7037 * parent 7038 * @param heightMeasureSpec Vertical space requirements as imposed by the 7039 * parent 7040 * 7041 * @see #onMeasure(int, int) 7042 */ 7043 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 7044 if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || 7045 widthMeasureSpec != mOldWidthMeasureSpec || 7046 heightMeasureSpec != mOldHeightMeasureSpec) { 7047 7048 // first clears the measured dimension flag 7049 mPrivateFlags &= ~MEASURED_DIMENSION_SET; 7050 7051 if (ViewDebug.TRACE_HIERARCHY) { 7052 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE); 7053 } 7054 7055 // measure ourselves, this should set the measured dimension flag back 7056 onMeasure(widthMeasureSpec, heightMeasureSpec); 7057 7058 // flag not set, setMeasuredDimension() was not invoked, we raise 7059 // an exception to warn the developer 7060 if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) { 7061 throw new IllegalStateException("onMeasure() did not set the" 7062 + " measured dimension by calling" 7063 + " setMeasuredDimension()"); 7064 } 7065 7066 mPrivateFlags |= LAYOUT_REQUIRED; 7067 } 7068 7069 mOldWidthMeasureSpec = widthMeasureSpec; 7070 mOldHeightMeasureSpec = heightMeasureSpec; 7071 } 7072 7073 /** 7074 * <p> 7075 * Measure the view and its content to determine the measured width and the 7076 * measured height. This method is invoked by {@link #measure(int, int)} and 7077 * should be overriden by subclasses to provide accurate and efficient 7078 * measurement of their contents. 7079 * </p> 7080 * 7081 * <p> 7082 * <strong>CONTRACT:</strong> When overriding this method, you 7083 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 7084 * measured width and height of this view. Failure to do so will trigger an 7085 * <code>IllegalStateException</code>, thrown by 7086 * {@link #measure(int, int)}. Calling the superclass' 7087 * {@link #onMeasure(int, int)} is a valid use. 7088 * </p> 7089 * 7090 * <p> 7091 * The base class implementation of measure defaults to the background size, 7092 * unless a larger size is allowed by the MeasureSpec. Subclasses should 7093 * override {@link #onMeasure(int, int)} to provide better measurements of 7094 * their content. 7095 * </p> 7096 * 7097 * <p> 7098 * If this method is overridden, it is the subclass's responsibility to make 7099 * sure the measured height and width are at least the view's minimum height 7100 * and width ({@link #getSuggestedMinimumHeight()} and 7101 * {@link #getSuggestedMinimumWidth()}). 7102 * </p> 7103 * 7104 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 7105 * The requirements are encoded with 7106 * {@link android.view.View.MeasureSpec}. 7107 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 7108 * The requirements are encoded with 7109 * {@link android.view.View.MeasureSpec}. 7110 * 7111 * @see #getMeasuredWidth() 7112 * @see #getMeasuredHeight() 7113 * @see #setMeasuredDimension(int, int) 7114 * @see #getSuggestedMinimumHeight() 7115 * @see #getSuggestedMinimumWidth() 7116 * @see android.view.View.MeasureSpec#getMode(int) 7117 * @see android.view.View.MeasureSpec#getSize(int) 7118 */ 7119 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 7120 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 7121 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 7122 } 7123 7124 /** 7125 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the 7126 * measured width and measured height. Failing to do so will trigger an 7127 * exception at measurement time.</p> 7128 * 7129 * @param measuredWidth the measured width of this view 7130 * @param measuredHeight the measured height of this view 7131 */ 7132 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 7133 mMeasuredWidth = measuredWidth; 7134 mMeasuredHeight = measuredHeight; 7135 7136 mPrivateFlags |= MEASURED_DIMENSION_SET; 7137 } 7138 7139 /** 7140 * Utility to reconcile a desired size with constraints imposed by a MeasureSpec. 7141 * Will take the desired size, unless a different size is imposed by the constraints. 7142 * 7143 * @param size How big the view wants to be 7144 * @param measureSpec Constraints imposed by the parent 7145 * @return The size this view should be. 7146 */ 7147 public static int resolveSize(int size, int measureSpec) { 7148 int result = size; 7149 int specMode = MeasureSpec.getMode(measureSpec); 7150 int specSize = MeasureSpec.getSize(measureSpec); 7151 switch (specMode) { 7152 case MeasureSpec.UNSPECIFIED: 7153 result = size; 7154 break; 7155 case MeasureSpec.AT_MOST: 7156 result = Math.min(size, specSize); 7157 break; 7158 case MeasureSpec.EXACTLY: 7159 result = specSize; 7160 break; 7161 } 7162 return result; 7163 } 7164 7165 /** 7166 * Utility to return a default size. Uses the supplied size if the 7167 * MeasureSpec imposed no contraints. Will get larger if allowed 7168 * by the MeasureSpec. 7169 * 7170 * @param size Default size for this view 7171 * @param measureSpec Constraints imposed by the parent 7172 * @return The size this view should be. 7173 */ 7174 public static int getDefaultSize(int size, int measureSpec) { 7175 int result = size; 7176 int specMode = MeasureSpec.getMode(measureSpec); 7177 int specSize = MeasureSpec.getSize(measureSpec); 7178 7179 switch (specMode) { 7180 case MeasureSpec.UNSPECIFIED: 7181 result = size; 7182 break; 7183 case MeasureSpec.AT_MOST: 7184 case MeasureSpec.EXACTLY: 7185 result = specSize; 7186 break; 7187 } 7188 return result; 7189 } 7190 7191 /** 7192 * Returns the suggested minimum height that the view should use. This 7193 * returns the maximum of the view's minimum height 7194 * and the background's minimum height 7195 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 7196 * <p> 7197 * When being used in {@link #onMeasure(int, int)}, the caller should still 7198 * ensure the returned height is within the requirements of the parent. 7199 * 7200 * @return The suggested minimum height of the view. 7201 */ 7202 protected int getSuggestedMinimumHeight() { 7203 int suggestedMinHeight = mMinHeight; 7204 7205 if (mBGDrawable != null) { 7206 final int bgMinHeight = mBGDrawable.getMinimumHeight(); 7207 if (suggestedMinHeight < bgMinHeight) { 7208 suggestedMinHeight = bgMinHeight; 7209 } 7210 } 7211 7212 return suggestedMinHeight; 7213 } 7214 7215 /** 7216 * Returns the suggested minimum width that the view should use. This 7217 * returns the maximum of the view's minimum width) 7218 * and the background's minimum width 7219 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 7220 * <p> 7221 * When being used in {@link #onMeasure(int, int)}, the caller should still 7222 * ensure the returned width is within the requirements of the parent. 7223 * 7224 * @return The suggested minimum width of the view. 7225 */ 7226 protected int getSuggestedMinimumWidth() { 7227 int suggestedMinWidth = mMinWidth; 7228 7229 if (mBGDrawable != null) { 7230 final int bgMinWidth = mBGDrawable.getMinimumWidth(); 7231 if (suggestedMinWidth < bgMinWidth) { 7232 suggestedMinWidth = bgMinWidth; 7233 } 7234 } 7235 7236 return suggestedMinWidth; 7237 } 7238 7239 /** 7240 * Sets the minimum height of the view. It is not guaranteed the view will 7241 * be able to achieve this minimum height (for example, if its parent layout 7242 * constrains it with less available height). 7243 * 7244 * @param minHeight The minimum height the view will try to be. 7245 */ 7246 public void setMinimumHeight(int minHeight) { 7247 mMinHeight = minHeight; 7248 } 7249 7250 /** 7251 * Sets the minimum width of the view. It is not guaranteed the view will 7252 * be able to achieve this minimum width (for example, if its parent layout 7253 * constrains it with less available width). 7254 * 7255 * @param minWidth The minimum width the view will try to be. 7256 */ 7257 public void setMinimumWidth(int minWidth) { 7258 mMinWidth = minWidth; 7259 } 7260 7261 /** 7262 * Get the animation currently associated with this view. 7263 * 7264 * @return The animation that is currently playing or 7265 * scheduled to play for this view. 7266 */ 7267 public Animation getAnimation() { 7268 return mCurrentAnimation; 7269 } 7270 7271 /** 7272 * Start the specified animation now. 7273 * 7274 * @param animation the animation to start now 7275 */ 7276 public void startAnimation(Animation animation) { 7277 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 7278 setAnimation(animation); 7279 invalidate(); 7280 } 7281 7282 /** 7283 * Cancels any animations for this view. 7284 */ 7285 public void clearAnimation() { 7286 mCurrentAnimation = null; 7287 } 7288 7289 /** 7290 * Sets the next animation to play for this view. 7291 * If you want the animation to play immediately, use 7292 * startAnimation. This method provides allows fine-grained 7293 * control over the start time and invalidation, but you 7294 * must make sure that 1) the animation has a start time set, and 7295 * 2) the view will be invalidated when the animation is supposed to 7296 * start. 7297 * 7298 * @param animation The next animation, or null. 7299 */ 7300 public void setAnimation(Animation animation) { 7301 mCurrentAnimation = animation; 7302 if (animation != null) { 7303 animation.reset(); 7304 } 7305 } 7306 7307 /** 7308 * Invoked by a parent ViewGroup to notify the start of the animation 7309 * currently associated with this view. If you override this method, 7310 * always call super.onAnimationStart(); 7311 * 7312 * @see #setAnimation(android.view.animation.Animation) 7313 * @see #getAnimation() 7314 */ 7315 protected void onAnimationStart() { 7316 mPrivateFlags |= ANIMATION_STARTED; 7317 } 7318 7319 /** 7320 * Invoked by a parent ViewGroup to notify the end of the animation 7321 * currently associated with this view. If you override this method, 7322 * always call super.onAnimationEnd(); 7323 * 7324 * @see #setAnimation(android.view.animation.Animation) 7325 * @see #getAnimation() 7326 */ 7327 protected void onAnimationEnd() { 7328 mPrivateFlags &= ~ANIMATION_STARTED; 7329 } 7330 7331 /** 7332 * Invoked if there is a Transform that involves alpha. Subclass that can 7333 * draw themselves with the specified alpha should return true, and then 7334 * respect that alpha when their onDraw() is called. If this returns false 7335 * then the view may be redirected to draw into an offscreen buffer to 7336 * fulfill the request, which will look fine, but may be slower than if the 7337 * subclass handles it internally. The default implementation returns false. 7338 * 7339 * @param alpha The alpha (0..255) to apply to the view's drawing 7340 * @return true if the view can draw with the specified alpha. 7341 */ 7342 protected boolean onSetAlpha(int alpha) { 7343 return false; 7344 } 7345 7346 /** 7347 * This is used by the RootView to perform an optimization when 7348 * the view hierarchy contains one or several SurfaceView. 7349 * SurfaceView is always considered transparent, but its children are not, 7350 * therefore all View objects remove themselves from the global transparent 7351 * region (passed as a parameter to this function). 7352 * 7353 * @param region The transparent region for this ViewRoot (window). 7354 * 7355 * @return Returns true if the effective visibility of the view at this 7356 * point is opaque, regardless of the transparent region; returns false 7357 * if it is possible for underlying windows to be seen behind the view. 7358 * 7359 * {@hide} 7360 */ 7361 public boolean gatherTransparentRegion(Region region) { 7362 final AttachInfo attachInfo = mAttachInfo; 7363 if (region != null && attachInfo != null) { 7364 final int pflags = mPrivateFlags; 7365 if ((pflags & SKIP_DRAW) == 0) { 7366 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 7367 // remove it from the transparent region. 7368 final int[] location = attachInfo.mTransparentLocation; 7369 getLocationInWindow(location); 7370 region.op(location[0], location[1], location[0] + mRight - mLeft, 7371 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 7372 } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) { 7373 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable 7374 // exists, so we remove the background drawable's non-transparent 7375 // parts from this transparent region. 7376 applyDrawableToTransparentRegion(mBGDrawable, region); 7377 } 7378 } 7379 return true; 7380 } 7381 7382 /** 7383 * Play a sound effect for this view. 7384 * 7385 * <p>The framework will play sound effects for some built in actions, such as 7386 * clicking, but you may wish to play these effects in your widget, 7387 * for instance, for internal navigation. 7388 * 7389 * <p>The sound effect will only be played if sound effects are enabled by the user, and 7390 * {@link #isSoundEffectsEnabled()} is true. 7391 * 7392 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 7393 */ 7394 public void playSoundEffect(int soundConstant) { 7395 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 7396 return; 7397 } 7398 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 7399 } 7400 7401 /** 7402 * Provide haptic feedback to the user for this view. 7403 * 7404 * <p>The framework will provide haptic feedback for some built in actions, 7405 * such as long presses, but you may wish to provide feedback for your 7406 * own widget. 7407 * 7408 * <p>The feedback will only be performed if 7409 * {@link #isHapticFeedbackEnabled()} is true. 7410 * 7411 * @param feedbackConstant One of the constants defined in 7412 * {@link HapticFeedbackConstants} 7413 */ 7414 public boolean performHapticFeedback(int feedbackConstant) { 7415 return performHapticFeedback(feedbackConstant, 0); 7416 } 7417 7418 /** 7419 * Like {@link #performHapticFeedback(int)}, with additional options. 7420 * 7421 * @param feedbackConstant One of the constants defined in 7422 * {@link HapticFeedbackConstants} 7423 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 7424 */ 7425 public boolean performHapticFeedback(int feedbackConstant, int flags) { 7426 if (mAttachInfo == null) { 7427 return false; 7428 } 7429 if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 7430 && !isHapticFeedbackEnabled()) { 7431 return false; 7432 } 7433 return mAttachInfo.mRootCallbacks.performHapticFeedback( 7434 feedbackConstant, 7435 (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 7436 } 7437 7438 /** 7439 * Given a Drawable whose bounds have been set to draw into this view, 7440 * update a Region being computed for {@link #gatherTransparentRegion} so 7441 * that any non-transparent parts of the Drawable are removed from the 7442 * given transparent region. 7443 * 7444 * @param dr The Drawable whose transparency is to be applied to the region. 7445 * @param region A Region holding the current transparency information, 7446 * where any parts of the region that are set are considered to be 7447 * transparent. On return, this region will be modified to have the 7448 * transparency information reduced by the corresponding parts of the 7449 * Drawable that are not transparent. 7450 * {@hide} 7451 */ 7452 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 7453 if (DBG) { 7454 Log.i("View", "Getting transparent region for: " + this); 7455 } 7456 final Region r = dr.getTransparentRegion(); 7457 final Rect db = dr.getBounds(); 7458 final AttachInfo attachInfo = mAttachInfo; 7459 if (r != null && attachInfo != null) { 7460 final int w = getRight()-getLeft(); 7461 final int h = getBottom()-getTop(); 7462 if (db.left > 0) { 7463 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 7464 r.op(0, 0, db.left, h, Region.Op.UNION); 7465 } 7466 if (db.right < w) { 7467 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 7468 r.op(db.right, 0, w, h, Region.Op.UNION); 7469 } 7470 if (db.top > 0) { 7471 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 7472 r.op(0, 0, w, db.top, Region.Op.UNION); 7473 } 7474 if (db.bottom < h) { 7475 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 7476 r.op(0, db.bottom, w, h, Region.Op.UNION); 7477 } 7478 final int[] location = attachInfo.mTransparentLocation; 7479 getLocationInWindow(location); 7480 r.translate(location[0], location[1]); 7481 region.op(r, Region.Op.INTERSECT); 7482 } else { 7483 region.op(db, Region.Op.DIFFERENCE); 7484 } 7485 } 7486 7487 private void postCheckForLongClick() { 7488 mHasPerformedLongPress = false; 7489 7490 if (mPendingCheckForLongPress == null) { 7491 mPendingCheckForLongPress = new CheckForLongPress(); 7492 } 7493 mPendingCheckForLongPress.rememberWindowAttachCount(); 7494 postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); 7495 } 7496 7497 private static int[] stateSetUnion(final int[] stateSet1, 7498 final int[] stateSet2) { 7499 final int stateSet1Length = stateSet1.length; 7500 final int stateSet2Length = stateSet2.length; 7501 final int[] newSet = new int[stateSet1Length + stateSet2Length]; 7502 int k = 0; 7503 int i = 0; 7504 int j = 0; 7505 // This is a merge of the two input state sets and assumes that the 7506 // input sets are sorted by the order imposed by ViewDrawableStates. 7507 for (int viewState : R.styleable.ViewDrawableStates) { 7508 if (i < stateSet1Length && stateSet1[i] == viewState) { 7509 newSet[k++] = viewState; 7510 i++; 7511 } else if (j < stateSet2Length && stateSet2[j] == viewState) { 7512 newSet[k++] = viewState; 7513 j++; 7514 } 7515 if (k > 1) { 7516 assert(newSet[k - 1] > newSet[k - 2]); 7517 } 7518 } 7519 return newSet; 7520 } 7521 7522 /** 7523 * Inflate a view from an XML resource. This convenience method wraps the {@link 7524 * LayoutInflater} class, which provides a full range of options for view inflation. 7525 * 7526 * @param context The Context object for your activity or application. 7527 * @param resource The resource ID to inflate 7528 * @param root A view group that will be the parent. Used to properly inflate the 7529 * layout_* parameters. 7530 * @see LayoutInflater 7531 */ 7532 public static View inflate(Context context, int resource, ViewGroup root) { 7533 LayoutInflater factory = LayoutInflater.from(context); 7534 return factory.inflate(resource, root); 7535 } 7536 7537 /** 7538 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 7539 * Each MeasureSpec represents a requirement for either the width or the height. 7540 * A MeasureSpec is comprised of a size and a mode. There are three possible 7541 * modes: 7542 * <dl> 7543 * <dt>UNSPECIFIED</dt> 7544 * <dd> 7545 * The parent has not imposed any constraint on the child. It can be whatever size 7546 * it wants. 7547 * </dd> 7548 * 7549 * <dt>EXACTLY</dt> 7550 * <dd> 7551 * The parent has determined an exact size for the child. The child is going to be 7552 * given those bounds regardless of how big it wants to be. 7553 * </dd> 7554 * 7555 * <dt>AT_MOST</dt> 7556 * <dd> 7557 * The child can be as large as it wants up to the specified size. 7558 * </dd> 7559 * </dl> 7560 * 7561 * MeasureSpecs are implemented as ints to reduce object allocation. This class 7562 * is provided to pack and unpack the <size, mode> tuple into the int. 7563 */ 7564 public static class MeasureSpec { 7565 private static final int MODE_SHIFT = 30; 7566 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 7567 7568 /** 7569 * Measure specification mode: The parent has not imposed any constraint 7570 * on the child. It can be whatever size it wants. 7571 */ 7572 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 7573 7574 /** 7575 * Measure specification mode: The parent has determined an exact size 7576 * for the child. The child is going to be given those bounds regardless 7577 * of how big it wants to be. 7578 */ 7579 public static final int EXACTLY = 1 << MODE_SHIFT; 7580 7581 /** 7582 * Measure specification mode: The child can be as large as it wants up 7583 * to the specified size. 7584 */ 7585 public static final int AT_MOST = 2 << MODE_SHIFT; 7586 7587 /** 7588 * Creates a measure specification based on the supplied size and mode. 7589 * 7590 * The mode must always be one of the following: 7591 * <ul> 7592 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 7593 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 7594 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 7595 * </ul> 7596 * 7597 * @param size the size of the measure specification 7598 * @param mode the mode of the measure specification 7599 * @return the measure specification based on size and mode 7600 */ 7601 public static int makeMeasureSpec(int size, int mode) { 7602 return size + mode; 7603 } 7604 7605 /** 7606 * Extracts the mode from the supplied measure specification. 7607 * 7608 * @param measureSpec the measure specification to extract the mode from 7609 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 7610 * {@link android.view.View.MeasureSpec#AT_MOST} or 7611 * {@link android.view.View.MeasureSpec#EXACTLY} 7612 */ 7613 public static int getMode(int measureSpec) { 7614 return (measureSpec & MODE_MASK); 7615 } 7616 7617 /** 7618 * Extracts the size from the supplied measure specification. 7619 * 7620 * @param measureSpec the measure specification to extract the size from 7621 * @return the size in pixels defined in the supplied measure specification 7622 */ 7623 public static int getSize(int measureSpec) { 7624 return (measureSpec & ~MODE_MASK); 7625 } 7626 7627 /** 7628 * Returns a String representation of the specified measure 7629 * specification. 7630 * 7631 * @param measureSpec the measure specification to convert to a String 7632 * @return a String with the following format: "MeasureSpec: MODE SIZE" 7633 */ 7634 public static String toString(int measureSpec) { 7635 int mode = getMode(measureSpec); 7636 int size = getSize(measureSpec); 7637 7638 StringBuilder sb = new StringBuilder("MeasureSpec: "); 7639 7640 if (mode == UNSPECIFIED) 7641 sb.append("UNSPECIFIED "); 7642 else if (mode == EXACTLY) 7643 sb.append("EXACTLY "); 7644 else if (mode == AT_MOST) 7645 sb.append("AT_MOST "); 7646 else 7647 sb.append(mode).append(" "); 7648 7649 sb.append(size); 7650 return sb.toString(); 7651 } 7652 } 7653 7654 class CheckForLongPress implements Runnable { 7655 7656 private int mOriginalWindowAttachCount; 7657 7658 public void run() { 7659 if (isPressed() && (mParent != null) && hasWindowFocus() 7660 && mOriginalWindowAttachCount == mWindowAttachCount) { 7661 if (performLongClick()) { 7662 mHasPerformedLongPress = true; 7663 } 7664 } 7665 } 7666 7667 public void rememberWindowAttachCount() { 7668 mOriginalWindowAttachCount = mWindowAttachCount; 7669 } 7670 } 7671 7672 /** 7673 * Interface definition for a callback to be invoked when a key event is 7674 * dispatched to this view. The callback will be invoked before the key 7675 * event is given to the view. 7676 */ 7677 public interface OnKeyListener { 7678 /** 7679 * Called when a key is dispatched to a view. This allows listeners to 7680 * get a chance to respond before the target view. 7681 * 7682 * @param v The view the key has been dispatched to. 7683 * @param keyCode The code for the physical key that was pressed 7684 * @param event The KeyEvent object containing full information about 7685 * the event. 7686 * @return True if the listener has consumed the event, false otherwise. 7687 */ 7688 boolean onKey(View v, int keyCode, KeyEvent event); 7689 } 7690 7691 /** 7692 * Interface definition for a callback to be invoked when a touch event is 7693 * dispatched to this view. The callback will be invoked before the touch 7694 * event is given to the view. 7695 */ 7696 public interface OnTouchListener { 7697 /** 7698 * Called when a touch event is dispatched to a view. This allows listeners to 7699 * get a chance to respond before the target view. 7700 * 7701 * @param v The view the touch event has been dispatched to. 7702 * @param event The MotionEvent object containing full information about 7703 * the event. 7704 * @return True if the listener has consumed the event, false otherwise. 7705 */ 7706 boolean onTouch(View v, MotionEvent event); 7707 } 7708 7709 /** 7710 * Interface definition for a callback to be invoked when a view has been clicked and held. 7711 */ 7712 public interface OnLongClickListener { 7713 /** 7714 * Called when a view has been clicked and held. 7715 * 7716 * @param v The view that was clicked and held. 7717 * 7718 * return True if the callback consumed the long click, false otherwise 7719 */ 7720 boolean onLongClick(View v); 7721 } 7722 7723 /** 7724 * Interface definition for a callback to be invoked when the focus state of 7725 * a view changed. 7726 */ 7727 public interface OnFocusChangeListener { 7728 /** 7729 * Called when the focus state of a view has changed. 7730 * 7731 * @param v The view whose state has changed. 7732 * @param hasFocus The new focus state of v. 7733 */ 7734 void onFocusChange(View v, boolean hasFocus); 7735 } 7736 7737 /** 7738 * Interface definition for a callback to be invoked when a view is clicked. 7739 */ 7740 public interface OnClickListener { 7741 /** 7742 * Called when a view has been clicked. 7743 * 7744 * @param v The view that was clicked. 7745 */ 7746 void onClick(View v); 7747 } 7748 7749 /** 7750 * Interface definition for a callback to be invoked when the context menu 7751 * for this view is being built. 7752 */ 7753 public interface OnCreateContextMenuListener { 7754 /** 7755 * Called when the context menu for this view is being built. It is not 7756 * safe to hold onto the menu after this method returns. 7757 * 7758 * @param menu The context menu that is being built 7759 * @param v The view for which the context menu is being built 7760 * @param menuInfo Extra information about the item for which the 7761 * context menu should be shown. This information will vary 7762 * depending on the class of v. 7763 */ 7764 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 7765 } 7766 7767 private final class UnsetPressedState implements Runnable { 7768 public void run() { 7769 setPressed(false); 7770 } 7771 } 7772 7773 /** 7774 * Base class for derived classes that want to save and restore their own 7775 * state in {@link android.view.View#onSaveInstanceState()}. 7776 */ 7777 public static class BaseSavedState extends AbsSavedState { 7778 /** 7779 * Constructor used when reading from a parcel. Reads the state of the superclass. 7780 * 7781 * @param source 7782 */ 7783 public BaseSavedState(Parcel source) { 7784 super(source); 7785 } 7786 7787 /** 7788 * Constructor called by derived classes when creating their SavedState objects 7789 * 7790 * @param superState The state of the superclass of this view 7791 */ 7792 public BaseSavedState(Parcelable superState) { 7793 super(superState); 7794 } 7795 7796 public static final Parcelable.Creator<BaseSavedState> CREATOR = 7797 new Parcelable.Creator<BaseSavedState>() { 7798 public BaseSavedState createFromParcel(Parcel in) { 7799 return new BaseSavedState(in); 7800 } 7801 7802 public BaseSavedState[] newArray(int size) { 7803 return new BaseSavedState[size]; 7804 } 7805 }; 7806 } 7807 7808 /** 7809 * A set of information given to a view when it is attached to its parent 7810 * window. 7811 */ 7812 static class AttachInfo { 7813 7814 interface Callbacks { 7815 void playSoundEffect(int effectId); 7816 boolean performHapticFeedback(int effectId, boolean always); 7817 } 7818 7819 /** 7820 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 7821 * to a Handler. This class contains the target (View) to invalidate and 7822 * the coordinates of the dirty rectangle. 7823 * 7824 * For performance purposes, this class also implements a pool of up to 7825 * POOL_LIMIT objects that get reused. This reduces memory allocations 7826 * whenever possible. 7827 * 7828 * The pool is implemented as a linked list of InvalidateInfo object with 7829 * the root pointing to the next available InvalidateInfo. If the root 7830 * is null (i.e. when all instances from the pool have been acquired), 7831 * then a new InvalidateInfo is created and returned to the caller. 7832 * 7833 * An InvalidateInfo is sent back to the pool by calling its release() 7834 * method. If the pool is full the object is simply discarded. 7835 * 7836 * This implementation follows the object pool pattern used in the 7837 * MotionEvent class. 7838 */ 7839 static class InvalidateInfo { 7840 private static final int POOL_LIMIT = 10; 7841 private static final Object sLock = new Object(); 7842 7843 private static int sAcquiredCount = 0; 7844 private static InvalidateInfo sRoot; 7845 7846 private InvalidateInfo next; 7847 7848 View target; 7849 7850 int left; 7851 int top; 7852 int right; 7853 int bottom; 7854 7855 static InvalidateInfo acquire() { 7856 synchronized (sLock) { 7857 if (sRoot == null) { 7858 return new InvalidateInfo(); 7859 } 7860 7861 InvalidateInfo info = sRoot; 7862 sRoot = info.next; 7863 sAcquiredCount--; 7864 7865 return info; 7866 } 7867 } 7868 7869 void release() { 7870 synchronized (sLock) { 7871 if (sAcquiredCount < POOL_LIMIT) { 7872 sAcquiredCount++; 7873 next = sRoot; 7874 sRoot = this; 7875 } 7876 } 7877 } 7878 } 7879 7880 final IWindowSession mSession; 7881 7882 final IWindow mWindow; 7883 7884 final IBinder mWindowToken; 7885 7886 final Callbacks mRootCallbacks; 7887 7888 /** 7889 * The top view of the hierarchy. 7890 */ 7891 View mRootView; 7892 7893 IBinder mPanelParentWindowToken; 7894 Surface mSurface; 7895 7896 /** 7897 * Left position of this view's window 7898 */ 7899 int mWindowLeft; 7900 7901 /** 7902 * Top position of this view's window 7903 */ 7904 int mWindowTop; 7905 7906 /** 7907 * For windows that are full-screen but using insets to layout inside 7908 * of the screen decorations, these are the current insets for the 7909 * content of the window. 7910 */ 7911 final Rect mContentInsets = new Rect(); 7912 7913 /** 7914 * For windows that are full-screen but using insets to layout inside 7915 * of the screen decorations, these are the current insets for the 7916 * actual visible parts of the window. 7917 */ 7918 final Rect mVisibleInsets = new Rect(); 7919 7920 /** 7921 * The internal insets given by this window. This value is 7922 * supplied by the client (through 7923 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 7924 * be given to the window manager when changed to be used in laying 7925 * out windows behind it. 7926 */ 7927 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 7928 = new ViewTreeObserver.InternalInsetsInfo(); 7929 7930 /** 7931 * All views in the window's hierarchy that serve as scroll containers, 7932 * used to determine if the window can be resized or must be panned 7933 * to adjust for a soft input area. 7934 */ 7935 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 7936 7937 /** 7938 * Indicates whether the view's window currently has the focus. 7939 */ 7940 boolean mHasWindowFocus; 7941 7942 /** 7943 * The current visibility of the window. 7944 */ 7945 int mWindowVisibility; 7946 7947 /** 7948 * Indicates the time at which drawing started to occur. 7949 */ 7950 long mDrawingTime; 7951 7952 /** 7953 * Indicates whether the view's window is currently in touch mode. 7954 */ 7955 boolean mInTouchMode; 7956 7957 /** 7958 * Indicates that ViewRoot should trigger a global layout change 7959 * the next time it performs a traversal 7960 */ 7961 boolean mRecomputeGlobalAttributes; 7962 7963 /** 7964 * Set to true when attributes (like mKeepScreenOn) need to be 7965 * recomputed. 7966 */ 7967 boolean mAttributesChanged; 7968 7969 /** 7970 * Set during a traveral if any views want to keep the screen on. 7971 */ 7972 boolean mKeepScreenOn; 7973 7974 /** 7975 * Set if the visibility of any views has changed. 7976 */ 7977 boolean mViewVisibilityChanged; 7978 7979 /** 7980 * Set to true if a view has been scrolled. 7981 */ 7982 boolean mViewScrollChanged; 7983 7984 /** 7985 * Global to the view hierarchy used as a temporary for dealing with 7986 * x/y points in the transparent region computations. 7987 */ 7988 final int[] mTransparentLocation = new int[2]; 7989 7990 /** 7991 * Global to the view hierarchy used as a temporary for dealing with 7992 * x/y points in the ViewGroup.invalidateChild implementation. 7993 */ 7994 final int[] mInvalidateChildLocation = new int[2]; 7995 7996 /** 7997 * The view tree observer used to dispatch global events like 7998 * layout, pre-draw, touch mode change, etc. 7999 */ 8000 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 8001 8002 /** 8003 * A Canvas used by the view hierarchy to perform bitmap caching. 8004 */ 8005 Canvas mCanvas; 8006 8007 /** 8008 * A Handler supplied by a view's {@link android.view.ViewRoot}. This 8009 * handler can be used to pump events in the UI events queue. 8010 */ 8011 final Handler mHandler; 8012 8013 /** 8014 * Identifier for messages requesting the view to be invalidated. 8015 * Such messages should be sent to {@link #mHandler}. 8016 */ 8017 static final int INVALIDATE_MSG = 0x1; 8018 8019 /** 8020 * Identifier for messages requesting the view to invalidate a region. 8021 * Such messages should be sent to {@link #mHandler}. 8022 */ 8023 static final int INVALIDATE_RECT_MSG = 0x2; 8024 8025 /** 8026 * Temporary for use in computing invalidate rectangles while 8027 * calling up the hierarchy. 8028 */ 8029 final Rect mTmpInvalRect = new Rect(); 8030 8031 /** 8032 * Creates a new set of attachment information with the specified 8033 * events handler and thread. 8034 * 8035 * @param handler the events handler the view must use 8036 */ 8037 AttachInfo(IWindowSession session, IWindow window, 8038 Handler handler, Callbacks effectPlayer) { 8039 mSession = session; 8040 mWindow = window; 8041 mWindowToken = window.asBinder(); 8042 mHandler = handler; 8043 mRootCallbacks = effectPlayer; 8044 } 8045 } 8046 8047 /** 8048 * <p>ScrollabilityCache holds various fields used by a View when scrolling 8049 * is supported. This avoids keeping too many unused fields in most 8050 * instances of View.</p> 8051 */ 8052 private static class ScrollabilityCache { 8053 public int fadingEdgeLength; 8054 8055 public int scrollBarSize; 8056 public ScrollBarDrawable scrollBar; 8057 8058 public final Paint paint; 8059 public final Matrix matrix; 8060 public Shader shader; 8061 8062 private int mLastColor; 8063 8064 public ScrollabilityCache(ViewConfiguration configuration) { 8065 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 8066 scrollBarSize = configuration.getScaledScrollBarSize(); 8067 8068 paint = new Paint(); 8069 matrix = new Matrix(); 8070 // use use a height of 1, and then wack the matrix each time we 8071 // actually use it. 8072 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 8073 8074 paint.setShader(shader); 8075 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 8076 } 8077 8078 public void setFadeColor(int color) { 8079 if (color != 0 && color != mLastColor) { 8080 mLastColor = color; 8081 color |= 0xFF000000; 8082 8083 shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP); 8084 8085 paint.setShader(shader); 8086 // Restore the default transfer mode (src_over) 8087 paint.setXfermode(null); 8088 } 8089 } 8090 } 8091} 8092