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