View.java revision 105925376f8d0f6b318c9938c7b83ef7fef094da
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 if (mPendingCheckForLongPress != null) { 3413 removeCallbacks(mPendingCheckForLongPress); 3414 } 3415 } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { 3416 imm.focusIn(this); 3417 } 3418 refreshDrawableState(); 3419 } 3420 3421 /** 3422 * Returns true if this view is in a window that currently has window focus. 3423 * Note that this is not the same as the view itself having focus. 3424 * 3425 * @return True if this view is in a window that currently has window focus. 3426 */ 3427 public boolean hasWindowFocus() { 3428 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 3429 } 3430 3431 /** 3432 * Dispatch a window visibility change down the view hierarchy. 3433 * ViewGroups should override to route to their children. 3434 * 3435 * @param visibility The new visibility of the window. 3436 * 3437 * @see #onWindowVisibilityChanged 3438 */ 3439 public void dispatchWindowVisibilityChanged(int visibility) { 3440 onWindowVisibilityChanged(visibility); 3441 } 3442 3443 /** 3444 * Called when the window containing has change its visibility 3445 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 3446 * that this tells you whether or not your window is being made visible 3447 * to the window manager; this does <em>not</em> tell you whether or not 3448 * your window is obscured by other windows on the screen, even if it 3449 * is itself visible. 3450 * 3451 * @param visibility The new visibility of the window. 3452 */ 3453 protected void onWindowVisibilityChanged(int visibility) { 3454 } 3455 3456 /** 3457 * Returns the current visibility of the window this view is attached to 3458 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 3459 * 3460 * @return Returns the current visibility of the view's window. 3461 */ 3462 public int getWindowVisibility() { 3463 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 3464 } 3465 3466 /** 3467 * Retrieve the overall visible display size in which the window this view is 3468 * attached to has been positioned in. This takes into account screen 3469 * decorations above the window, for both cases where the window itself 3470 * is being position inside of them or the window is being placed under 3471 * then and covered insets are used for the window to position its content 3472 * inside. In effect, this tells you the available area where content can 3473 * be placed and remain visible to users. 3474 * 3475 * <p>This function requires an IPC back to the window manager to retrieve 3476 * the requested information, so should not be used in performance critical 3477 * code like drawing. 3478 * 3479 * @param outRect Filled in with the visible display frame. If the view 3480 * is not attached to a window, this is simply the raw display size. 3481 */ 3482 public void getWindowVisibleDisplayFrame(Rect outRect) { 3483 if (mAttachInfo != null) { 3484 try { 3485 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 3486 } catch (RemoteException e) { 3487 return; 3488 } 3489 // XXX This is really broken, and probably all needs to be done 3490 // in the window manager, and we need to know more about whether 3491 // we want the area behind or in front of the IME. 3492 final Rect insets = mAttachInfo.mVisibleInsets; 3493 outRect.left += insets.left; 3494 outRect.top += insets.top; 3495 outRect.right -= insets.right; 3496 outRect.bottom -= insets.bottom; 3497 return; 3498 } 3499 Display d = WindowManagerImpl.getDefault().getDefaultDisplay(); 3500 outRect.set(0, 0, d.getWidth(), d.getHeight()); 3501 } 3502 3503 /** 3504 * Private function to aggregate all per-view attributes in to the view 3505 * root. 3506 */ 3507 void dispatchCollectViewAttributes(int visibility) { 3508 performCollectViewAttributes(visibility); 3509 } 3510 3511 void performCollectViewAttributes(int visibility) { 3512 //noinspection PointlessBitwiseExpression 3513 if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON)) 3514 == (VISIBLE | KEEP_SCREEN_ON)) { 3515 mAttachInfo.mKeepScreenOn = true; 3516 } 3517 } 3518 3519 void needGlobalAttributesUpdate(boolean force) { 3520 AttachInfo ai = mAttachInfo; 3521 if (ai != null) { 3522 if (ai.mKeepScreenOn || force) { 3523 ai.mRecomputeGlobalAttributes = true; 3524 } 3525 } 3526 } 3527 3528 /** 3529 * Returns whether the device is currently in touch mode. Touch mode is entered 3530 * once the user begins interacting with the device by touch, and affects various 3531 * things like whether focus is always visible to the user. 3532 * 3533 * @return Whether the device is in touch mode. 3534 */ 3535 @ViewDebug.ExportedProperty 3536 public boolean isInTouchMode() { 3537 if (mAttachInfo != null) { 3538 return mAttachInfo.mInTouchMode; 3539 } else { 3540 return ViewRoot.isInTouchMode(); 3541 } 3542 } 3543 3544 /** 3545 * Returns the context the view is running in, through which it can 3546 * access the current theme, resources, etc. 3547 * 3548 * @return The view's Context. 3549 */ 3550 @ViewDebug.CapturedViewProperty 3551 public final Context getContext() { 3552 return mContext; 3553 } 3554 3555 /** 3556 * Handle a key event before it is processed by any input method 3557 * associated with the view hierarchy. This can be used to intercept 3558 * key events in special situations before the IME consumes them; a 3559 * typical example would be handling the BACK key to update the application's 3560 * UI instead of allowing the IME to see it and close itself. 3561 * 3562 * @param keyCode The value in event.getKeyCode(). 3563 * @param event Description of the key event. 3564 * @return If you handled the event, return true. If you want to allow the 3565 * event to be handled by the next receiver, return false. 3566 */ 3567 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 3568 return false; 3569 } 3570 3571 /** 3572 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3573 * KeyEvent.Callback.onKeyMultiple()}: perform press of the view 3574 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 3575 * is released, if the view is enabled and clickable. 3576 * 3577 * @param keyCode A key code that represents the button pressed, from 3578 * {@link android.view.KeyEvent}. 3579 * @param event The KeyEvent object that defines the button action. 3580 */ 3581 public boolean onKeyDown(int keyCode, KeyEvent event) { 3582 boolean result = false; 3583 3584 switch (keyCode) { 3585 case KeyEvent.KEYCODE_DPAD_CENTER: 3586 case KeyEvent.KEYCODE_ENTER: { 3587 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 3588 return true; 3589 } 3590 // Long clickable items don't necessarily have to be clickable 3591 if (((mViewFlags & CLICKABLE) == CLICKABLE || 3592 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) && 3593 (event.getRepeatCount() == 0)) { 3594 setPressed(true); 3595 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 3596 postCheckForLongClick(); 3597 } 3598 return true; 3599 } 3600 break; 3601 } 3602 } 3603 return result; 3604 } 3605 3606 /** 3607 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3608 * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view 3609 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or 3610 * {@link KeyEvent#KEYCODE_ENTER} is released. 3611 * 3612 * @param keyCode A key code that represents the button pressed, from 3613 * {@link android.view.KeyEvent}. 3614 * @param event The KeyEvent object that defines the button action. 3615 */ 3616 public boolean onKeyUp(int keyCode, KeyEvent event) { 3617 boolean result = false; 3618 3619 switch (keyCode) { 3620 case KeyEvent.KEYCODE_DPAD_CENTER: 3621 case KeyEvent.KEYCODE_ENTER: { 3622 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 3623 return true; 3624 } 3625 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 3626 setPressed(false); 3627 3628 if (!mHasPerformedLongPress) { 3629 // This is a tap, so remove the longpress check 3630 if (mPendingCheckForLongPress != null) { 3631 removeCallbacks(mPendingCheckForLongPress); 3632 } 3633 3634 result = performClick(); 3635 } 3636 } 3637 break; 3638 } 3639 } 3640 return result; 3641 } 3642 3643 /** 3644 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 3645 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 3646 * the event). 3647 * 3648 * @param keyCode A key code that represents the button pressed, from 3649 * {@link android.view.KeyEvent}. 3650 * @param repeatCount The number of times the action was made. 3651 * @param event The KeyEvent object that defines the button action. 3652 */ 3653 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 3654 return false; 3655 } 3656 3657 /** 3658 * Called when an unhandled key shortcut event occurs. 3659 * 3660 * @param keyCode The value in event.getKeyCode(). 3661 * @param event Description of the key event. 3662 * @return If you handled the event, return true. If you want to allow the 3663 * event to be handled by the next receiver, return false. 3664 */ 3665 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 3666 return false; 3667 } 3668 3669 /** 3670 * Check whether the called view is a text editor, in which case it 3671 * would make sense to automatically display a soft input window for 3672 * it. Subclasses should override this if they implement 3673 * {@link #onCreateInputConnection(EditorInfo)} to return true if 3674 * a call on that method would return a non-null InputConnection, and 3675 * they are really a first-class editor that the user would normally 3676 * start typing on when the go into a window containing your view. 3677 * 3678 * <p>The default implementation always returns false. This does 3679 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 3680 * will not be called or the user can not otherwise perform edits on your 3681 * view; it is just a hint to the system that this is not the primary 3682 * purpose of this view. 3683 * 3684 * @return Returns true if this view is a text editor, else false. 3685 */ 3686 public boolean onCheckIsTextEditor() { 3687 return false; 3688 } 3689 3690 /** 3691 * Create a new InputConnection for an InputMethod to interact 3692 * with the view. The default implementation returns null, since it doesn't 3693 * support input methods. You can override this to implement such support. 3694 * This is only needed for views that take focus and text input. 3695 * 3696 * <p>When implementing this, you probably also want to implement 3697 * {@link #onCheckIsTextEditor()} to indicate you will return a 3698 * non-null InputConnection. 3699 * 3700 * @param outAttrs Fill in with attribute information about the connection. 3701 */ 3702 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 3703 return null; 3704 } 3705 3706 /** 3707 * Called by the {@link android.view.inputmethod.InputMethodManager} 3708 * when a view who is not the current 3709 * input connection target is trying to make a call on the manager. The 3710 * default implementation returns false; you can override this to return 3711 * true for certain views if you are performing InputConnection proxying 3712 * to them. 3713 * @param view The View that is making the InputMethodManager call. 3714 * @return Return true to allow the call, false to reject. 3715 */ 3716 public boolean checkInputConnectionProxy(View view) { 3717 return false; 3718 } 3719 3720 /** 3721 * Show the context menu for this view. It is not safe to hold on to the 3722 * menu after returning from this method. 3723 * 3724 * @param menu The context menu to populate 3725 */ 3726 public void createContextMenu(ContextMenu menu) { 3727 ContextMenuInfo menuInfo = getContextMenuInfo(); 3728 3729 // Sets the current menu info so all items added to menu will have 3730 // my extra info set. 3731 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 3732 3733 onCreateContextMenu(menu); 3734 if (mOnCreateContextMenuListener != null) { 3735 mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 3736 } 3737 3738 // Clear the extra information so subsequent items that aren't mine don't 3739 // have my extra info. 3740 ((MenuBuilder)menu).setCurrentMenuInfo(null); 3741 3742 if (mParent != null) { 3743 mParent.createContextMenu(menu); 3744 } 3745 } 3746 3747 /** 3748 * Views should implement this if they have extra information to associate 3749 * with the context menu. The return result is supplied as a parameter to 3750 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 3751 * callback. 3752 * 3753 * @return Extra information about the item for which the context menu 3754 * should be shown. This information will vary across different 3755 * subclasses of View. 3756 */ 3757 protected ContextMenuInfo getContextMenuInfo() { 3758 return null; 3759 } 3760 3761 /** 3762 * Views should implement this if the view itself is going to add items to 3763 * the context menu. 3764 * 3765 * @param menu the context menu to populate 3766 */ 3767 protected void onCreateContextMenu(ContextMenu menu) { 3768 } 3769 3770 /** 3771 * Implement this method to handle trackball motion events. The 3772 * <em>relative</em> movement of the trackball since the last event 3773 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 3774 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 3775 * that a movement of 1 corresponds to the user pressing one DPAD key (so 3776 * they will often be fractional values, representing the more fine-grained 3777 * movement information available from a trackball). 3778 * 3779 * @param event The motion event. 3780 * @return True if the event was handled, false otherwise. 3781 */ 3782 public boolean onTrackballEvent(MotionEvent event) { 3783 return false; 3784 } 3785 3786 /** 3787 * Implement this method to handle touch screen motion events. 3788 * 3789 * @param event The motion event. 3790 * @return True if the event was handled, false otherwise. 3791 */ 3792 public boolean onTouchEvent(MotionEvent event) { 3793 final int viewFlags = mViewFlags; 3794 3795 if ((viewFlags & ENABLED_MASK) == DISABLED) { 3796 // A disabled view that is clickable still consumes the touch 3797 // events, it just doesn't respond to them. 3798 return (((viewFlags & CLICKABLE) == CLICKABLE || 3799 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); 3800 } 3801 3802 if (mTouchDelegate != null) { 3803 if (mTouchDelegate.onTouchEvent(event)) { 3804 return true; 3805 } 3806 } 3807 3808 if (((viewFlags & CLICKABLE) == CLICKABLE || 3809 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { 3810 switch (event.getAction()) { 3811 case MotionEvent.ACTION_UP: 3812 if ((mPrivateFlags & PRESSED) != 0) { 3813 // take focus if we don't have it already and we should in 3814 // touch mode. 3815 boolean focusTaken = false; 3816 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 3817 focusTaken = requestFocus(); 3818 } 3819 3820 if (!mHasPerformedLongPress) { 3821 // This is a tap, so remove the longpress check 3822 if (mPendingCheckForLongPress != null) { 3823 removeCallbacks(mPendingCheckForLongPress); 3824 } 3825 3826 // Only perform take click actions if we were in the pressed state 3827 if (!focusTaken) { 3828 performClick(); 3829 } 3830 } 3831 3832 if (mUnsetPressedState == null) { 3833 mUnsetPressedState = new UnsetPressedState(); 3834 } 3835 3836 if (!post(mUnsetPressedState)) { 3837 // If the post failed, unpress right now 3838 mUnsetPressedState.run(); 3839 } 3840 } 3841 break; 3842 3843 case MotionEvent.ACTION_DOWN: 3844 mPrivateFlags |= PRESSED; 3845 refreshDrawableState(); 3846 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 3847 postCheckForLongClick(); 3848 } 3849 break; 3850 3851 case MotionEvent.ACTION_CANCEL: 3852 mPrivateFlags &= ~PRESSED; 3853 refreshDrawableState(); 3854 break; 3855 3856 case MotionEvent.ACTION_MOVE: 3857 final int x = (int) event.getX(); 3858 final int y = (int) event.getY(); 3859 3860 // Be lenient about moving outside of buttons 3861 int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); 3862 if ((x < 0 - slop) || (x >= getWidth() + slop) || 3863 (y < 0 - slop) || (y >= getHeight() + slop)) { 3864 // Outside button 3865 if ((mPrivateFlags & PRESSED) != 0) { 3866 // Remove any future long press checks 3867 if (mPendingCheckForLongPress != null) { 3868 removeCallbacks(mPendingCheckForLongPress); 3869 } 3870 3871 // Need to switch from pressed to not pressed 3872 mPrivateFlags &= ~PRESSED; 3873 refreshDrawableState(); 3874 } 3875 } else { 3876 // Inside button 3877 if ((mPrivateFlags & PRESSED) == 0) { 3878 // Need to switch from not pressed to pressed 3879 mPrivateFlags |= PRESSED; 3880 refreshDrawableState(); 3881 } 3882 } 3883 break; 3884 } 3885 return true; 3886 } 3887 3888 return false; 3889 } 3890 3891 /** 3892 * Cancels a pending long press. Your subclass can use this if you 3893 * want the context menu to come up if the user presses and holds 3894 * at the same place, but you don't want it to come up if they press 3895 * and then move around enough to cause scrolling. 3896 */ 3897 public void cancelLongPress() { 3898 if (mPendingCheckForLongPress != null) { 3899 removeCallbacks(mPendingCheckForLongPress); 3900 } 3901 } 3902 3903 /** 3904 * Sets the TouchDelegate for this View. 3905 */ 3906 public void setTouchDelegate(TouchDelegate delegate) { 3907 mTouchDelegate = delegate; 3908 } 3909 3910 /** 3911 * Gets the TouchDelegate for this View. 3912 */ 3913 public TouchDelegate getTouchDelegate() { 3914 return mTouchDelegate; 3915 } 3916 3917 /** 3918 * Set flags controlling behavior of this view. 3919 * 3920 * @param flags Constant indicating the value which should be set 3921 * @param mask Constant indicating the bit range that should be changed 3922 */ 3923 void setFlags(int flags, int mask) { 3924 int old = mViewFlags; 3925 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 3926 3927 int changed = mViewFlags ^ old; 3928 if (changed == 0) { 3929 return; 3930 } 3931 int privateFlags = mPrivateFlags; 3932 3933 /* Check if the FOCUSABLE bit has changed */ 3934 if (((changed & FOCUSABLE_MASK) != 0) && 3935 ((privateFlags & HAS_BOUNDS) !=0)) { 3936 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 3937 && ((privateFlags & FOCUSED) != 0)) { 3938 /* Give up focus if we are no longer focusable */ 3939 clearFocus(); 3940 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 3941 && ((privateFlags & FOCUSED) == 0)) { 3942 /* 3943 * Tell the view system that we are now available to take focus 3944 * if no one else already has it. 3945 */ 3946 if (mParent != null) mParent.focusableViewAvailable(this); 3947 } 3948 } 3949 3950 if ((flags & VISIBILITY_MASK) == VISIBLE) { 3951 if ((changed & VISIBILITY_MASK) != 0) { 3952 /* 3953 * If this view is becoming visible, set the DRAWN flag so that 3954 * the next invalidate() will not be skipped. 3955 */ 3956 mPrivateFlags |= DRAWN; 3957 3958 needGlobalAttributesUpdate(true); 3959 3960 // a view becoming visible is worth notifying the parent 3961 // about in case nothing has focus. even if this specific view 3962 // isn't focusable, it may contain something that is, so let 3963 // the root view try to give this focus if nothing else does. 3964 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 3965 mParent.focusableViewAvailable(this); 3966 } 3967 } 3968 } 3969 3970 /* Check if the GONE bit has changed */ 3971 if ((changed & GONE) != 0) { 3972 needGlobalAttributesUpdate(false); 3973 requestLayout(); 3974 invalidate(); 3975 3976 if (((mViewFlags & VISIBILITY_MASK) == GONE) && hasFocus()) { 3977 clearFocus(); 3978 } 3979 if (mAttachInfo != null) { 3980 mAttachInfo.mViewVisibilityChanged = true; 3981 } 3982 } 3983 3984 /* Check if the VISIBLE bit has changed */ 3985 if ((changed & INVISIBLE) != 0) { 3986 needGlobalAttributesUpdate(false); 3987 invalidate(); 3988 3989 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) { 3990 // root view becoming invisible shouldn't clear focus 3991 if (getRootView() != this) { 3992 clearFocus(); 3993 } 3994 } 3995 if (mAttachInfo != null) { 3996 mAttachInfo.mViewVisibilityChanged = true; 3997 } 3998 } 3999 4000 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 4001 destroyDrawingCache(); 4002 } 4003 4004 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 4005 destroyDrawingCache(); 4006 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4007 } 4008 4009 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 4010 destroyDrawingCache(); 4011 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4012 } 4013 4014 if ((changed & DRAW_MASK) != 0) { 4015 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 4016 if (mBGDrawable != null) { 4017 mPrivateFlags &= ~SKIP_DRAW; 4018 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 4019 } else { 4020 mPrivateFlags |= SKIP_DRAW; 4021 } 4022 } else { 4023 mPrivateFlags &= ~SKIP_DRAW; 4024 } 4025 requestLayout(); 4026 invalidate(); 4027 } 4028 4029 if ((changed & KEEP_SCREEN_ON) != 0) { 4030 if (mParent != null) { 4031 mParent.recomputeViewAttributes(this); 4032 } 4033 } 4034 } 4035 4036 /** 4037 * Change the view's z order in the tree, so it's on top of other sibling 4038 * views 4039 */ 4040 public void bringToFront() { 4041 if (mParent != null) { 4042 mParent.bringChildToFront(this); 4043 } 4044 } 4045 4046 /** 4047 * This is called in response to an internal scroll in this view (i.e., the 4048 * view scrolled its own contents). This is typically as a result of 4049 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 4050 * called. 4051 * 4052 * @param l Current horizontal scroll origin. 4053 * @param t Current vertical scroll origin. 4054 * @param oldl Previous horizontal scroll origin. 4055 * @param oldt Previous vertical scroll origin. 4056 */ 4057 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 4058 mBackgroundSizeChanged = true; 4059 4060 final AttachInfo ai = mAttachInfo; 4061 if (ai != null) { 4062 ai.mViewScrollChanged = true; 4063 } 4064 } 4065 4066 /** 4067 * This is called during layout when the size of this view has changed. If 4068 * you were just added to the view hierarchy, you're called with the old 4069 * values of 0. 4070 * 4071 * @param w Current width of this view. 4072 * @param h Current height of this view. 4073 * @param oldw Old width of this view. 4074 * @param oldh Old height of this view. 4075 */ 4076 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 4077 } 4078 4079 /** 4080 * Called by draw to draw the child views. This may be overridden 4081 * by derived classes to gain control just before its children are drawn 4082 * (but after its own view has been drawn). 4083 * @param canvas the canvas on which to draw the view 4084 */ 4085 protected void dispatchDraw(Canvas canvas) { 4086 } 4087 4088 /** 4089 * Gets the parent of this view. Note that the parent is a 4090 * ViewParent and not necessarily a View. 4091 * 4092 * @return Parent of this view. 4093 */ 4094 public final ViewParent getParent() { 4095 return mParent; 4096 } 4097 4098 /** 4099 * Return the scrolled left position of this view. This is the left edge of 4100 * the displayed part of your view. You do not need to draw any pixels 4101 * farther left, since those are outside of the frame of your view on 4102 * screen. 4103 * 4104 * @return The left edge of the displayed part of your view, in pixels. 4105 */ 4106 public final int getScrollX() { 4107 return mScrollX; 4108 } 4109 4110 /** 4111 * Return the scrolled top position of this view. This is the top edge of 4112 * the displayed part of your view. You do not need to draw any pixels above 4113 * it, since those are outside of the frame of your view on screen. 4114 * 4115 * @return The top edge of the displayed part of your view, in pixels. 4116 */ 4117 public final int getScrollY() { 4118 return mScrollY; 4119 } 4120 4121 /** 4122 * Return the width of the your view. 4123 * 4124 * @return The width of your view, in pixels. 4125 */ 4126 @ViewDebug.ExportedProperty 4127 public final int getWidth() { 4128 return mRight - mLeft; 4129 } 4130 4131 /** 4132 * Return the height of your view. 4133 * 4134 * @return The height of your view, in pixels. 4135 */ 4136 @ViewDebug.ExportedProperty 4137 public final int getHeight() { 4138 return mBottom - mTop; 4139 } 4140 4141 /** 4142 * Return the visible drawing bounds of your view. Fills in the output 4143 * rectangle with the values from getScrollX(), getScrollY(), 4144 * getWidth(), and getHeight(). 4145 * 4146 * @param outRect The (scrolled) drawing bounds of the view. 4147 */ 4148 public void getDrawingRect(Rect outRect) { 4149 outRect.left = mScrollX; 4150 outRect.top = mScrollY; 4151 outRect.right = mScrollX + (mRight - mLeft); 4152 outRect.bottom = mScrollY + (mBottom - mTop); 4153 } 4154 4155 /** 4156 * The width of this view as measured in the most recent call to measure(). 4157 * This should be used during measurement and layout calculations only. Use 4158 * {@link #getWidth()} to see how wide a view is after layout. 4159 * 4160 * @return The measured width of this view. 4161 */ 4162 public final int getMeasuredWidth() { 4163 return mMeasuredWidth; 4164 } 4165 4166 /** 4167 * The height of this view as measured in the most recent call to measure(). 4168 * This should be used during measurement and layout calculations only. Use 4169 * {@link #getHeight()} to see how tall a view is after layout. 4170 * 4171 * @return The measured height of this view. 4172 */ 4173 public final int getMeasuredHeight() { 4174 return mMeasuredHeight; 4175 } 4176 4177 /** 4178 * Top position of this view relative to its parent. 4179 * 4180 * @return The top of this view, in pixels. 4181 */ 4182 @ViewDebug.CapturedViewProperty 4183 public final int getTop() { 4184 return mTop; 4185 } 4186 4187 /** 4188 * Bottom position of this view relative to its parent. 4189 * 4190 * @return The bottom of this view, in pixels. 4191 */ 4192 @ViewDebug.CapturedViewProperty 4193 public final int getBottom() { 4194 return mBottom; 4195 } 4196 4197 /** 4198 * Left position of this view relative to its parent. 4199 * 4200 * @return The left edge of this view, in pixels. 4201 */ 4202 @ViewDebug.CapturedViewProperty 4203 public final int getLeft() { 4204 return mLeft; 4205 } 4206 4207 /** 4208 * Right position of this view relative to its parent. 4209 * 4210 * @return The right edge of this view, in pixels. 4211 */ 4212 @ViewDebug.CapturedViewProperty 4213 public final int getRight() { 4214 return mRight; 4215 } 4216 4217 /** 4218 * Hit rectangle in parent's coordinates 4219 * 4220 * @param outRect The hit rectangle of the view. 4221 */ 4222 public void getHitRect(Rect outRect) { 4223 outRect.set(mLeft, mTop, mRight, mBottom); 4224 } 4225 4226 /** 4227 * When a view has focus and the user navigates away from it, the next view is searched for 4228 * starting from the rectangle filled in by this method. 4229 * 4230 * By default, the rectange is the {@link #getDrawingRect})of the view. However, if your 4231 * view maintains some idea of internal selection, such as a cursor, or a selected row 4232 * or column, you should override this method and fill in a more specific rectangle. 4233 * 4234 * @param r The rectangle to fill in, in this view's coordinates. 4235 */ 4236 public void getFocusedRect(Rect r) { 4237 getDrawingRect(r); 4238 } 4239 4240 /** 4241 * If some part of this view is not clipped by any of its parents, then 4242 * return that area in r in global (root) coordinates. To convert r to local 4243 * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x, 4244 * -globalOffset.y)) If the view is completely clipped or translated out, 4245 * return false. 4246 * 4247 * @param r If true is returned, r holds the global coordinates of the 4248 * visible portion of this view. 4249 * @param globalOffset If true is returned, globalOffset holds the dx,dy 4250 * between this view and its root. globalOffet may be null. 4251 * @return true if r is non-empty (i.e. part of the view is visible at the 4252 * root level. 4253 */ 4254 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 4255 int width = mRight - mLeft; 4256 int height = mBottom - mTop; 4257 if (width > 0 && height > 0) { 4258 r.set(0, 0, width, height); 4259 if (globalOffset != null) { 4260 globalOffset.set(-mScrollX, -mScrollY); 4261 } 4262 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 4263 } 4264 return false; 4265 } 4266 4267 public final boolean getGlobalVisibleRect(Rect r) { 4268 return getGlobalVisibleRect(r, null); 4269 } 4270 4271 public final boolean getLocalVisibleRect(Rect r) { 4272 Point offset = new Point(); 4273 if (getGlobalVisibleRect(r, offset)) { 4274 r.offset(-offset.x, -offset.y); // make r local 4275 return true; 4276 } 4277 return false; 4278 } 4279 4280 /** 4281 * Offset this view's vertical location by the specified number of pixels. 4282 * 4283 * @param offset the number of pixels to offset the view by 4284 */ 4285 public void offsetTopAndBottom(int offset) { 4286 mTop += offset; 4287 mBottom += offset; 4288 } 4289 4290 /** 4291 * Offset this view's horizontal location by the specified amount of pixels. 4292 * 4293 * @param offset the numer of pixels to offset the view by 4294 */ 4295 public void offsetLeftAndRight(int offset) { 4296 mLeft += offset; 4297 mRight += offset; 4298 } 4299 4300 /** 4301 * Get the LayoutParams associated with this view. All views should have 4302 * layout parameters. These supply parameters to the <i>parent</i> of this 4303 * view specifying how it should be arranged. There are many subclasses of 4304 * ViewGroup.LayoutParams, and these correspond to the different subclasses 4305 * of ViewGroup that are responsible for arranging their children. 4306 * @return The LayoutParams associated with this view 4307 */ 4308 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 4309 public ViewGroup.LayoutParams getLayoutParams() { 4310 return mLayoutParams; 4311 } 4312 4313 /** 4314 * Set the layout parameters associated with this view. These supply 4315 * parameters to the <i>parent</i> of this view specifying how it should be 4316 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 4317 * correspond to the different subclasses of ViewGroup that are responsible 4318 * for arranging their children. 4319 * 4320 * @param params the layout parameters for this view 4321 */ 4322 public void setLayoutParams(ViewGroup.LayoutParams params) { 4323 if (params == null) { 4324 throw new NullPointerException("params == null"); 4325 } 4326 mLayoutParams = params; 4327 requestLayout(); 4328 } 4329 4330 /** 4331 * Set the scrolled position of your view. This will cause a call to 4332 * {@link #onScrollChanged(int, int, int, int)} and the view will be 4333 * invalidated. 4334 * @param x the x position to scroll to 4335 * @param y the y position to scroll to 4336 */ 4337 public void scrollTo(int x, int y) { 4338 if (mScrollX != x || mScrollY != y) { 4339 int oldX = mScrollX; 4340 int oldY = mScrollY; 4341 mScrollX = x; 4342 mScrollY = y; 4343 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 4344 invalidate(); 4345 } 4346 } 4347 4348 /** 4349 * Move the scrolled position of your view. This will cause a call to 4350 * {@link #onScrollChanged(int, int, int, int)} and the view will be 4351 * invalidated. 4352 * @param x the amount of pixels to scroll by horizontally 4353 * @param y the amount of pixels to scroll by vertically 4354 */ 4355 public void scrollBy(int x, int y) { 4356 scrollTo(mScrollX + x, mScrollY + y); 4357 } 4358 4359 /** 4360 * Mark the the area defined by dirty as needing to be drawn. If the view is 4361 * visible, {@link #onDraw} will be called at some point in the future. 4362 * This must be called from a UI thread. To call from a non-UI thread, call 4363 * {@link #postInvalidate()}. 4364 * 4365 * WARNING: This method is destructive to dirty. 4366 * @param dirty the rectangle representing the bounds of the dirty region 4367 */ 4368 public void invalidate(Rect dirty) { 4369 if (ViewDebug.TRACE_HIERARCHY) { 4370 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4371 } 4372 4373 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4374 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4375 final ViewParent p = mParent; 4376 final AttachInfo ai = mAttachInfo; 4377 if (p != null && ai != null) { 4378 final int scrollX = mScrollX; 4379 final int scrollY = mScrollY; 4380 final Rect r = ai.mTmpInvalRect; 4381 r.set(dirty.left - scrollX, dirty.top - scrollY, 4382 dirty.right - scrollX, dirty.bottom - scrollY); 4383 mParent.invalidateChild(this, r); 4384 } 4385 } 4386 } 4387 4388 /** 4389 * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn. 4390 * The coordinates of the dirty rect are relative to the view. 4391 * If the view is visible, {@link #onDraw} will be called at some point 4392 * in the future. This must be called from a UI thread. To call 4393 * from a non-UI thread, call {@link #postInvalidate()}. 4394 * @param l the left position of the dirty region 4395 * @param t the top position of the dirty region 4396 * @param r the right position of the dirty region 4397 * @param b the bottom position of the dirty region 4398 */ 4399 public void invalidate(int l, int t, int r, int b) { 4400 if (ViewDebug.TRACE_HIERARCHY) { 4401 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4402 } 4403 4404 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4405 mPrivateFlags &= ~DRAWING_CACHE_VALID; 4406 final ViewParent p = mParent; 4407 final AttachInfo ai = mAttachInfo; 4408 if (p != null && ai != null && l < r && t < b) { 4409 final int scrollX = mScrollX; 4410 final int scrollY = mScrollY; 4411 final Rect tmpr = ai.mTmpInvalRect; 4412 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY); 4413 p.invalidateChild(this, tmpr); 4414 } 4415 } 4416 } 4417 4418 /** 4419 * Invalidate the whole view. If the view is visible, {@link #onDraw} will 4420 * be called at some point in the future. This must be called from a 4421 * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. 4422 */ 4423 public void invalidate() { 4424 if (ViewDebug.TRACE_HIERARCHY) { 4425 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); 4426 } 4427 4428 if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { 4429 mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID; 4430 final ViewParent p = mParent; 4431 final AttachInfo ai = mAttachInfo; 4432 if (p != null && ai != null) { 4433 final Rect r = ai.mTmpInvalRect; 4434 r.set(0, 0, mRight - mLeft, mBottom - mTop); 4435 // Don't call invalidate -- we don't want to internally scroll 4436 // our own bounds 4437 p.invalidateChild(this, r); 4438 } 4439 } 4440 } 4441 4442 /** 4443 * @return A handler associated with the thread running the View. This 4444 * handler can be used to pump events in the UI events queue. 4445 */ 4446 public Handler getHandler() { 4447 if (mAttachInfo != null) { 4448 return mAttachInfo.mHandler; 4449 } 4450 return null; 4451 } 4452 4453 /** 4454 * Causes the Runnable to be added to the message queue. 4455 * The runnable will be run on the user interface thread. 4456 * 4457 * @param action The Runnable that will be executed. 4458 * 4459 * @return Returns true if the Runnable was successfully placed in to the 4460 * message queue. Returns false on failure, usually because the 4461 * looper processing the message queue is exiting. 4462 */ 4463 public boolean post(Runnable action) { 4464 Handler handler; 4465 if (mAttachInfo != null) { 4466 handler = mAttachInfo.mHandler; 4467 } else { 4468 // Assume that post will succeed later 4469 ViewRoot.getRunQueue().post(action); 4470 return true; 4471 } 4472 4473 return handler.post(action); 4474 } 4475 4476 /** 4477 * Causes the Runnable to be added to the message queue, to be run 4478 * after the specified amount of time elapses. 4479 * The runnable will be run on the user interface thread. 4480 * 4481 * @param action The Runnable that will be executed. 4482 * @param delayMillis The delay (in milliseconds) until the Runnable 4483 * will be executed. 4484 * 4485 * @return true if the Runnable was successfully placed in to the 4486 * message queue. Returns false on failure, usually because the 4487 * looper processing the message queue is exiting. Note that a 4488 * result of true does not mean the Runnable will be processed -- 4489 * if the looper is quit before the delivery time of the message 4490 * occurs then the message will be dropped. 4491 */ 4492 public boolean postDelayed(Runnable action, long delayMillis) { 4493 Handler handler; 4494 if (mAttachInfo != null) { 4495 handler = mAttachInfo.mHandler; 4496 } else { 4497 // Assume that post will succeed later 4498 ViewRoot.getRunQueue().postDelayed(action, delayMillis); 4499 return true; 4500 } 4501 4502 return handler.postDelayed(action, delayMillis); 4503 } 4504 4505 /** 4506 * Removes the specified Runnable from the message queue. 4507 * 4508 * @param action The Runnable to remove from the message handling queue 4509 * 4510 * @return true if this view could ask the Handler to remove the Runnable, 4511 * false otherwise. When the returned value is true, the Runnable 4512 * may or may not have been actually removed from the message queue 4513 * (for instance, if the Runnable was not in the queue already.) 4514 */ 4515 public boolean removeCallbacks(Runnable action) { 4516 Handler handler; 4517 if (mAttachInfo != null) { 4518 handler = mAttachInfo.mHandler; 4519 } else { 4520 // Assume that post will succeed later 4521 ViewRoot.getRunQueue().removeCallbacks(action); 4522 return true; 4523 } 4524 4525 handler.removeCallbacks(action); 4526 return true; 4527 } 4528 4529 /** 4530 * Cause an invalidate to happen on a subsequent cycle through the event loop. 4531 * Use this to invalidate the View from a non-UI thread. 4532 * 4533 * @see #invalidate() 4534 */ 4535 public void postInvalidate() { 4536 postInvalidateDelayed(0); 4537 } 4538 4539 /** 4540 * Cause an invalidate of the specified area to happen on a subsequent cycle 4541 * through the event loop. Use this to invalidate the View from a non-UI thread. 4542 * 4543 * @param left The left coordinate of the rectangle to invalidate. 4544 * @param top The top coordinate of the rectangle to invalidate. 4545 * @param right The right coordinate of the rectangle to invalidate. 4546 * @param bottom The bottom coordinate of the rectangle to invalidate. 4547 * 4548 * @see #invalidate(int, int, int, int) 4549 * @see #invalidate(Rect) 4550 */ 4551 public void postInvalidate(int left, int top, int right, int bottom) { 4552 postInvalidateDelayed(0, left, top, right, bottom); 4553 } 4554 4555 /** 4556 * Cause an invalidate to happen on a subsequent cycle through the event 4557 * loop. Waits for the specified amount of time. 4558 * 4559 * @param delayMilliseconds the duration in milliseconds to delay the 4560 * invalidation by 4561 */ 4562 public void postInvalidateDelayed(long delayMilliseconds) { 4563 // We try only with the AttachInfo because there's no point in invalidating 4564 // if we are not attached to our window 4565 if (mAttachInfo != null) { 4566 Message msg = Message.obtain(); 4567 msg.what = AttachInfo.INVALIDATE_MSG; 4568 msg.obj = this; 4569 mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 4570 } 4571 } 4572 4573 /** 4574 * Cause an invalidate of the specified area to happen on a subsequent cycle 4575 * through the event loop. Waits for the specified amount of time. 4576 * 4577 * @param delayMilliseconds the duration in milliseconds to delay the 4578 * invalidation by 4579 * @param left The left coordinate of the rectangle to invalidate. 4580 * @param top The top coordinate of the rectangle to invalidate. 4581 * @param right The right coordinate of the rectangle to invalidate. 4582 * @param bottom The bottom coordinate of the rectangle to invalidate. 4583 */ 4584 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 4585 int right, int bottom) { 4586 4587 // We try only with the AttachInfo because there's no point in invalidating 4588 // if we are not attached to our window 4589 if (mAttachInfo != null) { 4590 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire(); 4591 info.target = this; 4592 info.left = left; 4593 info.top = top; 4594 info.right = right; 4595 info.bottom = bottom; 4596 4597 final Message msg = Message.obtain(); 4598 msg.what = AttachInfo.INVALIDATE_RECT_MSG; 4599 msg.obj = info; 4600 mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds); 4601 } 4602 } 4603 4604 /** 4605 * Called by a parent to request that a child update its values for mScrollX 4606 * and mScrollY if necessary. This will typically be done if the child is 4607 * animating a scroll using a {@link android.widget.Scroller Scroller} 4608 * object. 4609 */ 4610 public void computeScroll() { 4611 } 4612 4613 /** 4614 * <p>Indicate whether the horizontal edges are faded when the view is 4615 * scrolled horizontally.</p> 4616 * 4617 * @return true if the horizontal edges should are faded on scroll, false 4618 * otherwise 4619 * 4620 * @see #setHorizontalFadingEdgeEnabled(boolean) 4621 * @attr ref android.R.styleable#View_fadingEdge 4622 */ 4623 public boolean isHorizontalFadingEdgeEnabled() { 4624 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 4625 } 4626 4627 /** 4628 * <p>Define whether the horizontal edges should be faded when this view 4629 * is scrolled horizontally.</p> 4630 * 4631 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 4632 * be faded when the view is scrolled 4633 * horizontally 4634 * 4635 * @see #isHorizontalFadingEdgeEnabled() 4636 * @attr ref android.R.styleable#View_fadingEdge 4637 */ 4638 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 4639 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 4640 if (horizontalFadingEdgeEnabled) { 4641 initScrollCache(); 4642 } 4643 4644 mViewFlags ^= FADING_EDGE_HORIZONTAL; 4645 } 4646 } 4647 4648 /** 4649 * <p>Indicate whether the vertical edges are faded when the view is 4650 * scrolled horizontally.</p> 4651 * 4652 * @return true if the vertical edges should are faded on scroll, false 4653 * otherwise 4654 * 4655 * @see #setVerticalFadingEdgeEnabled(boolean) 4656 * @attr ref android.R.styleable#View_fadingEdge 4657 */ 4658 public boolean isVerticalFadingEdgeEnabled() { 4659 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 4660 } 4661 4662 /** 4663 * <p>Define whether the vertical edges should be faded when this view 4664 * is scrolled vertically.</p> 4665 * 4666 * @param verticalFadingEdgeEnabled true if the vertical edges should 4667 * be faded when the view is scrolled 4668 * vertically 4669 * 4670 * @see #isVerticalFadingEdgeEnabled() 4671 * @attr ref android.R.styleable#View_fadingEdge 4672 */ 4673 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 4674 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 4675 if (verticalFadingEdgeEnabled) { 4676 initScrollCache(); 4677 } 4678 4679 mViewFlags ^= FADING_EDGE_VERTICAL; 4680 } 4681 } 4682 4683 /** 4684 * Returns the strength, or intensity, of the top faded edge. The strength is 4685 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4686 * returns 0.0 or 1.0 but no value in between. 4687 * 4688 * Subclasses should override this method to provide a smoother fade transition 4689 * when scrolling occurs. 4690 * 4691 * @return the intensity of the top fade as a float between 0.0f and 1.0f 4692 */ 4693 protected float getTopFadingEdgeStrength() { 4694 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 4695 } 4696 4697 /** 4698 * Returns the strength, or intensity, of the bottom faded edge. The strength is 4699 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4700 * returns 0.0 or 1.0 but no value in between. 4701 * 4702 * Subclasses should override this method to provide a smoother fade transition 4703 * when scrolling occurs. 4704 * 4705 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 4706 */ 4707 protected float getBottomFadingEdgeStrength() { 4708 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 4709 computeVerticalScrollRange() ? 1.0f : 0.0f; 4710 } 4711 4712 /** 4713 * Returns the strength, or intensity, of the left faded edge. The strength is 4714 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4715 * returns 0.0 or 1.0 but no value in between. 4716 * 4717 * Subclasses should override this method to provide a smoother fade transition 4718 * when scrolling occurs. 4719 * 4720 * @return the intensity of the left fade as a float between 0.0f and 1.0f 4721 */ 4722 protected float getLeftFadingEdgeStrength() { 4723 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 4724 } 4725 4726 /** 4727 * Returns the strength, or intensity, of the right faded edge. The strength is 4728 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 4729 * returns 0.0 or 1.0 but no value in between. 4730 * 4731 * Subclasses should override this method to provide a smoother fade transition 4732 * when scrolling occurs. 4733 * 4734 * @return the intensity of the right fade as a float between 0.0f and 1.0f 4735 */ 4736 protected float getRightFadingEdgeStrength() { 4737 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 4738 computeHorizontalScrollRange() ? 1.0f : 0.0f; 4739 } 4740 4741 /** 4742 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 4743 * scrollbar is not drawn by default.</p> 4744 * 4745 * @return true if the horizontal scrollbar should be painted, false 4746 * otherwise 4747 * 4748 * @see #setHorizontalScrollBarEnabled(boolean) 4749 */ 4750 public boolean isHorizontalScrollBarEnabled() { 4751 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 4752 } 4753 4754 /** 4755 * <p>Define whether the horizontal scrollbar should be drawn or not. The 4756 * scrollbar is not drawn by default.</p> 4757 * 4758 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 4759 * be painted 4760 * 4761 * @see #isHorizontalScrollBarEnabled() 4762 */ 4763 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 4764 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 4765 mViewFlags ^= SCROLLBARS_HORIZONTAL; 4766 recomputePadding(); 4767 } 4768 } 4769 4770 /** 4771 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 4772 * scrollbar is not drawn by default.</p> 4773 * 4774 * @return true if the vertical scrollbar should be painted, false 4775 * otherwise 4776 * 4777 * @see #setVerticalScrollBarEnabled(boolean) 4778 */ 4779 public boolean isVerticalScrollBarEnabled() { 4780 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 4781 } 4782 4783 /** 4784 * <p>Define whether the vertical scrollbar should be drawn or not. The 4785 * scrollbar is not drawn by default.</p> 4786 * 4787 * @param verticalScrollBarEnabled true if the vertical scrollbar should 4788 * be painted 4789 * 4790 * @see #isVerticalScrollBarEnabled() 4791 */ 4792 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 4793 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 4794 mViewFlags ^= SCROLLBARS_VERTICAL; 4795 recomputePadding(); 4796 } 4797 } 4798 4799 private void recomputePadding() { 4800 setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 4801 } 4802 4803 /** 4804 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 4805 * inset. When inset, they add to the padding of the view. And the scrollbars 4806 * can be drawn inside the padding area or on the edge of the view. For example, 4807 * if a view has a background drawable and you want to draw the scrollbars 4808 * inside the padding specified by the drawable, you can use 4809 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 4810 * appear at the edge of the view, ignoring the padding, then you can use 4811 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 4812 * @param style the style of the scrollbars. Should be one of 4813 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 4814 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 4815 * @see #SCROLLBARS_INSIDE_OVERLAY 4816 * @see #SCROLLBARS_INSIDE_INSET 4817 * @see #SCROLLBARS_OUTSIDE_OVERLAY 4818 * @see #SCROLLBARS_OUTSIDE_INSET 4819 */ 4820 public void setScrollBarStyle(int style) { 4821 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 4822 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 4823 recomputePadding(); 4824 } 4825 } 4826 4827 /** 4828 * <p>Returns the current scrollbar style.</p> 4829 * @return the current scrollbar style 4830 * @see #SCROLLBARS_INSIDE_OVERLAY 4831 * @see #SCROLLBARS_INSIDE_INSET 4832 * @see #SCROLLBARS_OUTSIDE_OVERLAY 4833 * @see #SCROLLBARS_OUTSIDE_INSET 4834 */ 4835 public int getScrollBarStyle() { 4836 return mViewFlags & SCROLLBARS_STYLE_MASK; 4837 } 4838 4839 /** 4840 * <p>Compute the horizontal range that the horizontal scrollbar 4841 * represents.</p> 4842 * 4843 * <p>The range is expressed in arbitrary units that must be the same as the 4844 * units used by {@link #computeHorizontalScrollExtent()} and 4845 * {@link #computeHorizontalScrollOffset()}.</p> 4846 * 4847 * <p>The default range is the drawing width of this view.</p> 4848 * 4849 * @return the total horizontal range represented by the horizontal 4850 * scrollbar 4851 * 4852 * @see #computeHorizontalScrollExtent() 4853 * @see #computeHorizontalScrollOffset() 4854 * @see android.widget.ScrollBarDrawable 4855 */ 4856 protected int computeHorizontalScrollRange() { 4857 return getWidth(); 4858 } 4859 4860 /** 4861 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 4862 * within the horizontal range. This value is used to compute the position 4863 * of the thumb within the scrollbar's track.</p> 4864 * 4865 * <p>The range is expressed in arbitrary units that must be the same as the 4866 * units used by {@link #computeHorizontalScrollRange()} and 4867 * {@link #computeHorizontalScrollExtent()}.</p> 4868 * 4869 * <p>The default offset is the scroll offset of this view.</p> 4870 * 4871 * @return the horizontal offset of the scrollbar's thumb 4872 * 4873 * @see #computeHorizontalScrollRange() 4874 * @see #computeHorizontalScrollExtent() 4875 * @see android.widget.ScrollBarDrawable 4876 */ 4877 protected int computeHorizontalScrollOffset() { 4878 return mScrollX; 4879 } 4880 4881 /** 4882 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 4883 * within the horizontal range. This value is used to compute the length 4884 * of the thumb within the scrollbar's track.</p> 4885 * 4886 * <p>The range is expressed in arbitrary units that must be the same as the 4887 * units used by {@link #computeHorizontalScrollRange()} and 4888 * {@link #computeHorizontalScrollOffset()}.</p> 4889 * 4890 * <p>The default extent is the drawing width of this view.</p> 4891 * 4892 * @return the horizontal extent of the scrollbar's thumb 4893 * 4894 * @see #computeHorizontalScrollRange() 4895 * @see #computeHorizontalScrollOffset() 4896 * @see android.widget.ScrollBarDrawable 4897 */ 4898 protected int computeHorizontalScrollExtent() { 4899 return getWidth(); 4900 } 4901 4902 /** 4903 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 4904 * 4905 * <p>The range is expressed in arbitrary units that must be the same as the 4906 * units used by {@link #computeVerticalScrollExtent()} and 4907 * {@link #computeVerticalScrollOffset()}.</p> 4908 * 4909 * @return the total vertical range represented by the vertical scrollbar 4910 * 4911 * <p>The default range is the drawing height of this view.</p> 4912 * 4913 * @see #computeVerticalScrollExtent() 4914 * @see #computeVerticalScrollOffset() 4915 * @see android.widget.ScrollBarDrawable 4916 */ 4917 protected int computeVerticalScrollRange() { 4918 return getHeight(); 4919 } 4920 4921 /** 4922 * <p>Compute the vertical offset of the vertical scrollbar's thumb 4923 * within the horizontal range. This value is used to compute the position 4924 * of the thumb within the scrollbar's track.</p> 4925 * 4926 * <p>The range is expressed in arbitrary units that must be the same as the 4927 * units used by {@link #computeVerticalScrollRange()} and 4928 * {@link #computeVerticalScrollExtent()}.</p> 4929 * 4930 * <p>The default offset is the scroll offset of this view.</p> 4931 * 4932 * @return the vertical offset of the scrollbar's thumb 4933 * 4934 * @see #computeVerticalScrollRange() 4935 * @see #computeVerticalScrollExtent() 4936 * @see android.widget.ScrollBarDrawable 4937 */ 4938 protected int computeVerticalScrollOffset() { 4939 return mScrollY; 4940 } 4941 4942 /** 4943 * <p>Compute the vertical extent of the horizontal scrollbar's thumb 4944 * within the vertical range. This value is used to compute the length 4945 * of the thumb within the scrollbar's track.</p> 4946 * 4947 * <p>The range is expressed in arbitrary units that must be the same as the 4948 * units used by {@link #computeHorizontalScrollRange()} and 4949 * {@link #computeVerticalScrollOffset()}.</p> 4950 * 4951 * <p>The default extent is the drawing height of this view.</p> 4952 * 4953 * @return the vertical extent of the scrollbar's thumb 4954 * 4955 * @see #computeVerticalScrollRange() 4956 * @see #computeVerticalScrollOffset() 4957 * @see android.widget.ScrollBarDrawable 4958 */ 4959 protected int computeVerticalScrollExtent() { 4960 return getHeight(); 4961 } 4962 4963 /** 4964 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 4965 * scrollbars are painted only if they have been awakened first.</p> 4966 * 4967 * @param canvas the canvas on which to draw the scrollbars 4968 */ 4969 private void onDrawScrollBars(Canvas canvas) { 4970 // scrollbars are drawn only when the animation is running 4971 final ScrollabilityCache cache = mScrollCache; 4972 if (cache != null) { 4973 final int viewFlags = mViewFlags; 4974 4975 final boolean drawHorizontalScrollBar = 4976 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 4977 final boolean drawVerticalScrollBar = 4978 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 4979 && !isVerticalScrollBarHidden(); 4980 4981 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 4982 final int width = mRight - mLeft; 4983 final int height = mBottom - mTop; 4984 4985 final ScrollBarDrawable scrollBar = cache.scrollBar; 4986 int size = scrollBar.getSize(false); 4987 if (size <= 0) { 4988 size = cache.scrollBarSize; 4989 } 4990 4991 if (drawHorizontalScrollBar) { 4992 onDrawHorizontalScrollBar(canvas, scrollBar, width, height, size); 4993 } 4994 4995 if (drawVerticalScrollBar) { 4996 onDrawVerticalScrollBar(canvas, scrollBar, width, height, size); 4997 } 4998 } 4999 } 5000 } 5001 5002 /** 5003 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 5004 * FastScroller is visible. 5005 * @return whether to temporarily hide the vertical scrollbar 5006 * @hide 5007 */ 5008 protected boolean isVerticalScrollBarHidden() { 5009 return false; 5010 } 5011 5012 /** 5013 * <p>Draw the horizontal scrollbar if 5014 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 5015 * 5016 * <p>The length of the scrollbar and its thumb is computed according to the 5017 * values returned by {@link #computeHorizontalScrollRange()}, 5018 * {@link #computeHorizontalScrollExtent()} and 5019 * {@link #computeHorizontalScrollOffset()}. Refer to 5020 * {@link android.widget.ScrollBarDrawable} for more information about how 5021 * these values relate to each other.</p> 5022 * 5023 * @param canvas the canvas on which to draw the scrollbar 5024 * @param scrollBar the scrollbar's drawable 5025 * @param width the width of the drawing surface 5026 * @param height the height of the drawing surface 5027 * @param size the size of the scrollbar 5028 * 5029 * @see #isHorizontalScrollBarEnabled() 5030 * @see #computeHorizontalScrollRange() 5031 * @see #computeHorizontalScrollExtent() 5032 * @see #computeHorizontalScrollOffset() 5033 * @see android.widget.ScrollBarDrawable 5034 */ 5035 private void onDrawHorizontalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, 5036 int height, int size) { 5037 5038 final int viewFlags = mViewFlags; 5039 final int scrollX = mScrollX; 5040 final int scrollY = mScrollY; 5041 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 5042 final int top = scrollY + height - size - (mUserPaddingBottom & inside); 5043 5044 final int verticalScrollBarGap = 5045 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ? 5046 getVerticalScrollbarWidth() : 0; 5047 5048 scrollBar.setBounds(scrollX + (mPaddingLeft & inside), top, 5049 scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size); 5050 scrollBar.setParameters( 5051 computeHorizontalScrollRange(), 5052 computeHorizontalScrollOffset(), 5053 computeHorizontalScrollExtent(), false); 5054 scrollBar.draw(canvas); 5055 } 5056 5057 /** 5058 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 5059 * returns true.</p> 5060 * 5061 * <p>The length of the scrollbar and its thumb is computed according to the 5062 * values returned by {@link #computeVerticalScrollRange()}, 5063 * {@link #computeVerticalScrollExtent()} and 5064 * {@link #computeVerticalScrollOffset()}. Refer to 5065 * {@link android.widget.ScrollBarDrawable} for more information about how 5066 * these values relate to each other.</p> 5067 * 5068 * @param canvas the canvas on which to draw the scrollbar 5069 * @param scrollBar the scrollbar's drawable 5070 * @param width the width of the drawing surface 5071 * @param height the height of the drawing surface 5072 * @param size the size of the scrollbar 5073 * 5074 * @see #isVerticalScrollBarEnabled() 5075 * @see #computeVerticalScrollRange() 5076 * @see #computeVerticalScrollExtent() 5077 * @see #computeVerticalScrollOffset() 5078 * @see android.widget.ScrollBarDrawable 5079 */ 5080 private void onDrawVerticalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, 5081 int height, int size) { 5082 5083 final int scrollX = mScrollX; 5084 final int scrollY = mScrollY; 5085 final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 5086 // TODO: Deal with RTL languages to position scrollbar on left 5087 final int left = scrollX + width - size - (mUserPaddingRight & inside); 5088 5089 scrollBar.setBounds(left, scrollY + (mPaddingTop & inside), 5090 left + size, scrollY + height - (mUserPaddingBottom & inside)); 5091 scrollBar.setParameters( 5092 computeVerticalScrollRange(), 5093 computeVerticalScrollOffset(), 5094 computeVerticalScrollExtent(), true); 5095 scrollBar.draw(canvas); 5096 } 5097 5098 /** 5099 * Implement this to do your drawing. 5100 * 5101 * @param canvas the canvas on which the background will be drawn 5102 */ 5103 protected void onDraw(Canvas canvas) { 5104 } 5105 5106 /* 5107 * Caller is responsible for calling requestLayout if necessary. 5108 * (This allows addViewInLayout to not request a new layout.) 5109 */ 5110 void assignParent(ViewParent parent) { 5111 if (mParent == null) { 5112 mParent = parent; 5113 } else if (parent == null) { 5114 mParent = null; 5115 } else { 5116 throw new RuntimeException("view " + this + " being added, but" 5117 + " it already has a parent"); 5118 } 5119 } 5120 5121 /** 5122 * This is called when the view is attached to a window. At this point it 5123 * has a Surface and will start drawing. Note that this function is 5124 * guaranteed to be called before {@link #onDraw}, however it may be called 5125 * any time before the first onDraw -- including before or after 5126 * {@link #onMeasure}. 5127 * 5128 * @see #onDetachedFromWindow() 5129 */ 5130 protected void onAttachedToWindow() { 5131 if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) { 5132 mParent.requestTransparentRegion(this); 5133 } 5134 } 5135 5136 /** 5137 * This is called when the view is detached from a window. At this point it 5138 * no longer has a surface for drawing. 5139 * 5140 * @see #onAttachedToWindow() 5141 */ 5142 protected void onDetachedFromWindow() { 5143 if (mPendingCheckForLongPress != null) { 5144 removeCallbacks(mPendingCheckForLongPress); 5145 } 5146 destroyDrawingCache(); 5147 } 5148 5149 /** 5150 * @return The number of times this view has been attached to a window 5151 */ 5152 protected int getWindowAttachCount() { 5153 return mWindowAttachCount; 5154 } 5155 5156 /** 5157 * Retrieve a unique token identifying the window this view is attached to. 5158 * @return Return the window's token for use in 5159 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 5160 */ 5161 public IBinder getWindowToken() { 5162 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 5163 } 5164 5165 /** 5166 * Retrieve a unique token identifying the top-level "real" window of 5167 * the window that this view is attached to. That is, this is like 5168 * {@link #getWindowToken}, except if the window this view in is a panel 5169 * window (attached to another containing window), then the token of 5170 * the containing window is returned instead. 5171 * 5172 * @return Returns the associated window token, either 5173 * {@link #getWindowToken()} or the containing window's token. 5174 */ 5175 public IBinder getApplicationWindowToken() { 5176 AttachInfo ai = mAttachInfo; 5177 if (ai != null) { 5178 IBinder appWindowToken = ai.mPanelParentWindowToken; 5179 if (appWindowToken == null) { 5180 appWindowToken = ai.mWindowToken; 5181 } 5182 return appWindowToken; 5183 } 5184 return null; 5185 } 5186 5187 /** 5188 * Retrieve private session object this view hierarchy is using to 5189 * communicate with the window manager. 5190 * @return the session object to communicate with the window manager 5191 */ 5192 /*package*/ IWindowSession getWindowSession() { 5193 return mAttachInfo != null ? mAttachInfo.mSession : null; 5194 } 5195 5196 /** 5197 * @param info the {@link android.view.View.AttachInfo} to associated with 5198 * this view 5199 */ 5200 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 5201 //System.out.println("Attached! " + this); 5202 mAttachInfo = info; 5203 mWindowAttachCount++; 5204 if (mFloatingTreeObserver != null) { 5205 info.mTreeObserver.merge(mFloatingTreeObserver); 5206 mFloatingTreeObserver = null; 5207 } 5208 if ((mPrivateFlags&SCROLL_CONTAINER) != 0) { 5209 mAttachInfo.mScrollContainers.add(this); 5210 mPrivateFlags |= SCROLL_CONTAINER_ADDED; 5211 } 5212 performCollectViewAttributes(visibility); 5213 onAttachedToWindow(); 5214 int vis = info.mWindowVisibility; 5215 if (vis != GONE) { 5216 onWindowVisibilityChanged(vis); 5217 } 5218 } 5219 5220 void dispatchDetachedFromWindow() { 5221 //System.out.println("Detached! " + this); 5222 AttachInfo info = mAttachInfo; 5223 if (info != null) { 5224 int vis = info.mWindowVisibility; 5225 if (vis != GONE) { 5226 onWindowVisibilityChanged(GONE); 5227 } 5228 } 5229 5230 onDetachedFromWindow(); 5231 if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) { 5232 mAttachInfo.mScrollContainers.remove(this); 5233 mPrivateFlags &= ~SCROLL_CONTAINER_ADDED; 5234 } 5235 mAttachInfo = null; 5236 } 5237 5238 /** 5239 * Store this view hierarchy's frozen state into the given container. 5240 * 5241 * @param container The SparseArray in which to save the view's state. 5242 * 5243 * @see #restoreHierarchyState 5244 * @see #dispatchSaveInstanceState 5245 * @see #onSaveInstanceState 5246 */ 5247 public void saveHierarchyState(SparseArray<Parcelable> container) { 5248 dispatchSaveInstanceState(container); 5249 } 5250 5251 /** 5252 * Called by {@link #saveHierarchyState} to store the state for this view and its children. 5253 * May be overridden to modify how freezing happens to a view's children; for example, some 5254 * views may want to not store state for their children. 5255 * 5256 * @param container The SparseArray in which to save the view's state. 5257 * 5258 * @see #dispatchRestoreInstanceState 5259 * @see #saveHierarchyState 5260 * @see #onSaveInstanceState 5261 */ 5262 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 5263 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 5264 mPrivateFlags &= ~SAVE_STATE_CALLED; 5265 Parcelable state = onSaveInstanceState(); 5266 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 5267 throw new IllegalStateException( 5268 "Derived class did not call super.onSaveInstanceState()"); 5269 } 5270 if (state != null) { 5271 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 5272 // + ": " + state); 5273 container.put(mID, state); 5274 } 5275 } 5276 } 5277 5278 /** 5279 * Hook allowing a view to generate a representation of its internal state 5280 * that can later be used to create a new instance with that same state. 5281 * This state should only contain information that is not persistent or can 5282 * not be reconstructed later. For example, you will never store your 5283 * current position on screen because that will be computed again when a 5284 * new instance of the view is placed in its view hierarchy. 5285 * <p> 5286 * Some examples of things you may store here: the current cursor position 5287 * in a text view (but usually not the text itself since that is stored in a 5288 * content provider or other persistent storage), the currently selected 5289 * item in a list view. 5290 * 5291 * @return Returns a Parcelable object containing the view's current dynamic 5292 * state, or null if there is nothing interesting to save. The 5293 * default implementation returns null. 5294 * @see #onRestoreInstanceState 5295 * @see #saveHierarchyState 5296 * @see #dispatchSaveInstanceState 5297 * @see #setSaveEnabled(boolean) 5298 */ 5299 protected Parcelable onSaveInstanceState() { 5300 mPrivateFlags |= SAVE_STATE_CALLED; 5301 return BaseSavedState.EMPTY_STATE; 5302 } 5303 5304 /** 5305 * Restore this view hierarchy's frozen state from the given container. 5306 * 5307 * @param container The SparseArray which holds previously frozen states. 5308 * 5309 * @see #saveHierarchyState 5310 * @see #dispatchRestoreInstanceState 5311 * @see #onRestoreInstanceState 5312 */ 5313 public void restoreHierarchyState(SparseArray<Parcelable> container) { 5314 dispatchRestoreInstanceState(container); 5315 } 5316 5317 /** 5318 * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its 5319 * children. May be overridden to modify how restoreing happens to a view's children; for 5320 * example, some views may want to not store state for their children. 5321 * 5322 * @param container The SparseArray which holds previously saved state. 5323 * 5324 * @see #dispatchSaveInstanceState 5325 * @see #restoreHierarchyState 5326 * @see #onRestoreInstanceState 5327 */ 5328 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 5329 if (mID != NO_ID) { 5330 Parcelable state = container.get(mID); 5331 if (state != null) { 5332 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 5333 // + ": " + state); 5334 mPrivateFlags &= ~SAVE_STATE_CALLED; 5335 onRestoreInstanceState(state); 5336 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) { 5337 throw new IllegalStateException( 5338 "Derived class did not call super.onRestoreInstanceState()"); 5339 } 5340 } 5341 } 5342 } 5343 5344 /** 5345 * Hook allowing a view to re-apply a representation of its internal state that had previously 5346 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 5347 * null state. 5348 * 5349 * @param state The frozen state that had previously been returned by 5350 * {@link #onSaveInstanceState}. 5351 * 5352 * @see #onSaveInstanceState 5353 * @see #restoreHierarchyState 5354 * @see #dispatchRestoreInstanceState 5355 */ 5356 protected void onRestoreInstanceState(Parcelable state) { 5357 mPrivateFlags |= SAVE_STATE_CALLED; 5358 if (state != BaseSavedState.EMPTY_STATE && state != null) { 5359 throw new IllegalArgumentException("Wrong state class -- expecting View State"); 5360 } 5361 } 5362 5363 /** 5364 * <p>Return the time at which the drawing of the view hierarchy started.</p> 5365 * 5366 * @return the drawing start time in milliseconds 5367 */ 5368 public long getDrawingTime() { 5369 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 5370 } 5371 5372 /** 5373 * <p>Enables or disables the duplication of the parent's state into this view. When 5374 * duplication is enabled, this view gets its drawable state from its parent rather 5375 * than from its own internal properties.</p> 5376 * 5377 * <p>Note: in the current implementation, setting this property to true after the 5378 * view was added to a ViewGroup might have no effect at all. This property should 5379 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 5380 * 5381 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 5382 * property is enabled, an exception will be thrown.</p> 5383 * 5384 * @param enabled True to enable duplication of the parent's drawable state, false 5385 * to disable it. 5386 * 5387 * @see #getDrawableState() 5388 * @see #isDuplicateParentStateEnabled() 5389 */ 5390 public void setDuplicateParentStateEnabled(boolean enabled) { 5391 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 5392 } 5393 5394 /** 5395 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 5396 * 5397 * @return True if this view's drawable state is duplicated from the parent, 5398 * false otherwise 5399 * 5400 * @see #getDrawableState() 5401 * @see #setDuplicateParentStateEnabled(boolean) 5402 */ 5403 public boolean isDuplicateParentStateEnabled() { 5404 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 5405 } 5406 5407 /** 5408 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 5409 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 5410 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 5411 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 5412 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 5413 * null.</p> 5414 * 5415 * @param enabled true to enable the drawing cache, false otherwise 5416 * 5417 * @see #isDrawingCacheEnabled() 5418 * @see #getDrawingCache() 5419 * @see #buildDrawingCache() 5420 */ 5421 public void setDrawingCacheEnabled(boolean enabled) { 5422 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 5423 } 5424 5425 /** 5426 * <p>Indicates whether the drawing cache is enabled for this view.</p> 5427 * 5428 * @return true if the drawing cache is enabled 5429 * 5430 * @see #setDrawingCacheEnabled(boolean) 5431 * @see #getDrawingCache() 5432 */ 5433 @ViewDebug.ExportedProperty 5434 public boolean isDrawingCacheEnabled() { 5435 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 5436 } 5437 5438 /** 5439 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 5440 * is null when caching is disabled. If caching is enabled and the cache is not ready, 5441 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 5442 * draw from the cache when the cache is enabled. To benefit from the cache, you must 5443 * request the drawing cache by calling this method and draw it on screen if the 5444 * returned bitmap is not null.</p> 5445 * 5446 * @return a bitmap representing this view or null if cache is disabled 5447 * 5448 * @see #setDrawingCacheEnabled(boolean) 5449 * @see #isDrawingCacheEnabled() 5450 * @see #buildDrawingCache() 5451 * @see #destroyDrawingCache() 5452 */ 5453 public Bitmap getDrawingCache() { 5454 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 5455 return null; 5456 } 5457 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 5458 buildDrawingCache(); 5459 } 5460 return mDrawingCache == null ? null : mDrawingCache.get(); 5461 } 5462 5463 /** 5464 * <p>Frees the resources used by the drawing cache. If you call 5465 * {@link #buildDrawingCache()} manually without calling 5466 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 5467 * should cleanup the cache with this method afterwards.</p> 5468 * 5469 * @see #setDrawingCacheEnabled(boolean) 5470 * @see #buildDrawingCache() 5471 * @see #getDrawingCache() 5472 */ 5473 public void destroyDrawingCache() { 5474 if (mDrawingCache != null) { 5475 final Bitmap bitmap = mDrawingCache.get(); 5476 if (bitmap != null) bitmap.recycle(); 5477 mDrawingCache = null; 5478 } 5479 } 5480 5481 /** 5482 * Setting a solid background color for the drawing cache's bitmaps will improve 5483 * perfromance and memory usage. Note, though that this should only be used if this 5484 * view will always be drawn on top of a solid color. 5485 * 5486 * @param color The background color to use for the drawing cache's bitmap 5487 * 5488 * @see #setDrawingCacheEnabled(boolean) 5489 * @see #buildDrawingCache() 5490 * @see #getDrawingCache() 5491 */ 5492 public void setDrawingCacheBackgroundColor(int color) { 5493 mDrawingCacheBackgroundColor = color; 5494 } 5495 5496 /** 5497 * @see #setDrawingCacheBackgroundColor(int) 5498 * 5499 * @return The background color to used for the drawing cache's bitmap 5500 */ 5501 public int getDrawingCacheBackgroundColor() { 5502 return mDrawingCacheBackgroundColor; 5503 } 5504 5505 /** 5506 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 5507 * 5508 * <p>If you call {@link #buildDrawingCache()} manually without calling 5509 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 5510 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 5511 * 5512 * @see #getDrawingCache() 5513 * @see #destroyDrawingCache() 5514 */ 5515 public void buildDrawingCache() { 5516 if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDrawingCache == null || 5517 mDrawingCache.get() == null) { 5518 5519 if (ViewDebug.TRACE_HIERARCHY) { 5520 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE); 5521 } 5522 if (ViewRoot.PROFILE_DRAWING) { 5523 EventLog.writeEvent(60002, hashCode()); 5524 } 5525 5526 final int width = mRight - mLeft; 5527 final int height = mBottom - mTop; 5528 5529 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 5530 final boolean opaque = drawingCacheBackgroundColor != 0 || 5531 (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE); 5532 5533 if (width <= 0 || height <= 0 || 5534 (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes 5535 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { 5536 destroyDrawingCache(); 5537 return; 5538 } 5539 5540 boolean clear = true; 5541 Bitmap bitmap = mDrawingCache == null ? null : mDrawingCache.get(); 5542 5543 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 5544 5545 Bitmap.Config quality; 5546 if (!opaque) { 5547 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 5548 case DRAWING_CACHE_QUALITY_AUTO: 5549 quality = Bitmap.Config.ARGB_8888; 5550 break; 5551 case DRAWING_CACHE_QUALITY_LOW: 5552 quality = Bitmap.Config.ARGB_4444; 5553 break; 5554 case DRAWING_CACHE_QUALITY_HIGH: 5555 quality = Bitmap.Config.ARGB_8888; 5556 break; 5557 default: 5558 quality = Bitmap.Config.ARGB_8888; 5559 break; 5560 } 5561 } else { 5562 quality = Bitmap.Config.RGB_565; 5563 } 5564 5565 // Try to cleanup memory 5566 if (bitmap != null) bitmap.recycle(); 5567 5568 try { 5569 bitmap = Bitmap.createBitmap(width, height, quality); 5570 mDrawingCache = new SoftReference<Bitmap>(bitmap); 5571 } catch (OutOfMemoryError e) { 5572 // If there is not enough memory to create the bitmap cache, just 5573 // ignore the issue as bitmap caches are not required to draw the 5574 // view hierarchy 5575 mDrawingCache = null; 5576 return; 5577 } 5578 5579 clear = drawingCacheBackgroundColor != 0; 5580 } 5581 5582 Canvas canvas; 5583 final AttachInfo attachInfo = mAttachInfo; 5584 if (attachInfo != null) { 5585 canvas = attachInfo.mCanvas; 5586 if (canvas == null) { 5587 canvas = new Canvas(); 5588 } 5589 canvas.setBitmap(bitmap); 5590 // Temporarily clobber the cached Canvas in case one of our children 5591 // is also using a drawing cache. Without this, the children would 5592 // steal the canvas by attaching their own bitmap to it and bad, bad 5593 // thing would happen (invisible views, corrupted drawings, etc.) 5594 attachInfo.mCanvas = null; 5595 } else { 5596 // This case should hopefully never or seldom happen 5597 canvas = new Canvas(bitmap); 5598 } 5599 5600 if (clear) { 5601 bitmap.eraseColor(drawingCacheBackgroundColor); 5602 } 5603 5604 computeScroll(); 5605 final int restoreCount = canvas.save(); 5606 canvas.translate(-mScrollX, -mScrollY); 5607 5608 mPrivateFlags |= DRAWN; 5609 5610 // Fast path for layouts with no backgrounds 5611 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { 5612 if (ViewDebug.TRACE_HIERARCHY) { 5613 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 5614 } 5615 dispatchDraw(canvas); 5616 } else { 5617 draw(canvas); 5618 } 5619 5620 canvas.restoreToCount(restoreCount); 5621 5622 if (attachInfo != null) { 5623 // Restore the cached Canvas for our siblings 5624 attachInfo.mCanvas = canvas; 5625 } 5626 mPrivateFlags |= DRAWING_CACHE_VALID; 5627 } 5628 } 5629 5630 /** 5631 * Indicates whether this View is currently in edit mode. A View is usually 5632 * in edit mode when displayed within a developer tool. For instance, if 5633 * this View is being drawn by a visual user interface builder, this method 5634 * should return true. 5635 * 5636 * Subclasses should check the return value of this method to provide 5637 * different behaviors if their normal behavior might interfere with the 5638 * host environment. For instance: the class spawns a thread in its 5639 * constructor, the drawing code relies on device-specific features, etc. 5640 * 5641 * This method is usually checked in the drawing code of custom widgets. 5642 * 5643 * @return True if this View is in edit mode, false otherwise. 5644 */ 5645 public boolean isInEditMode() { 5646 return false; 5647 } 5648 5649 /** 5650 * If the View draws content inside its padding and enables fading edges, 5651 * it needs to support padding offsets. Padding offsets are added to the 5652 * fading edges to extend the length of the fade so that it covers pixels 5653 * drawn inside the padding. 5654 * 5655 * Subclasses of this class should override this method if they need 5656 * to draw content inside the padding. 5657 * 5658 * @return True if padding offset must be applied, false otherwise. 5659 * 5660 * @see #getLeftPaddingOffset() 5661 * @see #getRightPaddingOffset() 5662 * @see #getTopPaddingOffset() 5663 * @see #getBottomPaddingOffset() 5664 * 5665 * @since CURRENT 5666 */ 5667 protected boolean isPaddingOffsetRequired() { 5668 return false; 5669 } 5670 5671 /** 5672 * Amount by which to extend the left fading region. Called only when 5673 * {@link #isPaddingOffsetRequired()} returns true. 5674 * 5675 * @return The left padding offset in pixels. 5676 * 5677 * @see #isPaddingOffsetRequired() 5678 * 5679 * @since CURRENT 5680 */ 5681 protected int getLeftPaddingOffset() { 5682 return 0; 5683 } 5684 5685 /** 5686 * Amount by which to extend the right fading region. Called only when 5687 * {@link #isPaddingOffsetRequired()} returns true. 5688 * 5689 * @return The right padding offset in pixels. 5690 * 5691 * @see #isPaddingOffsetRequired() 5692 * 5693 * @since CURRENT 5694 */ 5695 protected int getRightPaddingOffset() { 5696 return 0; 5697 } 5698 5699 /** 5700 * Amount by which to extend the top fading region. Called only when 5701 * {@link #isPaddingOffsetRequired()} returns true. 5702 * 5703 * @return The top padding offset in pixels. 5704 * 5705 * @see #isPaddingOffsetRequired() 5706 * 5707 * @since CURRENT 5708 */ 5709 protected int getTopPaddingOffset() { 5710 return 0; 5711 } 5712 5713 /** 5714 * Amount by which to extend the bottom fading region. Called only when 5715 * {@link #isPaddingOffsetRequired()} returns true. 5716 * 5717 * @return The bottom padding offset in pixels. 5718 * 5719 * @see #isPaddingOffsetRequired() 5720 * 5721 * @since CURRENT 5722 */ 5723 protected int getBottomPaddingOffset() { 5724 return 0; 5725 } 5726 5727 /** 5728 * Manually render this view (and all of its children) to the given Canvas. 5729 * The view must have already done a full layout before this function is 5730 * called. When implementing a view, do not override this method; instead, 5731 * you should implement {@link #onDraw}. 5732 * 5733 * @param canvas The Canvas to which the View is rendered. 5734 */ 5735 public void draw(Canvas canvas) { 5736 if (ViewDebug.TRACE_HIERARCHY) { 5737 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); 5738 } 5739 5740 mPrivateFlags |= DRAWN; 5741 5742 /* 5743 * Draw traversal performs several drawing steps which must be executed 5744 * in the appropriate order: 5745 * 5746 * 1. Draw the background 5747 * 2. If necessary, save the canvas' layers to prepare for fading 5748 * 3. Draw view's content 5749 * 4. Draw children 5750 * 5. If necessary, draw the fading edges and restore layers 5751 * 6. Draw decorations (scrollbars for instance) 5752 */ 5753 5754 // Step 1, draw the background, if needed 5755 int saveCount; 5756 5757 final Drawable background = mBGDrawable; 5758 if (background != null) { 5759 final int scrollX = mScrollX; 5760 final int scrollY = mScrollY; 5761 5762 if (mBackgroundSizeChanged) { 5763 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 5764 mBackgroundSizeChanged = false; 5765 } 5766 5767 if ((scrollX | scrollY) == 0) { 5768 background.draw(canvas); 5769 } else { 5770 canvas.translate(scrollX, scrollY); 5771 background.draw(canvas); 5772 canvas.translate(-scrollX, -scrollY); 5773 } 5774 } 5775 5776 // skip step 2 & 5 if possible (common case) 5777 final int viewFlags = mViewFlags; 5778 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 5779 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 5780 if (!verticalEdges && !horizontalEdges) { 5781 // Step 3, draw the content 5782 onDraw(canvas); 5783 5784 // Step 4, draw the children 5785 dispatchDraw(canvas); 5786 5787 // Step 6, draw decorations (scrollbars) 5788 onDrawScrollBars(canvas); 5789 5790 // we're done... 5791 return; 5792 } 5793 5794 /* 5795 * Here we do the full fledged routine... 5796 * (this is an uncommon case where speed matters less, 5797 * this is why we repeat some of the tests that have been 5798 * done above) 5799 */ 5800 5801 boolean drawTop = false; 5802 boolean drawBottom = false; 5803 boolean drawLeft = false; 5804 boolean drawRight = false; 5805 5806 float topFadeStrength = 0.0f; 5807 float bottomFadeStrength = 0.0f; 5808 float leftFadeStrength = 0.0f; 5809 float rightFadeStrength = 0.0f; 5810 5811 // Step 2, save the canvas' layers 5812 int paddingLeft = mPaddingLeft; 5813 int paddingTop = mPaddingTop; 5814 5815 final boolean offsetRequired = isPaddingOffsetRequired(); 5816 if (offsetRequired) { 5817 paddingLeft += getLeftPaddingOffset(); 5818 paddingTop += getTopPaddingOffset(); 5819 } 5820 5821 int left = mScrollX + paddingLeft; 5822 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 5823 int top = mScrollY + paddingTop; 5824 int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop; 5825 5826 if (offsetRequired) { 5827 right += getRightPaddingOffset(); 5828 bottom += getBottomPaddingOffset(); 5829 } 5830 5831 final ScrollabilityCache scrollabilityCache = mScrollCache; 5832 int length = scrollabilityCache.fadingEdgeLength; 5833 5834 // clip the fade length if top and bottom fades overlap 5835 // overlapping fades produce odd-looking artifacts 5836 if (verticalEdges && (top + length > bottom - length)) { 5837 length = (bottom - top) / 2; 5838 } 5839 5840 // also clip horizontal fades if necessary 5841 if (horizontalEdges && (left + length > right - length)) { 5842 length = (right - left) / 2; 5843 } 5844 5845 if (verticalEdges) { 5846 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 5847 drawTop = topFadeStrength >= 0.0f; 5848 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 5849 drawBottom = bottomFadeStrength >= 0.0f; 5850 } 5851 5852 if (horizontalEdges) { 5853 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 5854 drawLeft = leftFadeStrength >= 0.0f; 5855 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 5856 drawRight = rightFadeStrength >= 0.0f; 5857 } 5858 5859 saveCount = canvas.getSaveCount(); 5860 5861 int solidColor = getSolidColor(); 5862 if (solidColor == 0) { 5863 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 5864 5865 if (drawTop) { 5866 canvas.saveLayer(left, top, right, top + length, null, flags); 5867 } 5868 5869 if (drawBottom) { 5870 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 5871 } 5872 5873 if (drawLeft) { 5874 canvas.saveLayer(left, top, left + length, bottom, null, flags); 5875 } 5876 5877 if (drawRight) { 5878 canvas.saveLayer(right - length, top, right, bottom, null, flags); 5879 } 5880 } else { 5881 scrollabilityCache.setFadeColor(solidColor); 5882 } 5883 5884 // Step 3, draw the content 5885 onDraw(canvas); 5886 5887 // Step 4, draw the children 5888 dispatchDraw(canvas); 5889 5890 // Step 5, draw the fade effect and restore layers 5891 final Paint p = scrollabilityCache.paint; 5892 final Matrix matrix = scrollabilityCache.matrix; 5893 final Shader fade = scrollabilityCache.shader; 5894 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 5895 5896 if (drawTop) { 5897 matrix.setScale(1, fadeHeight * topFadeStrength); 5898 matrix.postTranslate(left, top); 5899 fade.setLocalMatrix(matrix); 5900 canvas.drawRect(left, top, right, top + length, p); 5901 } 5902 5903 if (drawBottom) { 5904 matrix.setScale(1, fadeHeight * bottomFadeStrength); 5905 matrix.postRotate(180); 5906 matrix.postTranslate(left, bottom); 5907 fade.setLocalMatrix(matrix); 5908 canvas.drawRect(left, bottom - length, right, bottom, p); 5909 } 5910 5911 if (drawLeft) { 5912 matrix.setScale(1, fadeHeight * leftFadeStrength); 5913 matrix.postRotate(-90); 5914 matrix.postTranslate(left, top); 5915 fade.setLocalMatrix(matrix); 5916 canvas.drawRect(left, top, left + length, bottom, p); 5917 } 5918 5919 if (drawRight) { 5920 matrix.setScale(1, fadeHeight * rightFadeStrength); 5921 matrix.postRotate(90); 5922 matrix.postTranslate(right, top); 5923 fade.setLocalMatrix(matrix); 5924 canvas.drawRect(right - length, top, right, bottom, p); 5925 } 5926 5927 canvas.restoreToCount(saveCount); 5928 5929 // Step 6, draw decorations (scrollbars) 5930 onDrawScrollBars(canvas); 5931 } 5932 5933 /** 5934 * Override this if your view is known to always be drawn on top of a solid color background, 5935 * and needs to draw fading edges. Returning a non-zero color enables the view system to 5936 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 5937 * should be set to 0xFF. 5938 * 5939 * @see #setVerticalFadingEdgeEnabled 5940 * @see #setHorizontalFadingEdgeEnabled 5941 * 5942 * @return The known solid color background for this view, or 0 if the color may vary 5943 */ 5944 public int getSolidColor() { 5945 return 0; 5946 } 5947 5948 /** 5949 * Build a human readable string representation of the specified view flags. 5950 * 5951 * @param flags the view flags to convert to a string 5952 * @return a String representing the supplied flags 5953 */ 5954 private static String printFlags(int flags) { 5955 String output = ""; 5956 int numFlags = 0; 5957 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 5958 output += "TAKES_FOCUS"; 5959 numFlags++; 5960 } 5961 5962 switch (flags & VISIBILITY_MASK) { 5963 case INVISIBLE: 5964 if (numFlags > 0) { 5965 output += " "; 5966 } 5967 output += "INVISIBLE"; 5968 // USELESS HERE numFlags++; 5969 break; 5970 case GONE: 5971 if (numFlags > 0) { 5972 output += " "; 5973 } 5974 output += "GONE"; 5975 // USELESS HERE numFlags++; 5976 break; 5977 default: 5978 break; 5979 } 5980 return output; 5981 } 5982 5983 /** 5984 * Build a human readable string representation of the specified private 5985 * view flags. 5986 * 5987 * @param privateFlags the private view flags to convert to a string 5988 * @return a String representing the supplied flags 5989 */ 5990 private static String printPrivateFlags(int privateFlags) { 5991 String output = ""; 5992 int numFlags = 0; 5993 5994 if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) { 5995 output += "WANTS_FOCUS"; 5996 numFlags++; 5997 } 5998 5999 if ((privateFlags & FOCUSED) == FOCUSED) { 6000 if (numFlags > 0) { 6001 output += " "; 6002 } 6003 output += "FOCUSED"; 6004 numFlags++; 6005 } 6006 6007 if ((privateFlags & SELECTED) == SELECTED) { 6008 if (numFlags > 0) { 6009 output += " "; 6010 } 6011 output += "SELECTED"; 6012 numFlags++; 6013 } 6014 6015 if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) { 6016 if (numFlags > 0) { 6017 output += " "; 6018 } 6019 output += "IS_ROOT_NAMESPACE"; 6020 numFlags++; 6021 } 6022 6023 if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) { 6024 if (numFlags > 0) { 6025 output += " "; 6026 } 6027 output += "HAS_BOUNDS"; 6028 numFlags++; 6029 } 6030 6031 if ((privateFlags & DRAWN) == DRAWN) { 6032 if (numFlags > 0) { 6033 output += " "; 6034 } 6035 output += "DRAWN"; 6036 // USELESS HERE numFlags++; 6037 } 6038 return output; 6039 } 6040 6041 /** 6042 * <p>Indicates whether or not this view's layout will be requested during 6043 * the next hierarchy layout pass.</p> 6044 * 6045 * @return true if the layout will be forced during next layout pass 6046 */ 6047 public boolean isLayoutRequested() { 6048 return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT; 6049 } 6050 6051 /** 6052 * Assign a size and position to a view and all of its 6053 * descendants 6054 * 6055 * <p>This is the second phase of the layout mechanism. 6056 * (The first is measuring). In this phase, each parent calls 6057 * layout on all of its children to position them. 6058 * This is typically done using the child measurements 6059 * that were stored in the measure pass(). 6060 * 6061 * Derived classes with children should override 6062 * onLayout. In that method, they should 6063 * call layout on each of their their children. 6064 * 6065 * @param l Left position, relative to parent 6066 * @param t Top position, relative to parent 6067 * @param r Right position, relative to parent 6068 * @param b Bottom position, relative to parent 6069 */ 6070 public final void layout(int l, int t, int r, int b) { 6071 boolean changed = setFrame(l, t, r, b); 6072 if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) { 6073 if (ViewDebug.TRACE_HIERARCHY) { 6074 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT); 6075 } 6076 6077 onLayout(changed, l, t, r, b); 6078 mPrivateFlags &= ~LAYOUT_REQUIRED; 6079 } 6080 mPrivateFlags &= ~FORCE_LAYOUT; 6081 } 6082 6083 /** 6084 * Called from layout when this view should 6085 * assign a size and position to each of its children. 6086 * 6087 * Derived classes with children should override 6088 * this method and call layout on each of 6089 * their their children. 6090 * @param changed This is a new size or position for this view 6091 * @param left Left position, relative to parent 6092 * @param top Top position, relative to parent 6093 * @param right Right position, relative to parent 6094 * @param bottom Bottom position, relative to parent 6095 */ 6096 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 6097 } 6098 6099 /** 6100 * Assign a size and position to this view. 6101 * 6102 * This is called from layout. 6103 * 6104 * @param left Left position, relative to parent 6105 * @param top Top position, relative to parent 6106 * @param right Right position, relative to parent 6107 * @param bottom Bottom position, relative to parent 6108 * @return true if the new size and position are different than the 6109 * previous ones 6110 * {@hide} 6111 */ 6112 protected boolean setFrame(int left, int top, int right, int bottom) { 6113 boolean changed = false; 6114 6115 if (DBG) { 6116 System.out.println(this + " View.setFrame(" + left + "," + top + "," 6117 + right + "," + bottom + ")"); 6118 } 6119 6120 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 6121 changed = true; 6122 6123 // Remember our drawn bit 6124 int drawn = mPrivateFlags & DRAWN; 6125 6126 // Invalidate our old position 6127 invalidate(); 6128 6129 6130 int oldWidth = mRight - mLeft; 6131 int oldHeight = mBottom - mTop; 6132 6133 mLeft = left; 6134 mTop = top; 6135 mRight = right; 6136 mBottom = bottom; 6137 6138 mPrivateFlags |= HAS_BOUNDS; 6139 6140 int newWidth = right - left; 6141 int newHeight = bottom - top; 6142 6143 if (newWidth != oldWidth || newHeight != oldHeight) { 6144 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 6145 } 6146 6147 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) { 6148 // If we are visible, force the DRAWN bit to on so that 6149 // this invalidate will go through (at least to our parent). 6150 // This is because someone may have invalidated this view 6151 // before this call to setFrame came in, therby clearing 6152 // the DRAWN bit. 6153 mPrivateFlags |= DRAWN; 6154 invalidate(); 6155 } 6156 6157 // Reset drawn bit to original value (invalidate turns it off) 6158 mPrivateFlags |= drawn; 6159 6160 mBackgroundSizeChanged = true; 6161 } 6162 return changed; 6163 } 6164 6165 /** 6166 * Finalize inflating a view from XML. This is called as the last phase 6167 * of inflation, after all child views have been added. 6168 * 6169 * <p>Even if the subclass overrides onFinishInflate, they should always be 6170 * sure to call the super method, so that we get called. 6171 */ 6172 protected void onFinishInflate() { 6173 } 6174 6175 /** 6176 * Returns the resources associated with this view. 6177 * 6178 * @return Resources object. 6179 */ 6180 public Resources getResources() { 6181 return mResources; 6182 } 6183 6184 /** 6185 * Invalidates the specified Drawable. 6186 * 6187 * @param drawable the drawable to invalidate 6188 */ 6189 public void invalidateDrawable(Drawable drawable) { 6190 if (verifyDrawable(drawable)) { 6191 final Rect dirty = drawable.getBounds(); 6192 final int scrollX = mScrollX; 6193 final int scrollY = mScrollY; 6194 6195 invalidate(dirty.left + scrollX, dirty.top + scrollY, 6196 dirty.right + scrollX, dirty.bottom + scrollY); 6197 } 6198 } 6199 6200 /** 6201 * Schedules an action on a drawable to occur at a specified time. 6202 * 6203 * @param who the recipient of the action 6204 * @param what the action to run on the drawable 6205 * @param when the time at which the action must occur. Uses the 6206 * {@link SystemClock#uptimeMillis} timebase. 6207 */ 6208 public void scheduleDrawable(Drawable who, Runnable what, long when) { 6209 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 6210 mAttachInfo.mHandler.postAtTime(what, who, when); 6211 } 6212 } 6213 6214 /** 6215 * Cancels a scheduled action on a drawable. 6216 * 6217 * @param who the recipient of the action 6218 * @param what the action to cancel 6219 */ 6220 public void unscheduleDrawable(Drawable who, Runnable what) { 6221 if (verifyDrawable(who) && what != null && mAttachInfo != null) { 6222 mAttachInfo.mHandler.removeCallbacks(what, who); 6223 } 6224 } 6225 6226 /** 6227 * Unschedule any events associated with the given Drawable. This can be 6228 * used when selecting a new Drawable into a view, so that the previous 6229 * one is completely unscheduled. 6230 * 6231 * @param who The Drawable to unschedule. 6232 * 6233 * @see #drawableStateChanged 6234 */ 6235 public void unscheduleDrawable(Drawable who) { 6236 if (mAttachInfo != null) { 6237 mAttachInfo.mHandler.removeCallbacksAndMessages(who); 6238 } 6239 } 6240 6241 /** 6242 * If your view subclass is displaying its own Drawable objects, it should 6243 * override this function and return true for any Drawable it is 6244 * displaying. This allows animations for those drawables to be 6245 * scheduled. 6246 * 6247 * <p>Be sure to call through to the super class when overriding this 6248 * function. 6249 * 6250 * @param who The Drawable to verify. Return true if it is one you are 6251 * displaying, else return the result of calling through to the 6252 * super class. 6253 * 6254 * @return boolean If true than the Drawable is being displayed in the 6255 * view; else false and it is not allowed to animate. 6256 * 6257 * @see #unscheduleDrawable 6258 * @see #drawableStateChanged 6259 */ 6260 protected boolean verifyDrawable(Drawable who) { 6261 return who == mBGDrawable; 6262 } 6263 6264 /** 6265 * This function is called whenever the state of the view changes in such 6266 * a way that it impacts the state of drawables being shown. 6267 * 6268 * <p>Be sure to call through to the superclass when overriding this 6269 * function. 6270 * 6271 * @see Drawable#setState 6272 */ 6273 protected void drawableStateChanged() { 6274 Drawable d = mBGDrawable; 6275 if (d != null && d.isStateful()) { 6276 d.setState(getDrawableState()); 6277 } 6278 } 6279 6280 /** 6281 * Call this to force a view to update its drawable state. This will cause 6282 * drawableStateChanged to be called on this view. Views that are interested 6283 * in the new state should call getDrawableState. 6284 * 6285 * @see #drawableStateChanged 6286 * @see #getDrawableState 6287 */ 6288 public void refreshDrawableState() { 6289 mPrivateFlags |= DRAWABLE_STATE_DIRTY; 6290 drawableStateChanged(); 6291 6292 ViewParent parent = mParent; 6293 if (parent != null) { 6294 parent.childDrawableStateChanged(this); 6295 } 6296 } 6297 6298 /** 6299 * Return an array of resource IDs of the drawable states representing the 6300 * current state of the view. 6301 * 6302 * @return The current drawable state 6303 * 6304 * @see Drawable#setState 6305 * @see #drawableStateChanged 6306 * @see #onCreateDrawableState 6307 */ 6308 public final int[] getDrawableState() { 6309 if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) { 6310 return mDrawableState; 6311 } else { 6312 mDrawableState = onCreateDrawableState(0); 6313 mPrivateFlags &= ~DRAWABLE_STATE_DIRTY; 6314 return mDrawableState; 6315 } 6316 } 6317 6318 /** 6319 * Generate the new {@link android.graphics.drawable.Drawable} state for 6320 * this view. This is called by the view 6321 * system when the cached Drawable state is determined to be invalid. To 6322 * retrieve the current state, you should use {@link #getDrawableState}. 6323 * 6324 * @param extraSpace if non-zero, this is the number of extra entries you 6325 * would like in the returned array in which you can place your own 6326 * states. 6327 * 6328 * @return Returns an array holding the current {@link Drawable} state of 6329 * the view. 6330 * 6331 * @see #mergeDrawableStates 6332 */ 6333 protected int[] onCreateDrawableState(int extraSpace) { 6334 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 6335 mParent instanceof View) { 6336 return ((View) mParent).onCreateDrawableState(extraSpace); 6337 } 6338 6339 int[] drawableState; 6340 6341 int privateFlags = mPrivateFlags; 6342 6343 int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0); 6344 6345 viewStateIndex = (viewStateIndex << 1) 6346 + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0); 6347 6348 viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0); 6349 6350 viewStateIndex = (viewStateIndex << 1) 6351 + (((privateFlags & SELECTED) != 0) ? 1 : 0); 6352 6353 final boolean hasWindowFocus = hasWindowFocus(); 6354 viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0); 6355 6356 drawableState = VIEW_STATE_SETS[viewStateIndex]; 6357 6358 //noinspection ConstantIfStatement 6359 if (false) { 6360 Log.i("View", "drawableStateIndex=" + viewStateIndex); 6361 Log.i("View", toString() 6362 + " pressed=" + ((privateFlags & PRESSED) != 0) 6363 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 6364 + " fo=" + hasFocus() 6365 + " sl=" + ((privateFlags & SELECTED) != 0) 6366 + " wf=" + hasWindowFocus 6367 + ": " + Arrays.toString(drawableState)); 6368 } 6369 6370 if (extraSpace == 0) { 6371 return drawableState; 6372 } 6373 6374 final int[] fullState; 6375 if (drawableState != null) { 6376 fullState = new int[drawableState.length + extraSpace]; 6377 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 6378 } else { 6379 fullState = new int[extraSpace]; 6380 } 6381 6382 return fullState; 6383 } 6384 6385 /** 6386 * Merge your own state values in <var>additionalState</var> into the base 6387 * state values <var>baseState</var> that were returned by 6388 * {@link #onCreateDrawableState}. 6389 * 6390 * @param baseState The base state values returned by 6391 * {@link #onCreateDrawableState}, which will be modified to also hold your 6392 * own additional state values. 6393 * 6394 * @param additionalState The additional state values you would like 6395 * added to <var>baseState</var>; this array is not modified. 6396 * 6397 * @return As a convenience, the <var>baseState</var> array you originally 6398 * passed into the function is returned. 6399 * 6400 * @see #onCreateDrawableState 6401 */ 6402 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 6403 final int N = baseState.length; 6404 int i = N - 1; 6405 while (i >= 0 && baseState[i] == 0) { 6406 i--; 6407 } 6408 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 6409 return baseState; 6410 } 6411 6412 /** 6413 * Sets the background color for this view. 6414 * @param color the color of the background 6415 */ 6416 public void setBackgroundColor(int color) { 6417 setBackgroundDrawable(new ColorDrawable(color)); 6418 } 6419 6420 /** 6421 * Set the background to a given resource. The resource should refer to 6422 * a Drawable object. 6423 * @param resid The identifier of the resource. 6424 * @attr ref android.R.styleable#View_background 6425 */ 6426 public void setBackgroundResource(int resid) { 6427 if (resid != 0 && resid == mBackgroundResource) { 6428 return; 6429 } 6430 6431 Drawable d= null; 6432 if (resid != 0) { 6433 d = mResources.getDrawable(resid); 6434 } 6435 setBackgroundDrawable(d); 6436 6437 mBackgroundResource = resid; 6438 } 6439 6440 /** 6441 * Set the background to a given Drawable, or remove the background. If the 6442 * background has padding, this View's padding is set to the background's 6443 * padding. However, when a background is removed, this View's padding isn't 6444 * touched. If setting the padding is desired, please use 6445 * {@link #setPadding(int, int, int, int)}. 6446 * 6447 * @param d The Drawable to use as the background, or null to remove the 6448 * background 6449 */ 6450 public void setBackgroundDrawable(Drawable d) { 6451 boolean requestLayout = false; 6452 6453 mBackgroundResource = 0; 6454 6455 /* 6456 * Regardless of whether we're setting a new background or not, we want 6457 * to clear the previous drawable. 6458 */ 6459 if (mBGDrawable != null) { 6460 mBGDrawable.setCallback(null); 6461 unscheduleDrawable(mBGDrawable); 6462 } 6463 6464 if (d != null) { 6465 Rect padding = sThreadLocal.get(); 6466 if (padding == null) { 6467 padding = new Rect(); 6468 sThreadLocal.set(padding); 6469 } 6470 if (d.getPadding(padding)) { 6471 setPadding(padding.left, padding.top, padding.right, padding.bottom); 6472 } 6473 6474 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 6475 // if it has a different minimum size, we should layout again 6476 if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() || 6477 mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) { 6478 requestLayout = true; 6479 } 6480 6481 d.setCallback(this); 6482 if (d.isStateful()) { 6483 d.setState(getDrawableState()); 6484 } 6485 d.setVisible(getVisibility() == VISIBLE, false); 6486 mBGDrawable = d; 6487 6488 if ((mPrivateFlags & SKIP_DRAW) != 0) { 6489 mPrivateFlags &= ~SKIP_DRAW; 6490 mPrivateFlags |= ONLY_DRAWS_BACKGROUND; 6491 requestLayout = true; 6492 } 6493 } else { 6494 /* Remove the background */ 6495 mBGDrawable = null; 6496 6497 if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) { 6498 /* 6499 * This view ONLY drew the background before and we're removing 6500 * the background, so now it won't draw anything 6501 * (hence we SKIP_DRAW) 6502 */ 6503 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND; 6504 mPrivateFlags |= SKIP_DRAW; 6505 } 6506 6507 /* 6508 * When the background is set, we try to apply its padding to this 6509 * View. When the background is removed, we don't touch this View's 6510 * padding. This is noted in the Javadocs. Hence, we don't need to 6511 * requestLayout(), the invalidate() below is sufficient. 6512 */ 6513 6514 // The old background's minimum size could have affected this 6515 // View's layout, so let's requestLayout 6516 requestLayout = true; 6517 } 6518 6519 if (requestLayout) { 6520 requestLayout(); 6521 } 6522 6523 mBackgroundSizeChanged = true; 6524 invalidate(); 6525 } 6526 6527 /** 6528 * Gets the background drawable 6529 * @return The drawable used as the background for this view, if any. 6530 */ 6531 public Drawable getBackground() { 6532 return mBGDrawable; 6533 } 6534 6535 /** 6536 * Sets the padding. The view may add on the space required to display 6537 * the scrollbars, depending on the style and visibility of the scrollbars. 6538 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 6539 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 6540 * from the values set in this call. 6541 * 6542 * @attr ref android.R.styleable#View_padding 6543 * @attr ref android.R.styleable#View_paddingBottom 6544 * @attr ref android.R.styleable#View_paddingLeft 6545 * @attr ref android.R.styleable#View_paddingRight 6546 * @attr ref android.R.styleable#View_paddingTop 6547 * @param left the left padding in pixels 6548 * @param top the top padding in pixels 6549 * @param right the right padding in pixels 6550 * @param bottom the bottom padding in pixels 6551 */ 6552 public void setPadding(int left, int top, int right, int bottom) { 6553 boolean changed = false; 6554 6555 mUserPaddingRight = right; 6556 mUserPaddingBottom = bottom; 6557 6558 final int viewFlags = mViewFlags; 6559 6560 // Common case is there are no scroll bars. 6561 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 6562 // TODO: Deal with RTL languages to adjust left padding instead of right. 6563 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 6564 right += (viewFlags & SCROLLBARS_INSET_MASK) == 0 6565 ? 0 : getVerticalScrollbarWidth(); 6566 } 6567 if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) { 6568 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 6569 ? 0 : getHorizontalScrollbarHeight(); 6570 } 6571 } 6572 6573 if (mPaddingLeft != left) { 6574 changed = true; 6575 mPaddingLeft = left; 6576 } 6577 if (mPaddingTop != top) { 6578 changed = true; 6579 mPaddingTop = top; 6580 } 6581 if (mPaddingRight != right) { 6582 changed = true; 6583 mPaddingRight = right; 6584 } 6585 if (mPaddingBottom != bottom) { 6586 changed = true; 6587 mPaddingBottom = bottom; 6588 } 6589 6590 if (changed) { 6591 requestLayout(); 6592 } 6593 } 6594 6595 /** 6596 * Returns the top padding of this view. 6597 * 6598 * @return the top padding in pixels 6599 */ 6600 public int getPaddingTop() { 6601 return mPaddingTop; 6602 } 6603 6604 /** 6605 * Returns the bottom padding of this view. If there are inset and enabled 6606 * scrollbars, this value may include the space required to display the 6607 * scrollbars as well. 6608 * 6609 * @return the bottom padding in pixels 6610 */ 6611 public int getPaddingBottom() { 6612 return mPaddingBottom; 6613 } 6614 6615 /** 6616 * Returns the left padding of this view. If there are inset and enabled 6617 * scrollbars, this value may include the space required to display the 6618 * scrollbars as well. 6619 * 6620 * @return the left padding in pixels 6621 */ 6622 public int getPaddingLeft() { 6623 return mPaddingLeft; 6624 } 6625 6626 /** 6627 * Returns the right padding of this view. If there are inset and enabled 6628 * scrollbars, this value may include the space required to display the 6629 * scrollbars as well. 6630 * 6631 * @return the right padding in pixels 6632 */ 6633 public int getPaddingRight() { 6634 return mPaddingRight; 6635 } 6636 6637 /** 6638 * Changes the selection state of this view. A view can be selected or not. 6639 * Note that selection is not the same as focus. Views are typically 6640 * selected in the context of an AdapterView like ListView or GridView; 6641 * the selected view is the view that is highlighted. 6642 * 6643 * @param selected true if the view must be selected, false otherwise 6644 */ 6645 public void setSelected(boolean selected) { 6646 if (((mPrivateFlags & SELECTED) != 0) != selected) { 6647 mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0); 6648 invalidate(); 6649 refreshDrawableState(); 6650 dispatchSetSelected(selected); 6651 } 6652 } 6653 6654 /** 6655 * Dispatch setSelected to all of this View's children. 6656 * 6657 * @see #setSelected(boolean) 6658 * 6659 * @param selected The new selected state 6660 */ 6661 protected void dispatchSetSelected(boolean selected) { 6662 } 6663 6664 /** 6665 * Indicates the selection state of this view. 6666 * 6667 * @return true if the view is selected, false otherwise 6668 */ 6669 @ViewDebug.ExportedProperty 6670 public boolean isSelected() { 6671 return (mPrivateFlags & SELECTED) != 0; 6672 } 6673 6674 /** 6675 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 6676 * observer can be used to get notifications when global events, like 6677 * layout, happen. 6678 * 6679 * The returned ViewTreeObserver observer is not guaranteed to remain 6680 * valid for the lifetime of this View. If the caller of this method keeps 6681 * a long-lived reference to ViewTreeObserver, it should always check for 6682 * the return value of {@link ViewTreeObserver#isAlive()}. 6683 * 6684 * @return The ViewTreeObserver for this view's hierarchy. 6685 */ 6686 public ViewTreeObserver getViewTreeObserver() { 6687 if (mAttachInfo != null) { 6688 return mAttachInfo.mTreeObserver; 6689 } 6690 if (mFloatingTreeObserver == null) { 6691 mFloatingTreeObserver = new ViewTreeObserver(); 6692 } 6693 return mFloatingTreeObserver; 6694 } 6695 6696 /** 6697 * <p>Finds the topmost view in the current view hierarchy.</p> 6698 * 6699 * @return the topmost view containing this view 6700 */ 6701 public View getRootView() { 6702 if (mAttachInfo != null) { 6703 final View v = mAttachInfo.mRootView; 6704 if (v != null) { 6705 return v; 6706 } 6707 } 6708 6709 View parent = this; 6710 6711 while (parent.mParent != null && parent.mParent instanceof View) { 6712 parent = (View) parent.mParent; 6713 } 6714 6715 return parent; 6716 } 6717 6718 /** 6719 * <p>Computes the coordinates of this view on the screen. The argument 6720 * must be an array of two integers. After the method returns, the array 6721 * contains the x and y location in that order.</p> 6722 * 6723 * @param location an array of two integers in which to hold the coordinates 6724 */ 6725 public void getLocationOnScreen(int[] location) { 6726 getLocationInWindow(location); 6727 6728 final AttachInfo info = mAttachInfo; 6729 location[0] += info.mWindowLeft; 6730 location[1] += info.mWindowTop; 6731 } 6732 6733 /** 6734 * <p>Computes the coordinates of this view in its window. The argument 6735 * must be an array of two integers. After the method returns, the array 6736 * contains the x and y location in that order.</p> 6737 * 6738 * @param location an array of two integers in which to hold the coordinates 6739 */ 6740 public void getLocationInWindow(int[] location) { 6741 if (location == null || location.length < 2) { 6742 throw new IllegalArgumentException("location must be an array of " 6743 + "two integers"); 6744 } 6745 6746 location[0] = mLeft; 6747 location[1] = mTop; 6748 6749 ViewParent viewParent = mParent; 6750 while (viewParent instanceof View) { 6751 final View view = (View)viewParent; 6752 location[0] += view.mLeft - view.mScrollX; 6753 location[1] += view.mTop - view.mScrollY; 6754 viewParent = view.mParent; 6755 } 6756 6757 if (viewParent instanceof ViewRoot) { 6758 // *cough* 6759 final ViewRoot vr = (ViewRoot)viewParent; 6760 location[1] -= vr.mCurScrollY; 6761 } 6762 } 6763 6764 /** 6765 * {@hide} 6766 * @param id the id of the view to be found 6767 * @return the view of the specified id, null if cannot be found 6768 */ 6769 protected View findViewTraversal(int id) { 6770 if (id == mID) { 6771 return this; 6772 } 6773 return null; 6774 } 6775 6776 /** 6777 * {@hide} 6778 * @param tag the tag of the view to be found 6779 * @return the view of specified tag, null if cannot be found 6780 */ 6781 protected View findViewWithTagTraversal(Object tag) { 6782 if (tag != null && tag.equals(mTag)) { 6783 return this; 6784 } 6785 return null; 6786 } 6787 6788 /** 6789 * Look for a child view with the given id. If this view has the given 6790 * id, return this view. 6791 * 6792 * @param id The id to search for. 6793 * @return The view that has the given id in the hierarchy or null 6794 */ 6795 public final View findViewById(int id) { 6796 if (id < 0) { 6797 return null; 6798 } 6799 return findViewTraversal(id); 6800 } 6801 6802 /** 6803 * Look for a child view with the given tag. If this view has the given 6804 * tag, return this view. 6805 * 6806 * @param tag The tag to search for, using "tag.equals(getTag())". 6807 * @return The View that has the given tag in the hierarchy or null 6808 */ 6809 public final View findViewWithTag(Object tag) { 6810 if (tag == null) { 6811 return null; 6812 } 6813 return findViewWithTagTraversal(tag); 6814 } 6815 6816 /** 6817 * Sets the identifier for this view. The identifier does not have to be 6818 * unique in this view's hierarchy. The identifier should be a positive 6819 * number. 6820 * 6821 * @see #NO_ID 6822 * @see #getId 6823 * @see #findViewById 6824 * 6825 * @param id a number used to identify the view 6826 * 6827 * @attr ref android.R.styleable#View_id 6828 */ 6829 public void setId(int id) { 6830 mID = id; 6831 } 6832 6833 /** 6834 * {@hide} 6835 * 6836 * @param isRoot true if the view belongs to the root namespace, false 6837 * otherwise 6838 */ 6839 public void setIsRootNamespace(boolean isRoot) { 6840 if (isRoot) { 6841 mPrivateFlags |= IS_ROOT_NAMESPACE; 6842 } else { 6843 mPrivateFlags &= ~IS_ROOT_NAMESPACE; 6844 } 6845 } 6846 6847 /** 6848 * {@hide} 6849 * 6850 * @return true if the view belongs to the root namespace, false otherwise 6851 */ 6852 public boolean isRootNamespace() { 6853 return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0; 6854 } 6855 6856 /** 6857 * Returns this view's identifier. 6858 * 6859 * @return a positive integer used to identify the view or {@link #NO_ID} 6860 * if the view has no ID 6861 * 6862 * @see #setId 6863 * @see #findViewById 6864 * @attr ref android.R.styleable#View_id 6865 */ 6866 @ViewDebug.CapturedViewProperty 6867 public int getId() { 6868 return mID; 6869 } 6870 6871 /** 6872 * Returns this view's tag. 6873 * 6874 * @return the Object stored in this view as a tag 6875 */ 6876 @ViewDebug.ExportedProperty 6877 public Object getTag() { 6878 return mTag; 6879 } 6880 6881 /** 6882 * Sets the tag associated with this view. A tag can be used to mark 6883 * a view in its hierarchy and does not have to be unique within the 6884 * hierarchy. Tags can also be used to store data within a view without 6885 * resorting to another data structure. 6886 * 6887 * @param tag an Object to tag the view with 6888 */ 6889 public void setTag(final Object tag) { 6890 mTag = tag; 6891 } 6892 6893 /** 6894 * Prints information about this view in the log output, with the tag 6895 * {@link #VIEW_LOG_TAG}. 6896 * 6897 * @hide 6898 */ 6899 public void debug() { 6900 debug(0); 6901 } 6902 6903 /** 6904 * Prints information about this view in the log output, with the tag 6905 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 6906 * indentation defined by the <code>depth</code>. 6907 * 6908 * @param depth the indentation level 6909 * 6910 * @hide 6911 */ 6912 protected void debug(int depth) { 6913 String output = debugIndent(depth - 1); 6914 6915 output += "+ " + this; 6916 int id = getId(); 6917 if (id != -1) { 6918 output += " (id=" + id + ")"; 6919 } 6920 Object tag = getTag(); 6921 if (tag != null) { 6922 output += " (tag=" + tag + ")"; 6923 } 6924 Log.d(VIEW_LOG_TAG, output); 6925 6926 if ((mPrivateFlags & FOCUSED) != 0) { 6927 output = debugIndent(depth) + " FOCUSED"; 6928 Log.d(VIEW_LOG_TAG, output); 6929 } 6930 6931 output = debugIndent(depth); 6932 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 6933 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 6934 + "} "; 6935 Log.d(VIEW_LOG_TAG, output); 6936 6937 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 6938 || mPaddingBottom != 0) { 6939 output = debugIndent(depth); 6940 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 6941 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 6942 Log.d(VIEW_LOG_TAG, output); 6943 } 6944 6945 output = debugIndent(depth); 6946 output += "mMeasureWidth=" + mMeasuredWidth + 6947 " mMeasureHeight=" + mMeasuredHeight; 6948 Log.d(VIEW_LOG_TAG, output); 6949 6950 output = debugIndent(depth); 6951 if (mLayoutParams == null) { 6952 output += "BAD! no layout params"; 6953 } else { 6954 output = mLayoutParams.debug(output); 6955 } 6956 Log.d(VIEW_LOG_TAG, output); 6957 6958 output = debugIndent(depth); 6959 output += "flags={"; 6960 output += View.printFlags(mViewFlags); 6961 output += "}"; 6962 Log.d(VIEW_LOG_TAG, output); 6963 6964 output = debugIndent(depth); 6965 output += "privateFlags={"; 6966 output += View.printPrivateFlags(mPrivateFlags); 6967 output += "}"; 6968 Log.d(VIEW_LOG_TAG, output); 6969 } 6970 6971 /** 6972 * Creates an string of whitespaces used for indentation. 6973 * 6974 * @param depth the indentation level 6975 * @return a String containing (depth * 2 + 3) * 2 white spaces 6976 * 6977 * @hide 6978 */ 6979 protected static String debugIndent(int depth) { 6980 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 6981 for (int i = 0; i < (depth * 2) + 3; i++) { 6982 spaces.append(' ').append(' '); 6983 } 6984 return spaces.toString(); 6985 } 6986 6987 /** 6988 * <p>Return the offset of the widget's text baseline from the widget's top 6989 * boundary. If this widget does not support baseline alignment, this 6990 * method returns -1. </p> 6991 * 6992 * @return the offset of the baseline within the widget's bounds or -1 6993 * if baseline alignment is not supported 6994 */ 6995 @ViewDebug.ExportedProperty 6996 public int getBaseline() { 6997 return -1; 6998 } 6999 7000 /** 7001 * Call this when something has changed which has invalidated the 7002 * layout of this view. This will schedule a layout pass of the view 7003 * tree. 7004 */ 7005 public void requestLayout() { 7006 if (ViewDebug.TRACE_HIERARCHY) { 7007 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT); 7008 } 7009 7010 mPrivateFlags |= FORCE_LAYOUT; 7011 7012 if (mParent != null && !mParent.isLayoutRequested()) { 7013 mParent.requestLayout(); 7014 } 7015 } 7016 7017 /** 7018 * Forces this view to be laid out during the next layout pass. 7019 * This method does not call requestLayout() or forceLayout() 7020 * on the parent. 7021 */ 7022 public void forceLayout() { 7023 mPrivateFlags |= FORCE_LAYOUT; 7024 } 7025 7026 /** 7027 * <p> 7028 * This is called to find out how big a view should be. The parent 7029 * supplies constraint information in the width and height parameters. 7030 * </p> 7031 * 7032 * <p> 7033 * The actual mesurement work of a view is performed in 7034 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 7035 * {@link #onMeasure(int, int)} can and must be overriden by subclasses. 7036 * </p> 7037 * 7038 * 7039 * @param widthMeasureSpec Horizontal space requirements as imposed by the 7040 * parent 7041 * @param heightMeasureSpec Vertical space requirements as imposed by the 7042 * parent 7043 * 7044 * @see #onMeasure(int, int) 7045 */ 7046 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 7047 if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || 7048 widthMeasureSpec != mOldWidthMeasureSpec || 7049 heightMeasureSpec != mOldHeightMeasureSpec) { 7050 7051 // first clears the measured dimension flag 7052 mPrivateFlags &= ~MEASURED_DIMENSION_SET; 7053 7054 if (ViewDebug.TRACE_HIERARCHY) { 7055 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE); 7056 } 7057 7058 // measure ourselves, this should set the measured dimension flag back 7059 onMeasure(widthMeasureSpec, heightMeasureSpec); 7060 7061 // flag not set, setMeasuredDimension() was not invoked, we raise 7062 // an exception to warn the developer 7063 if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) { 7064 throw new IllegalStateException("onMeasure() did not set the" 7065 + " measured dimension by calling" 7066 + " setMeasuredDimension()"); 7067 } 7068 7069 mPrivateFlags |= LAYOUT_REQUIRED; 7070 } 7071 7072 mOldWidthMeasureSpec = widthMeasureSpec; 7073 mOldHeightMeasureSpec = heightMeasureSpec; 7074 } 7075 7076 /** 7077 * <p> 7078 * Measure the view and its content to determine the measured width and the 7079 * measured height. This method is invoked by {@link #measure(int, int)} and 7080 * should be overriden by subclasses to provide accurate and efficient 7081 * measurement of their contents. 7082 * </p> 7083 * 7084 * <p> 7085 * <strong>CONTRACT:</strong> When overriding this method, you 7086 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 7087 * measured width and height of this view. Failure to do so will trigger an 7088 * <code>IllegalStateException</code>, thrown by 7089 * {@link #measure(int, int)}. Calling the superclass' 7090 * {@link #onMeasure(int, int)} is a valid use. 7091 * </p> 7092 * 7093 * <p> 7094 * The base class implementation of measure defaults to the background size, 7095 * unless a larger size is allowed by the MeasureSpec. Subclasses should 7096 * override {@link #onMeasure(int, int)} to provide better measurements of 7097 * their content. 7098 * </p> 7099 * 7100 * <p> 7101 * If this method is overridden, it is the subclass's responsibility to make 7102 * sure the measured height and width are at least the view's minimum height 7103 * and width ({@link #getSuggestedMinimumHeight()} and 7104 * {@link #getSuggestedMinimumWidth()}). 7105 * </p> 7106 * 7107 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 7108 * The requirements are encoded with 7109 * {@link android.view.View.MeasureSpec}. 7110 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 7111 * The requirements are encoded with 7112 * {@link android.view.View.MeasureSpec}. 7113 * 7114 * @see #getMeasuredWidth() 7115 * @see #getMeasuredHeight() 7116 * @see #setMeasuredDimension(int, int) 7117 * @see #getSuggestedMinimumHeight() 7118 * @see #getSuggestedMinimumWidth() 7119 * @see android.view.View.MeasureSpec#getMode(int) 7120 * @see android.view.View.MeasureSpec#getSize(int) 7121 */ 7122 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 7123 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 7124 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 7125 } 7126 7127 /** 7128 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the 7129 * measured width and measured height. Failing to do so will trigger an 7130 * exception at measurement time.</p> 7131 * 7132 * @param measuredWidth the measured width of this view 7133 * @param measuredHeight the measured height of this view 7134 */ 7135 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 7136 mMeasuredWidth = measuredWidth; 7137 mMeasuredHeight = measuredHeight; 7138 7139 mPrivateFlags |= MEASURED_DIMENSION_SET; 7140 } 7141 7142 /** 7143 * Utility to reconcile a desired size with constraints imposed by a MeasureSpec. 7144 * Will take the desired size, unless a different size is imposed by the constraints. 7145 * 7146 * @param size How big the view wants to be 7147 * @param measureSpec Constraints imposed by the parent 7148 * @return The size this view should be. 7149 */ 7150 public static int resolveSize(int size, int measureSpec) { 7151 int result = size; 7152 int specMode = MeasureSpec.getMode(measureSpec); 7153 int specSize = MeasureSpec.getSize(measureSpec); 7154 switch (specMode) { 7155 case MeasureSpec.UNSPECIFIED: 7156 result = size; 7157 break; 7158 case MeasureSpec.AT_MOST: 7159 result = Math.min(size, specSize); 7160 break; 7161 case MeasureSpec.EXACTLY: 7162 result = specSize; 7163 break; 7164 } 7165 return result; 7166 } 7167 7168 /** 7169 * Utility to return a default size. Uses the supplied size if the 7170 * MeasureSpec imposed no contraints. Will get larger if allowed 7171 * by the MeasureSpec. 7172 * 7173 * @param size Default size for this view 7174 * @param measureSpec Constraints imposed by the parent 7175 * @return The size this view should be. 7176 */ 7177 public static int getDefaultSize(int size, int measureSpec) { 7178 int result = size; 7179 int specMode = MeasureSpec.getMode(measureSpec); 7180 int specSize = MeasureSpec.getSize(measureSpec); 7181 7182 switch (specMode) { 7183 case MeasureSpec.UNSPECIFIED: 7184 result = size; 7185 break; 7186 case MeasureSpec.AT_MOST: 7187 case MeasureSpec.EXACTLY: 7188 result = specSize; 7189 break; 7190 } 7191 return result; 7192 } 7193 7194 /** 7195 * Returns the suggested minimum height that the view should use. This 7196 * returns the maximum of the view's minimum height 7197 * and the background's minimum height 7198 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 7199 * <p> 7200 * When being used in {@link #onMeasure(int, int)}, the caller should still 7201 * ensure the returned height is within the requirements of the parent. 7202 * 7203 * @return The suggested minimum height of the view. 7204 */ 7205 protected int getSuggestedMinimumHeight() { 7206 int suggestedMinHeight = mMinHeight; 7207 7208 if (mBGDrawable != null) { 7209 final int bgMinHeight = mBGDrawable.getMinimumHeight(); 7210 if (suggestedMinHeight < bgMinHeight) { 7211 suggestedMinHeight = bgMinHeight; 7212 } 7213 } 7214 7215 return suggestedMinHeight; 7216 } 7217 7218 /** 7219 * Returns the suggested minimum width that the view should use. This 7220 * returns the maximum of the view's minimum width) 7221 * and the background's minimum width 7222 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 7223 * <p> 7224 * When being used in {@link #onMeasure(int, int)}, the caller should still 7225 * ensure the returned width is within the requirements of the parent. 7226 * 7227 * @return The suggested minimum width of the view. 7228 */ 7229 protected int getSuggestedMinimumWidth() { 7230 int suggestedMinWidth = mMinWidth; 7231 7232 if (mBGDrawable != null) { 7233 final int bgMinWidth = mBGDrawable.getMinimumWidth(); 7234 if (suggestedMinWidth < bgMinWidth) { 7235 suggestedMinWidth = bgMinWidth; 7236 } 7237 } 7238 7239 return suggestedMinWidth; 7240 } 7241 7242 /** 7243 * Sets the minimum height of the view. It is not guaranteed the view will 7244 * be able to achieve this minimum height (for example, if its parent layout 7245 * constrains it with less available height). 7246 * 7247 * @param minHeight The minimum height the view will try to be. 7248 */ 7249 public void setMinimumHeight(int minHeight) { 7250 mMinHeight = minHeight; 7251 } 7252 7253 /** 7254 * Sets the minimum width of the view. It is not guaranteed the view will 7255 * be able to achieve this minimum width (for example, if its parent layout 7256 * constrains it with less available width). 7257 * 7258 * @param minWidth The minimum width the view will try to be. 7259 */ 7260 public void setMinimumWidth(int minWidth) { 7261 mMinWidth = minWidth; 7262 } 7263 7264 /** 7265 * Get the animation currently associated with this view. 7266 * 7267 * @return The animation that is currently playing or 7268 * scheduled to play for this view. 7269 */ 7270 public Animation getAnimation() { 7271 return mCurrentAnimation; 7272 } 7273 7274 /** 7275 * Start the specified animation now. 7276 * 7277 * @param animation the animation to start now 7278 */ 7279 public void startAnimation(Animation animation) { 7280 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 7281 setAnimation(animation); 7282 invalidate(); 7283 } 7284 7285 /** 7286 * Cancels any animations for this view. 7287 */ 7288 public void clearAnimation() { 7289 mCurrentAnimation = null; 7290 } 7291 7292 /** 7293 * Sets the next animation to play for this view. 7294 * If you want the animation to play immediately, use 7295 * startAnimation. This method provides allows fine-grained 7296 * control over the start time and invalidation, but you 7297 * must make sure that 1) the animation has a start time set, and 7298 * 2) the view will be invalidated when the animation is supposed to 7299 * start. 7300 * 7301 * @param animation The next animation, or null. 7302 */ 7303 public void setAnimation(Animation animation) { 7304 mCurrentAnimation = animation; 7305 if (animation != null) { 7306 animation.reset(); 7307 } 7308 } 7309 7310 /** 7311 * Invoked by a parent ViewGroup to notify the start of the animation 7312 * currently associated with this view. If you override this method, 7313 * always call super.onAnimationStart(); 7314 * 7315 * @see #setAnimation(android.view.animation.Animation) 7316 * @see #getAnimation() 7317 */ 7318 protected void onAnimationStart() { 7319 mPrivateFlags |= ANIMATION_STARTED; 7320 } 7321 7322 /** 7323 * Invoked by a parent ViewGroup to notify the end of the animation 7324 * currently associated with this view. If you override this method, 7325 * always call super.onAnimationEnd(); 7326 * 7327 * @see #setAnimation(android.view.animation.Animation) 7328 * @see #getAnimation() 7329 */ 7330 protected void onAnimationEnd() { 7331 mPrivateFlags &= ~ANIMATION_STARTED; 7332 } 7333 7334 /** 7335 * Invoked if there is a Transform that involves alpha. Subclass that can 7336 * draw themselves with the specified alpha should return true, and then 7337 * respect that alpha when their onDraw() is called. If this returns false 7338 * then the view may be redirected to draw into an offscreen buffer to 7339 * fulfill the request, which will look fine, but may be slower than if the 7340 * subclass handles it internally. The default implementation returns false. 7341 * 7342 * @param alpha The alpha (0..255) to apply to the view's drawing 7343 * @return true if the view can draw with the specified alpha. 7344 */ 7345 protected boolean onSetAlpha(int alpha) { 7346 return false; 7347 } 7348 7349 /** 7350 * This is used by the RootView to perform an optimization when 7351 * the view hierarchy contains one or several SurfaceView. 7352 * SurfaceView is always considered transparent, but its children are not, 7353 * therefore all View objects remove themselves from the global transparent 7354 * region (passed as a parameter to this function). 7355 * 7356 * @param region The transparent region for this ViewRoot (window). 7357 * 7358 * @return Returns true if the effective visibility of the view at this 7359 * point is opaque, regardless of the transparent region; returns false 7360 * if it is possible for underlying windows to be seen behind the view. 7361 * 7362 * {@hide} 7363 */ 7364 public boolean gatherTransparentRegion(Region region) { 7365 final AttachInfo attachInfo = mAttachInfo; 7366 if (region != null && attachInfo != null) { 7367 final int pflags = mPrivateFlags; 7368 if ((pflags & SKIP_DRAW) == 0) { 7369 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 7370 // remove it from the transparent region. 7371 final int[] location = attachInfo.mTransparentLocation; 7372 getLocationInWindow(location); 7373 region.op(location[0], location[1], location[0] + mRight - mLeft, 7374 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 7375 } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) { 7376 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable 7377 // exists, so we remove the background drawable's non-transparent 7378 // parts from this transparent region. 7379 applyDrawableToTransparentRegion(mBGDrawable, region); 7380 } 7381 } 7382 return true; 7383 } 7384 7385 /** 7386 * Play a sound effect for this view. 7387 * 7388 * <p>The framework will play sound effects for some built in actions, such as 7389 * clicking, but you may wish to play these effects in your widget, 7390 * for instance, for internal navigation. 7391 * 7392 * <p>The sound effect will only be played if sound effects are enabled by the user, and 7393 * {@link #isSoundEffectsEnabled()} is true. 7394 * 7395 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 7396 */ 7397 public void playSoundEffect(int soundConstant) { 7398 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 7399 return; 7400 } 7401 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 7402 } 7403 7404 /** 7405 * Provide haptic feedback to the user for this view. 7406 * 7407 * <p>The framework will provide haptic feedback for some built in actions, 7408 * such as long presses, but you may wish to provide feedback for your 7409 * own widget. 7410 * 7411 * <p>The feedback will only be performed if 7412 * {@link #isHapticFeedbackEnabled()} is true. 7413 * 7414 * @param feedbackConstant One of the constants defined in 7415 * {@link HapticFeedbackConstants} 7416 */ 7417 public boolean performHapticFeedback(int feedbackConstant) { 7418 return performHapticFeedback(feedbackConstant, 0); 7419 } 7420 7421 /** 7422 * Like {@link #performHapticFeedback(int)}, with additional options. 7423 * 7424 * @param feedbackConstant One of the constants defined in 7425 * {@link HapticFeedbackConstants} 7426 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 7427 */ 7428 public boolean performHapticFeedback(int feedbackConstant, int flags) { 7429 if (mAttachInfo == null) { 7430 return false; 7431 } 7432 if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 7433 && !isHapticFeedbackEnabled()) { 7434 return false; 7435 } 7436 return mAttachInfo.mRootCallbacks.performHapticFeedback( 7437 feedbackConstant, 7438 (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 7439 } 7440 7441 /** 7442 * Given a Drawable whose bounds have been set to draw into this view, 7443 * update a Region being computed for {@link #gatherTransparentRegion} so 7444 * that any non-transparent parts of the Drawable are removed from the 7445 * given transparent region. 7446 * 7447 * @param dr The Drawable whose transparency is to be applied to the region. 7448 * @param region A Region holding the current transparency information, 7449 * where any parts of the region that are set are considered to be 7450 * transparent. On return, this region will be modified to have the 7451 * transparency information reduced by the corresponding parts of the 7452 * Drawable that are not transparent. 7453 * {@hide} 7454 */ 7455 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 7456 if (DBG) { 7457 Log.i("View", "Getting transparent region for: " + this); 7458 } 7459 final Region r = dr.getTransparentRegion(); 7460 final Rect db = dr.getBounds(); 7461 final AttachInfo attachInfo = mAttachInfo; 7462 if (r != null && attachInfo != null) { 7463 final int w = getRight()-getLeft(); 7464 final int h = getBottom()-getTop(); 7465 if (db.left > 0) { 7466 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 7467 r.op(0, 0, db.left, h, Region.Op.UNION); 7468 } 7469 if (db.right < w) { 7470 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 7471 r.op(db.right, 0, w, h, Region.Op.UNION); 7472 } 7473 if (db.top > 0) { 7474 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 7475 r.op(0, 0, w, db.top, Region.Op.UNION); 7476 } 7477 if (db.bottom < h) { 7478 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 7479 r.op(0, db.bottom, w, h, Region.Op.UNION); 7480 } 7481 final int[] location = attachInfo.mTransparentLocation; 7482 getLocationInWindow(location); 7483 r.translate(location[0], location[1]); 7484 region.op(r, Region.Op.INTERSECT); 7485 } else { 7486 region.op(db, Region.Op.DIFFERENCE); 7487 } 7488 } 7489 7490 private void postCheckForLongClick() { 7491 mHasPerformedLongPress = false; 7492 7493 if (mPendingCheckForLongPress == null) { 7494 mPendingCheckForLongPress = new CheckForLongPress(); 7495 } 7496 mPendingCheckForLongPress.rememberWindowAttachCount(); 7497 postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); 7498 } 7499 7500 private static int[] stateSetUnion(final int[] stateSet1, 7501 final int[] stateSet2) { 7502 final int stateSet1Length = stateSet1.length; 7503 final int stateSet2Length = stateSet2.length; 7504 final int[] newSet = new int[stateSet1Length + stateSet2Length]; 7505 int k = 0; 7506 int i = 0; 7507 int j = 0; 7508 // This is a merge of the two input state sets and assumes that the 7509 // input sets are sorted by the order imposed by ViewDrawableStates. 7510 for (int viewState : R.styleable.ViewDrawableStates) { 7511 if (i < stateSet1Length && stateSet1[i] == viewState) { 7512 newSet[k++] = viewState; 7513 i++; 7514 } else if (j < stateSet2Length && stateSet2[j] == viewState) { 7515 newSet[k++] = viewState; 7516 j++; 7517 } 7518 if (k > 1) { 7519 assert(newSet[k - 1] > newSet[k - 2]); 7520 } 7521 } 7522 return newSet; 7523 } 7524 7525 /** 7526 * Inflate a view from an XML resource. This convenience method wraps the {@link 7527 * LayoutInflater} class, which provides a full range of options for view inflation. 7528 * 7529 * @param context The Context object for your activity or application. 7530 * @param resource The resource ID to inflate 7531 * @param root A view group that will be the parent. Used to properly inflate the 7532 * layout_* parameters. 7533 * @see LayoutInflater 7534 */ 7535 public static View inflate(Context context, int resource, ViewGroup root) { 7536 LayoutInflater factory = LayoutInflater.from(context); 7537 return factory.inflate(resource, root); 7538 } 7539 7540 /** 7541 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 7542 * Each MeasureSpec represents a requirement for either the width or the height. 7543 * A MeasureSpec is comprised of a size and a mode. There are three possible 7544 * modes: 7545 * <dl> 7546 * <dt>UNSPECIFIED</dt> 7547 * <dd> 7548 * The parent has not imposed any constraint on the child. It can be whatever size 7549 * it wants. 7550 * </dd> 7551 * 7552 * <dt>EXACTLY</dt> 7553 * <dd> 7554 * The parent has determined an exact size for the child. The child is going to be 7555 * given those bounds regardless of how big it wants to be. 7556 * </dd> 7557 * 7558 * <dt>AT_MOST</dt> 7559 * <dd> 7560 * The child can be as large as it wants up to the specified size. 7561 * </dd> 7562 * </dl> 7563 * 7564 * MeasureSpecs are implemented as ints to reduce object allocation. This class 7565 * is provided to pack and unpack the <size, mode> tuple into the int. 7566 */ 7567 public static class MeasureSpec { 7568 private static final int MODE_SHIFT = 30; 7569 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 7570 7571 /** 7572 * Measure specification mode: The parent has not imposed any constraint 7573 * on the child. It can be whatever size it wants. 7574 */ 7575 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 7576 7577 /** 7578 * Measure specification mode: The parent has determined an exact size 7579 * for the child. The child is going to be given those bounds regardless 7580 * of how big it wants to be. 7581 */ 7582 public static final int EXACTLY = 1 << MODE_SHIFT; 7583 7584 /** 7585 * Measure specification mode: The child can be as large as it wants up 7586 * to the specified size. 7587 */ 7588 public static final int AT_MOST = 2 << MODE_SHIFT; 7589 7590 /** 7591 * Creates a measure specification based on the supplied size and mode. 7592 * 7593 * The mode must always be one of the following: 7594 * <ul> 7595 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 7596 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 7597 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 7598 * </ul> 7599 * 7600 * @param size the size of the measure specification 7601 * @param mode the mode of the measure specification 7602 * @return the measure specification based on size and mode 7603 */ 7604 public static int makeMeasureSpec(int size, int mode) { 7605 return size + mode; 7606 } 7607 7608 /** 7609 * Extracts the mode from the supplied measure specification. 7610 * 7611 * @param measureSpec the measure specification to extract the mode from 7612 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 7613 * {@link android.view.View.MeasureSpec#AT_MOST} or 7614 * {@link android.view.View.MeasureSpec#EXACTLY} 7615 */ 7616 public static int getMode(int measureSpec) { 7617 return (measureSpec & MODE_MASK); 7618 } 7619 7620 /** 7621 * Extracts the size from the supplied measure specification. 7622 * 7623 * @param measureSpec the measure specification to extract the size from 7624 * @return the size in pixels defined in the supplied measure specification 7625 */ 7626 public static int getSize(int measureSpec) { 7627 return (measureSpec & ~MODE_MASK); 7628 } 7629 7630 /** 7631 * Returns a String representation of the specified measure 7632 * specification. 7633 * 7634 * @param measureSpec the measure specification to convert to a String 7635 * @return a String with the following format: "MeasureSpec: MODE SIZE" 7636 */ 7637 public static String toString(int measureSpec) { 7638 int mode = getMode(measureSpec); 7639 int size = getSize(measureSpec); 7640 7641 StringBuilder sb = new StringBuilder("MeasureSpec: "); 7642 7643 if (mode == UNSPECIFIED) 7644 sb.append("UNSPECIFIED "); 7645 else if (mode == EXACTLY) 7646 sb.append("EXACTLY "); 7647 else if (mode == AT_MOST) 7648 sb.append("AT_MOST "); 7649 else 7650 sb.append(mode).append(" "); 7651 7652 sb.append(size); 7653 return sb.toString(); 7654 } 7655 } 7656 7657 class CheckForLongPress implements Runnable { 7658 7659 private int mOriginalWindowAttachCount; 7660 7661 public void run() { 7662 if (isPressed() && (mParent != null) 7663 && mOriginalWindowAttachCount == mWindowAttachCount) { 7664 if (performLongClick()) { 7665 mHasPerformedLongPress = true; 7666 } 7667 } 7668 } 7669 7670 public void rememberWindowAttachCount() { 7671 mOriginalWindowAttachCount = mWindowAttachCount; 7672 } 7673 } 7674 7675 /** 7676 * Interface definition for a callback to be invoked when a key event is 7677 * dispatched to this view. The callback will be invoked before the key 7678 * event is given to the view. 7679 */ 7680 public interface OnKeyListener { 7681 /** 7682 * Called when a key is dispatched to a view. This allows listeners to 7683 * get a chance to respond before the target view. 7684 * 7685 * @param v The view the key has been dispatched to. 7686 * @param keyCode The code for the physical key that was pressed 7687 * @param event The KeyEvent object containing full information about 7688 * the event. 7689 * @return True if the listener has consumed the event, false otherwise. 7690 */ 7691 boolean onKey(View v, int keyCode, KeyEvent event); 7692 } 7693 7694 /** 7695 * Interface definition for a callback to be invoked when a touch event is 7696 * dispatched to this view. The callback will be invoked before the touch 7697 * event is given to the view. 7698 */ 7699 public interface OnTouchListener { 7700 /** 7701 * Called when a touch event is dispatched to a view. This allows listeners to 7702 * get a chance to respond before the target view. 7703 * 7704 * @param v The view the touch event has been dispatched to. 7705 * @param event The MotionEvent object containing full information about 7706 * the event. 7707 * @return True if the listener has consumed the event, false otherwise. 7708 */ 7709 boolean onTouch(View v, MotionEvent event); 7710 } 7711 7712 /** 7713 * Interface definition for a callback to be invoked when a view has been clicked and held. 7714 */ 7715 public interface OnLongClickListener { 7716 /** 7717 * Called when a view has been clicked and held. 7718 * 7719 * @param v The view that was clicked and held. 7720 * 7721 * return True if the callback consumed the long click, false otherwise 7722 */ 7723 boolean onLongClick(View v); 7724 } 7725 7726 /** 7727 * Interface definition for a callback to be invoked when the focus state of 7728 * a view changed. 7729 */ 7730 public interface OnFocusChangeListener { 7731 /** 7732 * Called when the focus state of a view has changed. 7733 * 7734 * @param v The view whose state has changed. 7735 * @param hasFocus The new focus state of v. 7736 */ 7737 void onFocusChange(View v, boolean hasFocus); 7738 } 7739 7740 /** 7741 * Interface definition for a callback to be invoked when a view is clicked. 7742 */ 7743 public interface OnClickListener { 7744 /** 7745 * Called when a view has been clicked. 7746 * 7747 * @param v The view that was clicked. 7748 */ 7749 void onClick(View v); 7750 } 7751 7752 /** 7753 * Interface definition for a callback to be invoked when the context menu 7754 * for this view is being built. 7755 */ 7756 public interface OnCreateContextMenuListener { 7757 /** 7758 * Called when the context menu for this view is being built. It is not 7759 * safe to hold onto the menu after this method returns. 7760 * 7761 * @param menu The context menu that is being built 7762 * @param v The view for which the context menu is being built 7763 * @param menuInfo Extra information about the item for which the 7764 * context menu should be shown. This information will vary 7765 * depending on the class of v. 7766 */ 7767 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 7768 } 7769 7770 private final class UnsetPressedState implements Runnable { 7771 public void run() { 7772 setPressed(false); 7773 } 7774 } 7775 7776 /** 7777 * Base class for derived classes that want to save and restore their own 7778 * state in {@link android.view.View#onSaveInstanceState()}. 7779 */ 7780 public static class BaseSavedState extends AbsSavedState { 7781 /** 7782 * Constructor used when reading from a parcel. Reads the state of the superclass. 7783 * 7784 * @param source 7785 */ 7786 public BaseSavedState(Parcel source) { 7787 super(source); 7788 } 7789 7790 /** 7791 * Constructor called by derived classes when creating their SavedState objects 7792 * 7793 * @param superState The state of the superclass of this view 7794 */ 7795 public BaseSavedState(Parcelable superState) { 7796 super(superState); 7797 } 7798 7799 public static final Parcelable.Creator<BaseSavedState> CREATOR = 7800 new Parcelable.Creator<BaseSavedState>() { 7801 public BaseSavedState createFromParcel(Parcel in) { 7802 return new BaseSavedState(in); 7803 } 7804 7805 public BaseSavedState[] newArray(int size) { 7806 return new BaseSavedState[size]; 7807 } 7808 }; 7809 } 7810 7811 /** 7812 * A set of information given to a view when it is attached to its parent 7813 * window. 7814 */ 7815 static class AttachInfo { 7816 7817 interface Callbacks { 7818 void playSoundEffect(int effectId); 7819 boolean performHapticFeedback(int effectId, boolean always); 7820 } 7821 7822 /** 7823 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 7824 * to a Handler. This class contains the target (View) to invalidate and 7825 * the coordinates of the dirty rectangle. 7826 * 7827 * For performance purposes, this class also implements a pool of up to 7828 * POOL_LIMIT objects that get reused. This reduces memory allocations 7829 * whenever possible. 7830 * 7831 * The pool is implemented as a linked list of InvalidateInfo object with 7832 * the root pointing to the next available InvalidateInfo. If the root 7833 * is null (i.e. when all instances from the pool have been acquired), 7834 * then a new InvalidateInfo is created and returned to the caller. 7835 * 7836 * An InvalidateInfo is sent back to the pool by calling its release() 7837 * method. If the pool is full the object is simply discarded. 7838 * 7839 * This implementation follows the object pool pattern used in the 7840 * MotionEvent class. 7841 */ 7842 static class InvalidateInfo { 7843 private static final int POOL_LIMIT = 10; 7844 private static final Object sLock = new Object(); 7845 7846 private static int sAcquiredCount = 0; 7847 private static InvalidateInfo sRoot; 7848 7849 private InvalidateInfo next; 7850 7851 View target; 7852 7853 int left; 7854 int top; 7855 int right; 7856 int bottom; 7857 7858 static InvalidateInfo acquire() { 7859 synchronized (sLock) { 7860 if (sRoot == null) { 7861 return new InvalidateInfo(); 7862 } 7863 7864 InvalidateInfo info = sRoot; 7865 sRoot = info.next; 7866 sAcquiredCount--; 7867 7868 return info; 7869 } 7870 } 7871 7872 void release() { 7873 synchronized (sLock) { 7874 if (sAcquiredCount < POOL_LIMIT) { 7875 sAcquiredCount++; 7876 next = sRoot; 7877 sRoot = this; 7878 } 7879 } 7880 } 7881 } 7882 7883 final IWindowSession mSession; 7884 7885 final IWindow mWindow; 7886 7887 final IBinder mWindowToken; 7888 7889 final Callbacks mRootCallbacks; 7890 7891 /** 7892 * The top view of the hierarchy. 7893 */ 7894 View mRootView; 7895 7896 IBinder mPanelParentWindowToken; 7897 Surface mSurface; 7898 7899 /** 7900 * Left position of this view's window 7901 */ 7902 int mWindowLeft; 7903 7904 /** 7905 * Top position of this view's window 7906 */ 7907 int mWindowTop; 7908 7909 /** 7910 * For windows that are full-screen but using insets to layout inside 7911 * of the screen decorations, these are the current insets for the 7912 * content of the window. 7913 */ 7914 final Rect mContentInsets = new Rect(); 7915 7916 /** 7917 * For windows that are full-screen but using insets to layout inside 7918 * of the screen decorations, these are the current insets for the 7919 * actual visible parts of the window. 7920 */ 7921 final Rect mVisibleInsets = new Rect(); 7922 7923 /** 7924 * The internal insets given by this window. This value is 7925 * supplied by the client (through 7926 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 7927 * be given to the window manager when changed to be used in laying 7928 * out windows behind it. 7929 */ 7930 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 7931 = new ViewTreeObserver.InternalInsetsInfo(); 7932 7933 /** 7934 * All views in the window's hierarchy that serve as scroll containers, 7935 * used to determine if the window can be resized or must be panned 7936 * to adjust for a soft input area. 7937 */ 7938 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 7939 7940 /** 7941 * Indicates whether the view's window currently has the focus. 7942 */ 7943 boolean mHasWindowFocus; 7944 7945 /** 7946 * The current visibility of the window. 7947 */ 7948 int mWindowVisibility; 7949 7950 /** 7951 * Indicates the time at which drawing started to occur. 7952 */ 7953 long mDrawingTime; 7954 7955 /** 7956 * Indicates whether the view's window is currently in touch mode. 7957 */ 7958 boolean mInTouchMode; 7959 7960 /** 7961 * Indicates that ViewRoot should trigger a global layout change 7962 * the next time it performs a traversal 7963 */ 7964 boolean mRecomputeGlobalAttributes; 7965 7966 /** 7967 * Set to true when attributes (like mKeepScreenOn) need to be 7968 * recomputed. 7969 */ 7970 boolean mAttributesChanged; 7971 7972 /** 7973 * Set during a traveral if any views want to keep the screen on. 7974 */ 7975 boolean mKeepScreenOn; 7976 7977 /** 7978 * Set if the visibility of any views has changed. 7979 */ 7980 boolean mViewVisibilityChanged; 7981 7982 /** 7983 * Set to true if a view has been scrolled. 7984 */ 7985 boolean mViewScrollChanged; 7986 7987 /** 7988 * Global to the view hierarchy used as a temporary for dealing with 7989 * x/y points in the transparent region computations. 7990 */ 7991 final int[] mTransparentLocation = new int[2]; 7992 7993 /** 7994 * Global to the view hierarchy used as a temporary for dealing with 7995 * x/y points in the ViewGroup.invalidateChild implementation. 7996 */ 7997 final int[] mInvalidateChildLocation = new int[2]; 7998 7999 /** 8000 * The view tree observer used to dispatch global events like 8001 * layout, pre-draw, touch mode change, etc. 8002 */ 8003 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 8004 8005 /** 8006 * A Canvas used by the view hierarchy to perform bitmap caching. 8007 */ 8008 Canvas mCanvas; 8009 8010 /** 8011 * A Handler supplied by a view's {@link android.view.ViewRoot}. This 8012 * handler can be used to pump events in the UI events queue. 8013 */ 8014 final Handler mHandler; 8015 8016 /** 8017 * Identifier for messages requesting the view to be invalidated. 8018 * Such messages should be sent to {@link #mHandler}. 8019 */ 8020 static final int INVALIDATE_MSG = 0x1; 8021 8022 /** 8023 * Identifier for messages requesting the view to invalidate a region. 8024 * Such messages should be sent to {@link #mHandler}. 8025 */ 8026 static final int INVALIDATE_RECT_MSG = 0x2; 8027 8028 /** 8029 * Temporary for use in computing invalidate rectangles while 8030 * calling up the hierarchy. 8031 */ 8032 final Rect mTmpInvalRect = new Rect(); 8033 8034 /** 8035 * Creates a new set of attachment information with the specified 8036 * events handler and thread. 8037 * 8038 * @param handler the events handler the view must use 8039 */ 8040 AttachInfo(IWindowSession session, IWindow window, 8041 Handler handler, Callbacks effectPlayer) { 8042 mSession = session; 8043 mWindow = window; 8044 mWindowToken = window.asBinder(); 8045 mHandler = handler; 8046 mRootCallbacks = effectPlayer; 8047 } 8048 } 8049 8050 /** 8051 * <p>ScrollabilityCache holds various fields used by a View when scrolling 8052 * is supported. This avoids keeping too many unused fields in most 8053 * instances of View.</p> 8054 */ 8055 private static class ScrollabilityCache { 8056 public int fadingEdgeLength; 8057 8058 public int scrollBarSize; 8059 public ScrollBarDrawable scrollBar; 8060 8061 public final Paint paint; 8062 public final Matrix matrix; 8063 public Shader shader; 8064 8065 private int mLastColor; 8066 8067 public ScrollabilityCache(ViewConfiguration configuration) { 8068 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 8069 scrollBarSize = configuration.getScaledScrollBarSize(); 8070 8071 paint = new Paint(); 8072 matrix = new Matrix(); 8073 // use use a height of 1, and then wack the matrix each time we 8074 // actually use it. 8075 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 8076 8077 paint.setShader(shader); 8078 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 8079 } 8080 8081 public void setFadeColor(int color) { 8082 if (color != 0 && color != mLastColor) { 8083 mLastColor = color; 8084 color |= 0xFF000000; 8085 8086 shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP); 8087 8088 paint.setShader(shader); 8089 // Restore the default transfer mode (src_over) 8090 paint.setXfermode(null); 8091 } 8092 } 8093 } 8094} 8095