View.java revision aa1a94daaa59e98303fdeb1c3066b60a58755dff
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.view; 18 19import android.animation.AnimatorInflater; 20import android.animation.StateListAnimator; 21import android.annotation.CallSuper; 22import android.annotation.ColorInt; 23import android.annotation.DrawableRes; 24import android.annotation.FloatRange; 25import android.annotation.IdRes; 26import android.annotation.IntDef; 27import android.annotation.LayoutRes; 28import android.annotation.NonNull; 29import android.annotation.Nullable; 30import android.annotation.Size; 31import android.annotation.UiThread; 32import android.content.ClipData; 33import android.content.Context; 34import android.content.ContextWrapper; 35import android.content.Intent; 36import android.content.res.ColorStateList; 37import android.content.res.Configuration; 38import android.content.res.Resources; 39import android.content.res.TypedArray; 40import android.graphics.Bitmap; 41import android.graphics.Canvas; 42import android.graphics.Insets; 43import android.graphics.Interpolator; 44import android.graphics.LinearGradient; 45import android.graphics.Matrix; 46import android.graphics.Outline; 47import android.graphics.Paint; 48import android.graphics.PixelFormat; 49import android.graphics.Point; 50import android.graphics.PorterDuff; 51import android.graphics.PorterDuffXfermode; 52import android.graphics.Rect; 53import android.graphics.RectF; 54import android.graphics.Region; 55import android.graphics.Shader; 56import android.graphics.drawable.ColorDrawable; 57import android.graphics.drawable.Drawable; 58import android.hardware.display.DisplayManagerGlobal; 59import android.os.Build.VERSION_CODES; 60import android.os.Bundle; 61import android.os.Handler; 62import android.os.IBinder; 63import android.os.Parcel; 64import android.os.Parcelable; 65import android.os.RemoteException; 66import android.os.SystemClock; 67import android.os.SystemProperties; 68import android.os.Trace; 69import android.text.TextUtils; 70import android.util.AttributeSet; 71import android.util.FloatProperty; 72import android.util.LayoutDirection; 73import android.util.Log; 74import android.util.LongSparseLongArray; 75import android.util.Pools.SynchronizedPool; 76import android.util.Property; 77import android.util.SparseArray; 78import android.util.StateSet; 79import android.util.SuperNotCalledException; 80import android.util.TypedValue; 81import android.view.ContextMenu.ContextMenuInfo; 82import android.view.AccessibilityIterators.TextSegmentIterator; 83import android.view.AccessibilityIterators.CharacterTextSegmentIterator; 84import android.view.AccessibilityIterators.WordTextSegmentIterator; 85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; 86import android.view.ViewGroup.LayoutParams; 87import android.view.accessibility.AccessibilityEvent; 88import android.view.accessibility.AccessibilityEventSource; 89import android.view.accessibility.AccessibilityManager; 90import android.view.accessibility.AccessibilityNodeInfo; 91import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 92import android.view.accessibility.AccessibilityNodeProvider; 93import android.view.animation.Animation; 94import android.view.animation.AnimationUtils; 95import android.view.animation.Transformation; 96import android.view.inputmethod.EditorInfo; 97import android.view.inputmethod.InputConnection; 98import android.view.inputmethod.InputMethodManager; 99import android.widget.Checkable; 100import android.widget.FrameLayout; 101import android.widget.ScrollBarDrawable; 102 103import static android.os.Build.VERSION_CODES.*; 104import static java.lang.Math.max; 105 106import com.android.internal.R; 107import com.android.internal.util.Predicate; 108import com.android.internal.view.menu.MenuBuilder; 109import com.google.android.collect.Lists; 110import com.google.android.collect.Maps; 111 112import java.lang.annotation.Retention; 113import java.lang.annotation.RetentionPolicy; 114import java.lang.ref.WeakReference; 115import java.lang.reflect.Field; 116import java.lang.reflect.InvocationTargetException; 117import java.lang.reflect.Method; 118import java.lang.reflect.Modifier; 119import java.util.ArrayList; 120import java.util.Arrays; 121import java.util.Collections; 122import java.util.HashMap; 123import java.util.List; 124import java.util.Locale; 125import java.util.Map; 126import java.util.concurrent.CopyOnWriteArrayList; 127import java.util.concurrent.atomic.AtomicInteger; 128 129/** 130 * <p> 131 * This class represents the basic building block for user interface components. A View 132 * occupies a rectangular area on the screen and is responsible for drawing and 133 * event handling. View is the base class for <em>widgets</em>, which are 134 * used to create interactive UI components (buttons, text fields, etc.). The 135 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which 136 * are invisible containers that hold other Views (or other ViewGroups) and define 137 * their layout properties. 138 * </p> 139 * 140 * <div class="special reference"> 141 * <h3>Developer Guides</h3> 142 * <p>For information about using this class to develop your application's user interface, 143 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide. 144 * </div> 145 * 146 * <a name="Using"></a> 147 * <h3>Using Views</h3> 148 * <p> 149 * All of the views in a window are arranged in a single tree. You can add views 150 * either from code or by specifying a tree of views in one or more XML layout 151 * files. There are many specialized subclasses of views that act as controls or 152 * are capable of displaying text, images, or other content. 153 * </p> 154 * <p> 155 * Once you have created a tree of views, there are typically a few types of 156 * common operations you may wish to perform: 157 * <ul> 158 * <li><strong>Set properties:</strong> for example setting the text of a 159 * {@link android.widget.TextView}. The available properties and the methods 160 * that set them will vary among the different subclasses of views. Note that 161 * properties that are known at build time can be set in the XML layout 162 * files.</li> 163 * <li><strong>Set focus:</strong> The framework will handled moving focus in 164 * response to user input. To force focus to a specific view, call 165 * {@link #requestFocus}.</li> 166 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners 167 * that will be notified when something interesting happens to the view. For 168 * example, all views will let you set a listener to be notified when the view 169 * gains or loses focus. You can register such a listener using 170 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}. 171 * Other view subclasses offer more specialized listeners. For example, a Button 172 * exposes a listener to notify clients when the button is clicked.</li> 173 * <li><strong>Set visibility:</strong> You can hide or show views using 174 * {@link #setVisibility(int)}.</li> 175 * </ul> 176 * </p> 177 * <p><em> 178 * Note: The Android framework is responsible for measuring, laying out and 179 * drawing views. You should not call methods that perform these actions on 180 * views yourself unless you are actually implementing a 181 * {@link android.view.ViewGroup}. 182 * </em></p> 183 * 184 * <a name="Lifecycle"></a> 185 * <h3>Implementing a Custom View</h3> 186 * 187 * <p> 188 * To implement a custom view, you will usually begin by providing overrides for 189 * some of the standard methods that the framework calls on all views. You do 190 * not need to override all of these methods. In fact, you can start by just 191 * overriding {@link #onDraw(android.graphics.Canvas)}. 192 * <table border="2" width="85%" align="center" cellpadding="5"> 193 * <thead> 194 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> 195 * </thead> 196 * 197 * <tbody> 198 * <tr> 199 * <td rowspan="2">Creation</td> 200 * <td>Constructors</td> 201 * <td>There is a form of the constructor that are called when the view 202 * is created from code and a form that is called when the view is 203 * inflated from a layout file. The second form should parse and apply 204 * any attributes defined in the layout file. 205 * </td> 206 * </tr> 207 * <tr> 208 * <td><code>{@link #onFinishInflate()}</code></td> 209 * <td>Called after a view and all of its children has been inflated 210 * from XML.</td> 211 * </tr> 212 * 213 * <tr> 214 * <td rowspan="3">Layout</td> 215 * <td><code>{@link #onMeasure(int, int)}</code></td> 216 * <td>Called to determine the size requirements for this view and all 217 * of its children. 218 * </td> 219 * </tr> 220 * <tr> 221 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td> 222 * <td>Called when this view should assign a size and position to all 223 * of its children. 224 * </td> 225 * </tr> 226 * <tr> 227 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td> 228 * <td>Called when the size of this view has changed. 229 * </td> 230 * </tr> 231 * 232 * <tr> 233 * <td>Drawing</td> 234 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td> 235 * <td>Called when the view should render its content. 236 * </td> 237 * </tr> 238 * 239 * <tr> 240 * <td rowspan="4">Event processing</td> 241 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td> 242 * <td>Called when a new hardware key event occurs. 243 * </td> 244 * </tr> 245 * <tr> 246 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td> 247 * <td>Called when a hardware key up event occurs. 248 * </td> 249 * </tr> 250 * <tr> 251 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td> 252 * <td>Called when a trackball motion event occurs. 253 * </td> 254 * </tr> 255 * <tr> 256 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td> 257 * <td>Called when a touch screen motion event occurs. 258 * </td> 259 * </tr> 260 * 261 * <tr> 262 * <td rowspan="2">Focus</td> 263 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td> 264 * <td>Called when the view gains or loses focus. 265 * </td> 266 * </tr> 267 * 268 * <tr> 269 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td> 270 * <td>Called when the window containing the view gains or loses focus. 271 * </td> 272 * </tr> 273 * 274 * <tr> 275 * <td rowspan="3">Attaching</td> 276 * <td><code>{@link #onAttachedToWindow()}</code></td> 277 * <td>Called when the view is attached to a window. 278 * </td> 279 * </tr> 280 * 281 * <tr> 282 * <td><code>{@link #onDetachedFromWindow}</code></td> 283 * <td>Called when the view is detached from its window. 284 * </td> 285 * </tr> 286 * 287 * <tr> 288 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td> 289 * <td>Called when the visibility of the window containing the view 290 * has changed. 291 * </td> 292 * </tr> 293 * </tbody> 294 * 295 * </table> 296 * </p> 297 * 298 * <a name="IDs"></a> 299 * <h3>IDs</h3> 300 * Views may have an integer id associated with them. These ids are typically 301 * assigned in the layout XML files, and are used to find specific views within 302 * the view tree. A common pattern is to: 303 * <ul> 304 * <li>Define a Button in the layout file and assign it a unique ID. 305 * <pre> 306 * <Button 307 * android:id="@+id/my_button" 308 * android:layout_width="wrap_content" 309 * android:layout_height="wrap_content" 310 * android:text="@string/my_button_text"/> 311 * </pre></li> 312 * <li>From the onCreate method of an Activity, find the Button 313 * <pre class="prettyprint"> 314 * Button myButton = (Button) findViewById(R.id.my_button); 315 * </pre></li> 316 * </ul> 317 * <p> 318 * View IDs need not be unique throughout the tree, but it is good practice to 319 * ensure that they are at least unique within the part of the tree you are 320 * searching. 321 * </p> 322 * 323 * <a name="Position"></a> 324 * <h3>Position</h3> 325 * <p> 326 * The geometry of a view is that of a rectangle. A view has a location, 327 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and 328 * two dimensions, expressed as a width and a height. The unit for location 329 * and dimensions is the pixel. 330 * </p> 331 * 332 * <p> 333 * It is possible to retrieve the location of a view by invoking the methods 334 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X, 335 * coordinate of the rectangle representing the view. The latter returns the 336 * top, or Y, coordinate of the rectangle representing the view. These methods 337 * both return the location of the view relative to its parent. For instance, 338 * when getLeft() returns 20, that means the view is located 20 pixels to the 339 * right of the left edge of its direct parent. 340 * </p> 341 * 342 * <p> 343 * In addition, several convenience methods are offered to avoid unnecessary 344 * computations, namely {@link #getRight()} and {@link #getBottom()}. 345 * These methods return the coordinates of the right and bottom edges of the 346 * rectangle representing the view. For instance, calling {@link #getRight()} 347 * is similar to the following computation: <code>getLeft() + getWidth()</code> 348 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.) 349 * </p> 350 * 351 * <a name="SizePaddingMargins"></a> 352 * <h3>Size, padding and margins</h3> 353 * <p> 354 * The size of a view is expressed with a width and a height. A view actually 355 * possess two pairs of width and height values. 356 * </p> 357 * 358 * <p> 359 * The first pair is known as <em>measured width</em> and 360 * <em>measured height</em>. These dimensions define how big a view wants to be 361 * within its parent (see <a href="#Layout">Layout</a> for more details.) The 362 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()} 363 * and {@link #getMeasuredHeight()}. 364 * </p> 365 * 366 * <p> 367 * The second pair is simply known as <em>width</em> and <em>height</em>, or 368 * sometimes <em>drawing width</em> and <em>drawing height</em>. These 369 * dimensions define the actual size of the view on screen, at drawing time and 370 * after layout. These values may, but do not have to, be different from the 371 * measured width and height. The width and height can be obtained by calling 372 * {@link #getWidth()} and {@link #getHeight()}. 373 * </p> 374 * 375 * <p> 376 * To measure its dimensions, a view takes into account its padding. The padding 377 * is expressed in pixels for the left, top, right and bottom parts of the view. 378 * Padding can be used to offset the content of the view by a specific amount of 379 * pixels. For instance, a left padding of 2 will push the view's content by 380 * 2 pixels to the right of the left edge. Padding can be set using the 381 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)} 382 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()}, 383 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()}, 384 * {@link #getPaddingEnd()}. 385 * </p> 386 * 387 * <p> 388 * Even though a view can define a padding, it does not provide any support for 389 * margins. However, view groups provide such a support. Refer to 390 * {@link android.view.ViewGroup} and 391 * {@link android.view.ViewGroup.MarginLayoutParams} for further information. 392 * </p> 393 * 394 * <a name="Layout"></a> 395 * <h3>Layout</h3> 396 * <p> 397 * Layout is a two pass process: a measure pass and a layout pass. The measuring 398 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal 399 * of the view tree. Each view pushes dimension specifications down the tree 400 * during the recursion. At the end of the measure pass, every view has stored 401 * its measurements. The second pass happens in 402 * {@link #layout(int,int,int,int)} and is also top-down. During 403 * this pass each parent is responsible for positioning all of its children 404 * using the sizes computed in the measure pass. 405 * </p> 406 * 407 * <p> 408 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and 409 * {@link #getMeasuredHeight()} values must be set, along with those for all of 410 * that view's descendants. A view's measured width and measured height values 411 * must respect the constraints imposed by the view's parents. This guarantees 412 * that at the end of the measure pass, all parents accept all of their 413 * children's measurements. A parent view may call measure() more than once on 414 * its children. For example, the parent may measure each child once with 415 * unspecified dimensions to find out how big they want to be, then call 416 * measure() on them again with actual numbers if the sum of all the children's 417 * unconstrained sizes is too big or too small. 418 * </p> 419 * 420 * <p> 421 * The measure pass uses two classes to communicate dimensions. The 422 * {@link MeasureSpec} class is used by views to tell their parents how they 423 * want to be measured and positioned. The base LayoutParams class just 424 * describes how big the view wants to be for both width and height. For each 425 * dimension, it can specify one of: 426 * <ul> 427 * <li> an exact number 428 * <li>MATCH_PARENT, which means the view wants to be as big as its parent 429 * (minus padding) 430 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to 431 * enclose its content (plus padding). 432 * </ul> 433 * There are subclasses of LayoutParams for different subclasses of ViewGroup. 434 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds 435 * an X and Y value. 436 * </p> 437 * 438 * <p> 439 * MeasureSpecs are used to push requirements down the tree from parent to 440 * child. A MeasureSpec can be in one of three modes: 441 * <ul> 442 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension 443 * of a child view. For example, a LinearLayout may call measure() on its child 444 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how 445 * tall the child view wants to be given a width of 240 pixels. 446 * <li>EXACTLY: This is used by the parent to impose an exact size on the 447 * child. The child must use this size, and guarantee that all of its 448 * descendants will fit within this size. 449 * <li>AT_MOST: This is used by the parent to impose a maximum size on the 450 * child. The child must guarantee that it and all of its descendants will fit 451 * within this size. 452 * </ul> 453 * </p> 454 * 455 * <p> 456 * To initiate a layout, call {@link #requestLayout}. This method is typically 457 * called by a view on itself when it believes that is can no longer fit within 458 * its current bounds. 459 * </p> 460 * 461 * <a name="Drawing"></a> 462 * <h3>Drawing</h3> 463 * <p> 464 * Drawing is handled by walking the tree and recording the drawing commands of 465 * any View that needs to update. After this, the drawing commands of the 466 * entire tree are issued to screen, clipped to the newly damaged area. 467 * </p> 468 * 469 * <p> 470 * The tree is largely recorded and drawn in order, with parents drawn before 471 * (i.e., behind) their children, with siblings drawn in the order they appear 472 * in the tree. If you set a background drawable for a View, then the View will 473 * draw it before calling back to its <code>onDraw()</code> method. The child 474 * drawing order can be overridden with 475 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order} 476 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views. 477 * </p> 478 * 479 * <p> 480 * To force a view to draw, call {@link #invalidate()}. 481 * </p> 482 * 483 * <a name="EventHandlingThreading"></a> 484 * <h3>Event Handling and Threading</h3> 485 * <p> 486 * The basic cycle of a view is as follows: 487 * <ol> 488 * <li>An event comes in and is dispatched to the appropriate view. The view 489 * handles the event and notifies any listeners.</li> 490 * <li>If in the course of processing the event, the view's bounds may need 491 * to be changed, the view will call {@link #requestLayout()}.</li> 492 * <li>Similarly, if in the course of processing the event the view's appearance 493 * may need to be changed, the view will call {@link #invalidate()}.</li> 494 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called, 495 * the framework will take care of measuring, laying out, and drawing the tree 496 * as appropriate.</li> 497 * </ol> 498 * </p> 499 * 500 * <p><em>Note: The entire view tree is single threaded. You must always be on 501 * the UI thread when calling any method on any view.</em> 502 * If you are doing work on other threads and want to update the state of a view 503 * from that thread, you should use a {@link Handler}. 504 * </p> 505 * 506 * <a name="FocusHandling"></a> 507 * <h3>Focus Handling</h3> 508 * <p> 509 * The framework will handle routine focus movement in response to user input. 510 * This includes changing the focus as views are removed or hidden, or as new 511 * views become available. Views indicate their willingness to take focus 512 * through the {@link #isFocusable} method. To change whether a view can take 513 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below) 514 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode} 515 * and can change this via {@link #setFocusableInTouchMode(boolean)}. 516 * </p> 517 * <p> 518 * Focus movement is based on an algorithm which finds the nearest neighbor in a 519 * given direction. In rare cases, the default algorithm may not match the 520 * intended behavior of the developer. In these situations, you can provide 521 * explicit overrides by using these XML attributes in the layout file: 522 * <pre> 523 * nextFocusDown 524 * nextFocusLeft 525 * nextFocusRight 526 * nextFocusUp 527 * </pre> 528 * </p> 529 * 530 * 531 * <p> 532 * To get a particular view to take focus, call {@link #requestFocus()}. 533 * </p> 534 * 535 * <a name="TouchMode"></a> 536 * <h3>Touch Mode</h3> 537 * <p> 538 * When a user is navigating a user interface via directional keys such as a D-pad, it is 539 * necessary to give focus to actionable items such as buttons so the user can see 540 * what will take input. If the device has touch capabilities, however, and the user 541 * begins interacting with the interface by touching it, it is no longer necessary to 542 * always highlight, or give focus to, a particular view. This motivates a mode 543 * for interaction named 'touch mode'. 544 * </p> 545 * <p> 546 * For a touch capable device, once the user touches the screen, the device 547 * will enter touch mode. From this point onward, only views for which 548 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets. 549 * Other views that are touchable, like buttons, will not take focus when touched; they will 550 * only fire the on click listeners. 551 * </p> 552 * <p> 553 * Any time a user hits a directional key, such as a D-pad direction, the view device will 554 * exit touch mode, and find a view to take focus, so that the user may resume interacting 555 * with the user interface without touching the screen again. 556 * </p> 557 * <p> 558 * The touch mode state is maintained across {@link android.app.Activity}s. Call 559 * {@link #isInTouchMode} to see whether the device is currently in touch mode. 560 * </p> 561 * 562 * <a name="Scrolling"></a> 563 * <h3>Scrolling</h3> 564 * <p> 565 * The framework provides basic support for views that wish to internally 566 * scroll their content. This includes keeping track of the X and Y scroll 567 * offset as well as mechanisms for drawing scrollbars. See 568 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 569 * {@link #awakenScrollBars()} for more details. 570 * </p> 571 * 572 * <a name="Tags"></a> 573 * <h3>Tags</h3> 574 * <p> 575 * Unlike IDs, tags are not used to identify views. Tags are essentially an 576 * extra piece of information that can be associated with a view. They are most 577 * often used as a convenience to store data related to views in the views 578 * themselves rather than by putting them in a separate structure. 579 * </p> 580 * <p> 581 * Tags may be specified with character sequence values in layout XML as either 582 * a single tag using the {@link android.R.styleable#View_tag android:tag} 583 * attribute or multiple tags using the {@code <tag>} child element: 584 * <pre> 585 * <View ... 586 * android:tag="@string/mytag_value" /> 587 * <View ...> 588 * <tag android:id="@+id/mytag" 589 * android:value="@string/mytag_value" /> 590 * </View> 591 * </pre> 592 * </p> 593 * <p> 594 * Tags may also be specified with arbitrary objects from code using 595 * {@link #setTag(Object)} or {@link #setTag(int, Object)}. 596 * </p> 597 * 598 * <a name="Themes"></a> 599 * <h3>Themes</h3> 600 * <p> 601 * By default, Views are created using the theme of the Context object supplied 602 * to their constructor; however, a different theme may be specified by using 603 * the {@link android.R.styleable#View_theme android:theme} attribute in layout 604 * XML or by passing a {@link ContextThemeWrapper} to the constructor from 605 * code. 606 * </p> 607 * <p> 608 * When the {@link android.R.styleable#View_theme android:theme} attribute is 609 * used in XML, the specified theme is applied on top of the inflation 610 * context's theme (see {@link LayoutInflater}) and used for the view itself as 611 * well as any child elements. 612 * </p> 613 * <p> 614 * In the following example, both views will be created using the Material dark 615 * color scheme; however, because an overlay theme is used which only defines a 616 * subset of attributes, the value of 617 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on 618 * the inflation context's theme (e.g. the Activity theme) will be preserved. 619 * <pre> 620 * <LinearLayout 621 * ... 622 * android:theme="@android:theme/ThemeOverlay.Material.Dark"> 623 * <View ...> 624 * </LinearLayout> 625 * </pre> 626 * </p> 627 * 628 * <a name="Properties"></a> 629 * <h3>Properties</h3> 630 * <p> 631 * The View class exposes an {@link #ALPHA} property, as well as several transform-related 632 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are 633 * available both in the {@link Property} form as well as in similarly-named setter/getter 634 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can 635 * be used to set persistent state associated with these rendering-related properties on the view. 636 * The properties and methods can also be used in conjunction with 637 * {@link android.animation.Animator Animator}-based animations, described more in the 638 * <a href="#Animation">Animation</a> section. 639 * </p> 640 * 641 * <a name="Animation"></a> 642 * <h3>Animation</h3> 643 * <p> 644 * Starting with Android 3.0, the preferred way of animating views is to use the 645 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based 646 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and 647 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0 648 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only 649 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class 650 * makes animating these View properties particularly easy and efficient. 651 * </p> 652 * <p> 653 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered. 654 * You can attach an {@link Animation} object to a view using 655 * {@link #setAnimation(Animation)} or 656 * {@link #startAnimation(Animation)}. The animation can alter the scale, 657 * rotation, translation and alpha of a view over time. If the animation is 658 * attached to a view that has children, the animation will affect the entire 659 * subtree rooted by that node. When an animation is started, the framework will 660 * take care of redrawing the appropriate views until the animation completes. 661 * </p> 662 * 663 * <a name="Security"></a> 664 * <h3>Security</h3> 665 * <p> 666 * Sometimes it is essential that an application be able to verify that an action 667 * is being performed with the full knowledge and consent of the user, such as 668 * granting a permission request, making a purchase or clicking on an advertisement. 669 * Unfortunately, a malicious application could try to spoof the user into 670 * performing these actions, unaware, by concealing the intended purpose of the view. 671 * As a remedy, the framework offers a touch filtering mechanism that can be used to 672 * improve the security of views that provide access to sensitive functionality. 673 * </p><p> 674 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the 675 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework 676 * will discard touches that are received whenever the view's window is obscured by 677 * another visible window. As a result, the view will not receive touches whenever a 678 * toast, dialog or other window appears above the view's window. 679 * </p><p> 680 * For more fine-grained control over security, consider overriding the 681 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own 682 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. 683 * </p> 684 * 685 * @attr ref android.R.styleable#View_alpha 686 * @attr ref android.R.styleable#View_background 687 * @attr ref android.R.styleable#View_clickable 688 * @attr ref android.R.styleable#View_contentDescription 689 * @attr ref android.R.styleable#View_drawingCacheQuality 690 * @attr ref android.R.styleable#View_duplicateParentState 691 * @attr ref android.R.styleable#View_id 692 * @attr ref android.R.styleable#View_requiresFadingEdge 693 * @attr ref android.R.styleable#View_fadeScrollbars 694 * @attr ref android.R.styleable#View_fadingEdgeLength 695 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 696 * @attr ref android.R.styleable#View_fitsSystemWindows 697 * @attr ref android.R.styleable#View_isScrollContainer 698 * @attr ref android.R.styleable#View_focusable 699 * @attr ref android.R.styleable#View_focusableInTouchMode 700 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 701 * @attr ref android.R.styleable#View_keepScreenOn 702 * @attr ref android.R.styleable#View_layerType 703 * @attr ref android.R.styleable#View_layoutDirection 704 * @attr ref android.R.styleable#View_longClickable 705 * @attr ref android.R.styleable#View_minHeight 706 * @attr ref android.R.styleable#View_minWidth 707 * @attr ref android.R.styleable#View_nextFocusDown 708 * @attr ref android.R.styleable#View_nextFocusLeft 709 * @attr ref android.R.styleable#View_nextFocusRight 710 * @attr ref android.R.styleable#View_nextFocusUp 711 * @attr ref android.R.styleable#View_onClick 712 * @attr ref android.R.styleable#View_padding 713 * @attr ref android.R.styleable#View_paddingBottom 714 * @attr ref android.R.styleable#View_paddingLeft 715 * @attr ref android.R.styleable#View_paddingRight 716 * @attr ref android.R.styleable#View_paddingTop 717 * @attr ref android.R.styleable#View_paddingStart 718 * @attr ref android.R.styleable#View_paddingEnd 719 * @attr ref android.R.styleable#View_saveEnabled 720 * @attr ref android.R.styleable#View_rotation 721 * @attr ref android.R.styleable#View_rotationX 722 * @attr ref android.R.styleable#View_rotationY 723 * @attr ref android.R.styleable#View_scaleX 724 * @attr ref android.R.styleable#View_scaleY 725 * @attr ref android.R.styleable#View_scrollX 726 * @attr ref android.R.styleable#View_scrollY 727 * @attr ref android.R.styleable#View_scrollbarSize 728 * @attr ref android.R.styleable#View_scrollbarStyle 729 * @attr ref android.R.styleable#View_scrollbars 730 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 731 * @attr ref android.R.styleable#View_scrollbarFadeDuration 732 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal 733 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal 734 * @attr ref android.R.styleable#View_scrollbarThumbVertical 735 * @attr ref android.R.styleable#View_scrollbarTrackVertical 736 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack 737 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack 738 * @attr ref android.R.styleable#View_stateListAnimator 739 * @attr ref android.R.styleable#View_transitionName 740 * @attr ref android.R.styleable#View_soundEffectsEnabled 741 * @attr ref android.R.styleable#View_tag 742 * @attr ref android.R.styleable#View_textAlignment 743 * @attr ref android.R.styleable#View_textDirection 744 * @attr ref android.R.styleable#View_transformPivotX 745 * @attr ref android.R.styleable#View_transformPivotY 746 * @attr ref android.R.styleable#View_translationX 747 * @attr ref android.R.styleable#View_translationY 748 * @attr ref android.R.styleable#View_translationZ 749 * @attr ref android.R.styleable#View_visibility 750 * @attr ref android.R.styleable#View_theme 751 * 752 * @see android.view.ViewGroup 753 */ 754@UiThread 755public class View implements Drawable.Callback, KeyEvent.Callback, 756 AccessibilityEventSource { 757 private static final boolean DBG = false; 758 759 /** 760 * The logging tag used by this class with android.util.Log. 761 */ 762 protected static final String VIEW_LOG_TAG = "View"; 763 764 /** 765 * When set to true, apps will draw debugging information about their layouts. 766 * 767 * @hide 768 */ 769 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout"; 770 771 /** 772 * When set to true, this view will save its attribute data. 773 * 774 * @hide 775 */ 776 public static boolean mDebugViewAttributes = false; 777 778 /** 779 * Used to mark a View that has no ID. 780 */ 781 public static final int NO_ID = -1; 782 783 /** 784 * Signals that compatibility booleans have been initialized according to 785 * target SDK versions. 786 */ 787 private static boolean sCompatibilityDone = false; 788 789 /** 790 * Use the old (broken) way of building MeasureSpecs. 791 */ 792 private static boolean sUseBrokenMakeMeasureSpec = false; 793 794 /** 795 * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED 796 */ 797 static boolean sUseZeroUnspecifiedMeasureSpec = false; 798 799 /** 800 * Ignore any optimizations using the measure cache. 801 */ 802 private static boolean sIgnoreMeasureCache = false; 803 804 /** 805 * Ignore an optimization that skips unnecessary EXACTLY layout passes. 806 */ 807 private static boolean sAlwaysRemeasureExactly = false; 808 809 /** 810 * Relax constraints around whether setLayoutParams() must be called after 811 * modifying the layout params. 812 */ 813 private static boolean sLayoutParamsAlwaysChanged = false; 814 815 /** 816 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when 817 * calling setFlags. 818 */ 819 private static final int NOT_FOCUSABLE = 0x00000000; 820 821 /** 822 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling 823 * setFlags. 824 */ 825 private static final int FOCUSABLE = 0x00000001; 826 827 /** 828 * Mask for use with setFlags indicating bits used for focus. 829 */ 830 private static final int FOCUSABLE_MASK = 0x00000001; 831 832 /** 833 * This view will adjust its padding to fit sytem windows (e.g. status bar) 834 */ 835 private static final int FITS_SYSTEM_WINDOWS = 0x00000002; 836 837 /** @hide */ 838 @IntDef({VISIBLE, INVISIBLE, GONE}) 839 @Retention(RetentionPolicy.SOURCE) 840 public @interface Visibility {} 841 842 /** 843 * This view is visible. 844 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 845 * android:visibility}. 846 */ 847 public static final int VISIBLE = 0x00000000; 848 849 /** 850 * This view is invisible, but it still takes up space for layout purposes. 851 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 852 * android:visibility}. 853 */ 854 public static final int INVISIBLE = 0x00000004; 855 856 /** 857 * This view is invisible, and it doesn't take any space for layout 858 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code 859 * android:visibility}. 860 */ 861 public static final int GONE = 0x00000008; 862 863 /** 864 * Mask for use with setFlags indicating bits used for visibility. 865 * {@hide} 866 */ 867 static final int VISIBILITY_MASK = 0x0000000C; 868 869 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE}; 870 871 /** 872 * This view is enabled. Interpretation varies by subclass. 873 * Use with ENABLED_MASK when calling setFlags. 874 * {@hide} 875 */ 876 static final int ENABLED = 0x00000000; 877 878 /** 879 * This view is disabled. Interpretation varies by subclass. 880 * Use with ENABLED_MASK when calling setFlags. 881 * {@hide} 882 */ 883 static final int DISABLED = 0x00000020; 884 885 /** 886 * Mask for use with setFlags indicating bits used for indicating whether 887 * this view is enabled 888 * {@hide} 889 */ 890 static final int ENABLED_MASK = 0x00000020; 891 892 /** 893 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be 894 * called and further optimizations will be performed. It is okay to have 895 * this flag set and a background. Use with DRAW_MASK when calling setFlags. 896 * {@hide} 897 */ 898 static final int WILL_NOT_DRAW = 0x00000080; 899 900 /** 901 * Mask for use with setFlags indicating bits used for indicating whether 902 * this view is will draw 903 * {@hide} 904 */ 905 static final int DRAW_MASK = 0x00000080; 906 907 /** 908 * <p>This view doesn't show scrollbars.</p> 909 * {@hide} 910 */ 911 static final int SCROLLBARS_NONE = 0x00000000; 912 913 /** 914 * <p>This view shows horizontal scrollbars.</p> 915 * {@hide} 916 */ 917 static final int SCROLLBARS_HORIZONTAL = 0x00000100; 918 919 /** 920 * <p>This view shows vertical scrollbars.</p> 921 * {@hide} 922 */ 923 static final int SCROLLBARS_VERTICAL = 0x00000200; 924 925 /** 926 * <p>Mask for use with setFlags indicating bits used for indicating which 927 * scrollbars are enabled.</p> 928 * {@hide} 929 */ 930 static final int SCROLLBARS_MASK = 0x00000300; 931 932 /** 933 * Indicates that the view should filter touches when its window is obscured. 934 * Refer to the class comments for more information about this security feature. 935 * {@hide} 936 */ 937 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400; 938 939 /** 940 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate 941 * that they are optional and should be skipped if the window has 942 * requested system UI flags that ignore those insets for layout. 943 */ 944 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800; 945 946 /** 947 * <p>This view doesn't show fading edges.</p> 948 * {@hide} 949 */ 950 static final int FADING_EDGE_NONE = 0x00000000; 951 952 /** 953 * <p>This view shows horizontal fading edges.</p> 954 * {@hide} 955 */ 956 static final int FADING_EDGE_HORIZONTAL = 0x00001000; 957 958 /** 959 * <p>This view shows vertical fading edges.</p> 960 * {@hide} 961 */ 962 static final int FADING_EDGE_VERTICAL = 0x00002000; 963 964 /** 965 * <p>Mask for use with setFlags indicating bits used for indicating which 966 * fading edges are enabled.</p> 967 * {@hide} 968 */ 969 static final int FADING_EDGE_MASK = 0x00003000; 970 971 /** 972 * <p>Indicates this view can be clicked. When clickable, a View reacts 973 * to clicks by notifying the OnClickListener.<p> 974 * {@hide} 975 */ 976 static final int CLICKABLE = 0x00004000; 977 978 /** 979 * <p>Indicates this view is caching its drawing into a bitmap.</p> 980 * {@hide} 981 */ 982 static final int DRAWING_CACHE_ENABLED = 0x00008000; 983 984 /** 985 * <p>Indicates that no icicle should be saved for this view.<p> 986 * {@hide} 987 */ 988 static final int SAVE_DISABLED = 0x000010000; 989 990 /** 991 * <p>Mask for use with setFlags indicating bits used for the saveEnabled 992 * property.</p> 993 * {@hide} 994 */ 995 static final int SAVE_DISABLED_MASK = 0x000010000; 996 997 /** 998 * <p>Indicates that no drawing cache should ever be created for this view.<p> 999 * {@hide} 1000 */ 1001 static final int WILL_NOT_CACHE_DRAWING = 0x000020000; 1002 1003 /** 1004 * <p>Indicates this view can take / keep focus when int touch mode.</p> 1005 * {@hide} 1006 */ 1007 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000; 1008 1009 /** @hide */ 1010 @Retention(RetentionPolicy.SOURCE) 1011 @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO}) 1012 public @interface DrawingCacheQuality {} 1013 1014 /** 1015 * <p>Enables low quality mode for the drawing cache.</p> 1016 */ 1017 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000; 1018 1019 /** 1020 * <p>Enables high quality mode for the drawing cache.</p> 1021 */ 1022 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000; 1023 1024 /** 1025 * <p>Enables automatic quality mode for the drawing cache.</p> 1026 */ 1027 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000; 1028 1029 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = { 1030 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH 1031 }; 1032 1033 /** 1034 * <p>Mask for use with setFlags indicating bits used for the cache 1035 * quality property.</p> 1036 * {@hide} 1037 */ 1038 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000; 1039 1040 /** 1041 * <p> 1042 * Indicates this view can be long clicked. When long clickable, a View 1043 * reacts to long clicks by notifying the OnLongClickListener or showing a 1044 * context menu. 1045 * </p> 1046 * {@hide} 1047 */ 1048 static final int LONG_CLICKABLE = 0x00200000; 1049 1050 /** 1051 * <p>Indicates that this view gets its drawable states from its direct parent 1052 * and ignores its original internal states.</p> 1053 * 1054 * @hide 1055 */ 1056 static final int DUPLICATE_PARENT_STATE = 0x00400000; 1057 1058 /** 1059 * <p> 1060 * Indicates this view can be context clicked. When context clickable, a View reacts to a 1061 * context click (e.g. a primary stylus button press or right mouse click) by notifying the 1062 * OnContextClickListener. 1063 * </p> 1064 * {@hide} 1065 */ 1066 static final int CONTEXT_CLICKABLE = 0x00800000; 1067 1068 1069 /** @hide */ 1070 @IntDef({ 1071 SCROLLBARS_INSIDE_OVERLAY, 1072 SCROLLBARS_INSIDE_INSET, 1073 SCROLLBARS_OUTSIDE_OVERLAY, 1074 SCROLLBARS_OUTSIDE_INSET 1075 }) 1076 @Retention(RetentionPolicy.SOURCE) 1077 public @interface ScrollBarStyle {} 1078 1079 /** 1080 * The scrollbar style to display the scrollbars inside the content area, 1081 * without increasing the padding. The scrollbars will be overlaid with 1082 * translucency on the view's content. 1083 */ 1084 public static final int SCROLLBARS_INSIDE_OVERLAY = 0; 1085 1086 /** 1087 * The scrollbar style to display the scrollbars inside the padded area, 1088 * increasing the padding of the view. The scrollbars will not overlap the 1089 * content area of the view. 1090 */ 1091 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000; 1092 1093 /** 1094 * The scrollbar style to display the scrollbars at the edge of the view, 1095 * without increasing the padding. The scrollbars will be overlaid with 1096 * translucency. 1097 */ 1098 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000; 1099 1100 /** 1101 * The scrollbar style to display the scrollbars at the edge of the view, 1102 * increasing the padding of the view. The scrollbars will only overlap the 1103 * background, if any. 1104 */ 1105 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000; 1106 1107 /** 1108 * Mask to check if the scrollbar style is overlay or inset. 1109 * {@hide} 1110 */ 1111 static final int SCROLLBARS_INSET_MASK = 0x01000000; 1112 1113 /** 1114 * Mask to check if the scrollbar style is inside or outside. 1115 * {@hide} 1116 */ 1117 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000; 1118 1119 /** 1120 * Mask for scrollbar style. 1121 * {@hide} 1122 */ 1123 static final int SCROLLBARS_STYLE_MASK = 0x03000000; 1124 1125 /** 1126 * View flag indicating that the screen should remain on while the 1127 * window containing this view is visible to the user. This effectively 1128 * takes care of automatically setting the WindowManager's 1129 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}. 1130 */ 1131 public static final int KEEP_SCREEN_ON = 0x04000000; 1132 1133 /** 1134 * View flag indicating whether this view should have sound effects enabled 1135 * for events such as clicking and touching. 1136 */ 1137 public static final int SOUND_EFFECTS_ENABLED = 0x08000000; 1138 1139 /** 1140 * View flag indicating whether this view should have haptic feedback 1141 * enabled for events such as long presses. 1142 */ 1143 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; 1144 1145 /** 1146 * <p>Indicates that the view hierarchy should stop saving state when 1147 * it reaches this view. If state saving is initiated immediately at 1148 * the view, it will be allowed. 1149 * {@hide} 1150 */ 1151 static final int PARENT_SAVE_DISABLED = 0x20000000; 1152 1153 /** 1154 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p> 1155 * {@hide} 1156 */ 1157 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000; 1158 1159 /** @hide */ 1160 @IntDef(flag = true, 1161 value = { 1162 FOCUSABLES_ALL, 1163 FOCUSABLES_TOUCH_MODE 1164 }) 1165 @Retention(RetentionPolicy.SOURCE) 1166 public @interface FocusableMode {} 1167 1168 /** 1169 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1170 * should add all focusable Views regardless if they are focusable in touch mode. 1171 */ 1172 public static final int FOCUSABLES_ALL = 0x00000000; 1173 1174 /** 1175 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)} 1176 * should add only Views focusable in touch mode. 1177 */ 1178 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001; 1179 1180 /** @hide */ 1181 @IntDef({ 1182 FOCUS_BACKWARD, 1183 FOCUS_FORWARD, 1184 FOCUS_LEFT, 1185 FOCUS_UP, 1186 FOCUS_RIGHT, 1187 FOCUS_DOWN 1188 }) 1189 @Retention(RetentionPolicy.SOURCE) 1190 public @interface FocusDirection {} 1191 1192 /** @hide */ 1193 @IntDef({ 1194 FOCUS_LEFT, 1195 FOCUS_UP, 1196 FOCUS_RIGHT, 1197 FOCUS_DOWN 1198 }) 1199 @Retention(RetentionPolicy.SOURCE) 1200 public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward 1201 1202 /** 1203 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable 1204 * item. 1205 */ 1206 public static final int FOCUS_BACKWARD = 0x00000001; 1207 1208 /** 1209 * Use with {@link #focusSearch(int)}. Move focus to the next selectable 1210 * item. 1211 */ 1212 public static final int FOCUS_FORWARD = 0x00000002; 1213 1214 /** 1215 * Use with {@link #focusSearch(int)}. Move focus to the left. 1216 */ 1217 public static final int FOCUS_LEFT = 0x00000011; 1218 1219 /** 1220 * Use with {@link #focusSearch(int)}. Move focus up. 1221 */ 1222 public static final int FOCUS_UP = 0x00000021; 1223 1224 /** 1225 * Use with {@link #focusSearch(int)}. Move focus to the right. 1226 */ 1227 public static final int FOCUS_RIGHT = 0x00000042; 1228 1229 /** 1230 * Use with {@link #focusSearch(int)}. Move focus down. 1231 */ 1232 public static final int FOCUS_DOWN = 0x00000082; 1233 1234 /** 1235 * Bits of {@link #getMeasuredWidthAndState()} and 1236 * {@link #getMeasuredWidthAndState()} that provide the actual measured size. 1237 */ 1238 public static final int MEASURED_SIZE_MASK = 0x00ffffff; 1239 1240 /** 1241 * Bits of {@link #getMeasuredWidthAndState()} and 1242 * {@link #getMeasuredWidthAndState()} that provide the additional state bits. 1243 */ 1244 public static final int MEASURED_STATE_MASK = 0xff000000; 1245 1246 /** 1247 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits 1248 * for functions that combine both width and height into a single int, 1249 * such as {@link #getMeasuredState()} and the childState argument of 1250 * {@link #resolveSizeAndState(int, int, int)}. 1251 */ 1252 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16; 1253 1254 /** 1255 * Bit of {@link #getMeasuredWidthAndState()} and 1256 * {@link #getMeasuredWidthAndState()} that indicates the measured size 1257 * is smaller that the space the view would like to have. 1258 */ 1259 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000; 1260 1261 /** 1262 * Base View state sets 1263 */ 1264 // Singles 1265 /** 1266 * Indicates the view has no states set. States are used with 1267 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1268 * view depending on its state. 1269 * 1270 * @see android.graphics.drawable.Drawable 1271 * @see #getDrawableState() 1272 */ 1273 protected static final int[] EMPTY_STATE_SET; 1274 /** 1275 * Indicates the view is enabled. States are used with 1276 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1277 * view depending on its state. 1278 * 1279 * @see android.graphics.drawable.Drawable 1280 * @see #getDrawableState() 1281 */ 1282 protected static final int[] ENABLED_STATE_SET; 1283 /** 1284 * Indicates the view is focused. States are used with 1285 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1286 * view depending on its state. 1287 * 1288 * @see android.graphics.drawable.Drawable 1289 * @see #getDrawableState() 1290 */ 1291 protected static final int[] FOCUSED_STATE_SET; 1292 /** 1293 * Indicates the view is selected. States are used with 1294 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1295 * view depending on its state. 1296 * 1297 * @see android.graphics.drawable.Drawable 1298 * @see #getDrawableState() 1299 */ 1300 protected static final int[] SELECTED_STATE_SET; 1301 /** 1302 * Indicates the view is pressed. States are used with 1303 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1304 * view depending on its state. 1305 * 1306 * @see android.graphics.drawable.Drawable 1307 * @see #getDrawableState() 1308 */ 1309 protected static final int[] PRESSED_STATE_SET; 1310 /** 1311 * Indicates the view's window has focus. States are used with 1312 * {@link android.graphics.drawable.Drawable} to change the drawing of the 1313 * view depending on its state. 1314 * 1315 * @see android.graphics.drawable.Drawable 1316 * @see #getDrawableState() 1317 */ 1318 protected static final int[] WINDOW_FOCUSED_STATE_SET; 1319 // Doubles 1320 /** 1321 * Indicates the view is enabled and has the focus. 1322 * 1323 * @see #ENABLED_STATE_SET 1324 * @see #FOCUSED_STATE_SET 1325 */ 1326 protected static final int[] ENABLED_FOCUSED_STATE_SET; 1327 /** 1328 * Indicates the view is enabled and selected. 1329 * 1330 * @see #ENABLED_STATE_SET 1331 * @see #SELECTED_STATE_SET 1332 */ 1333 protected static final int[] ENABLED_SELECTED_STATE_SET; 1334 /** 1335 * Indicates the view is enabled and that its window has focus. 1336 * 1337 * @see #ENABLED_STATE_SET 1338 * @see #WINDOW_FOCUSED_STATE_SET 1339 */ 1340 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET; 1341 /** 1342 * Indicates the view is focused and selected. 1343 * 1344 * @see #FOCUSED_STATE_SET 1345 * @see #SELECTED_STATE_SET 1346 */ 1347 protected static final int[] FOCUSED_SELECTED_STATE_SET; 1348 /** 1349 * Indicates the view has the focus and that its window has the focus. 1350 * 1351 * @see #FOCUSED_STATE_SET 1352 * @see #WINDOW_FOCUSED_STATE_SET 1353 */ 1354 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET; 1355 /** 1356 * Indicates the view is selected and that its window has the focus. 1357 * 1358 * @see #SELECTED_STATE_SET 1359 * @see #WINDOW_FOCUSED_STATE_SET 1360 */ 1361 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET; 1362 // Triples 1363 /** 1364 * Indicates the view is enabled, focused and selected. 1365 * 1366 * @see #ENABLED_STATE_SET 1367 * @see #FOCUSED_STATE_SET 1368 * @see #SELECTED_STATE_SET 1369 */ 1370 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET; 1371 /** 1372 * Indicates the view is enabled, focused and its window has the focus. 1373 * 1374 * @see #ENABLED_STATE_SET 1375 * @see #FOCUSED_STATE_SET 1376 * @see #WINDOW_FOCUSED_STATE_SET 1377 */ 1378 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1379 /** 1380 * Indicates the view is enabled, selected and its window has the focus. 1381 * 1382 * @see #ENABLED_STATE_SET 1383 * @see #SELECTED_STATE_SET 1384 * @see #WINDOW_FOCUSED_STATE_SET 1385 */ 1386 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1387 /** 1388 * Indicates the view is focused, selected and its window has the focus. 1389 * 1390 * @see #FOCUSED_STATE_SET 1391 * @see #SELECTED_STATE_SET 1392 * @see #WINDOW_FOCUSED_STATE_SET 1393 */ 1394 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1395 /** 1396 * Indicates the view is enabled, focused, selected and its window 1397 * has the focus. 1398 * 1399 * @see #ENABLED_STATE_SET 1400 * @see #FOCUSED_STATE_SET 1401 * @see #SELECTED_STATE_SET 1402 * @see #WINDOW_FOCUSED_STATE_SET 1403 */ 1404 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1405 /** 1406 * Indicates the view is pressed and its window has the focus. 1407 * 1408 * @see #PRESSED_STATE_SET 1409 * @see #WINDOW_FOCUSED_STATE_SET 1410 */ 1411 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET; 1412 /** 1413 * Indicates the view is pressed and selected. 1414 * 1415 * @see #PRESSED_STATE_SET 1416 * @see #SELECTED_STATE_SET 1417 */ 1418 protected static final int[] PRESSED_SELECTED_STATE_SET; 1419 /** 1420 * Indicates the view is pressed, selected and its window has the focus. 1421 * 1422 * @see #PRESSED_STATE_SET 1423 * @see #SELECTED_STATE_SET 1424 * @see #WINDOW_FOCUSED_STATE_SET 1425 */ 1426 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1427 /** 1428 * Indicates the view is pressed and focused. 1429 * 1430 * @see #PRESSED_STATE_SET 1431 * @see #FOCUSED_STATE_SET 1432 */ 1433 protected static final int[] PRESSED_FOCUSED_STATE_SET; 1434 /** 1435 * Indicates the view is pressed, focused and its window has the focus. 1436 * 1437 * @see #PRESSED_STATE_SET 1438 * @see #FOCUSED_STATE_SET 1439 * @see #WINDOW_FOCUSED_STATE_SET 1440 */ 1441 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1442 /** 1443 * Indicates the view is pressed, focused and selected. 1444 * 1445 * @see #PRESSED_STATE_SET 1446 * @see #SELECTED_STATE_SET 1447 * @see #FOCUSED_STATE_SET 1448 */ 1449 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET; 1450 /** 1451 * Indicates the view is pressed, focused, selected and its window has the focus. 1452 * 1453 * @see #PRESSED_STATE_SET 1454 * @see #FOCUSED_STATE_SET 1455 * @see #SELECTED_STATE_SET 1456 * @see #WINDOW_FOCUSED_STATE_SET 1457 */ 1458 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1459 /** 1460 * Indicates the view is pressed and enabled. 1461 * 1462 * @see #PRESSED_STATE_SET 1463 * @see #ENABLED_STATE_SET 1464 */ 1465 protected static final int[] PRESSED_ENABLED_STATE_SET; 1466 /** 1467 * Indicates the view is pressed, enabled and its window has the focus. 1468 * 1469 * @see #PRESSED_STATE_SET 1470 * @see #ENABLED_STATE_SET 1471 * @see #WINDOW_FOCUSED_STATE_SET 1472 */ 1473 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET; 1474 /** 1475 * Indicates the view is pressed, enabled and selected. 1476 * 1477 * @see #PRESSED_STATE_SET 1478 * @see #ENABLED_STATE_SET 1479 * @see #SELECTED_STATE_SET 1480 */ 1481 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET; 1482 /** 1483 * Indicates the view is pressed, enabled, selected and its window has the 1484 * focus. 1485 * 1486 * @see #PRESSED_STATE_SET 1487 * @see #ENABLED_STATE_SET 1488 * @see #SELECTED_STATE_SET 1489 * @see #WINDOW_FOCUSED_STATE_SET 1490 */ 1491 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1492 /** 1493 * Indicates the view is pressed, enabled and focused. 1494 * 1495 * @see #PRESSED_STATE_SET 1496 * @see #ENABLED_STATE_SET 1497 * @see #FOCUSED_STATE_SET 1498 */ 1499 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET; 1500 /** 1501 * Indicates the view is pressed, enabled, focused and its window has the 1502 * focus. 1503 * 1504 * @see #PRESSED_STATE_SET 1505 * @see #ENABLED_STATE_SET 1506 * @see #FOCUSED_STATE_SET 1507 * @see #WINDOW_FOCUSED_STATE_SET 1508 */ 1509 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET; 1510 /** 1511 * Indicates the view is pressed, enabled, focused and selected. 1512 * 1513 * @see #PRESSED_STATE_SET 1514 * @see #ENABLED_STATE_SET 1515 * @see #SELECTED_STATE_SET 1516 * @see #FOCUSED_STATE_SET 1517 */ 1518 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET; 1519 /** 1520 * Indicates the view is pressed, enabled, focused, selected and its window 1521 * has the focus. 1522 * 1523 * @see #PRESSED_STATE_SET 1524 * @see #ENABLED_STATE_SET 1525 * @see #SELECTED_STATE_SET 1526 * @see #FOCUSED_STATE_SET 1527 * @see #WINDOW_FOCUSED_STATE_SET 1528 */ 1529 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET; 1530 1531 static { 1532 EMPTY_STATE_SET = StateSet.get(0); 1533 1534 WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED); 1535 1536 SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED); 1537 SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1538 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED); 1539 1540 FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED); 1541 FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1542 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED); 1543 FOCUSED_SELECTED_STATE_SET = StateSet.get( 1544 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED); 1545 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1546 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1547 | StateSet.VIEW_STATE_FOCUSED); 1548 1549 ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED); 1550 ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1551 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1552 ENABLED_SELECTED_STATE_SET = StateSet.get( 1553 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED); 1554 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1555 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1556 | StateSet.VIEW_STATE_ENABLED); 1557 ENABLED_FOCUSED_STATE_SET = StateSet.get( 1558 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED); 1559 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1560 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1561 | StateSet.VIEW_STATE_ENABLED); 1562 ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1563 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1564 | StateSet.VIEW_STATE_ENABLED); 1565 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1566 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1567 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED); 1568 1569 PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED); 1570 PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1571 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1572 PRESSED_SELECTED_STATE_SET = StateSet.get( 1573 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED); 1574 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1575 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1576 | StateSet.VIEW_STATE_PRESSED); 1577 PRESSED_FOCUSED_STATE_SET = StateSet.get( 1578 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1579 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1580 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1581 | StateSet.VIEW_STATE_PRESSED); 1582 PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1583 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1584 | StateSet.VIEW_STATE_PRESSED); 1585 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1586 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1587 | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED); 1588 PRESSED_ENABLED_STATE_SET = StateSet.get( 1589 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1590 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1591 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED 1592 | StateSet.VIEW_STATE_PRESSED); 1593 PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get( 1594 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED 1595 | StateSet.VIEW_STATE_PRESSED); 1596 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1597 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1598 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1599 PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get( 1600 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED 1601 | StateSet.VIEW_STATE_PRESSED); 1602 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1603 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED 1604 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1605 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get( 1606 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED 1607 | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED); 1608 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get( 1609 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED 1610 | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED 1611 | StateSet.VIEW_STATE_PRESSED); 1612 } 1613 1614 /** 1615 * Accessibility event types that are dispatched for text population. 1616 */ 1617 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES = 1618 AccessibilityEvent.TYPE_VIEW_CLICKED 1619 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 1620 | AccessibilityEvent.TYPE_VIEW_SELECTED 1621 | AccessibilityEvent.TYPE_VIEW_FOCUSED 1622 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 1623 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 1624 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 1625 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 1626 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 1627 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 1628 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 1629 1630 /** 1631 * Temporary Rect currently for use in setBackground(). This will probably 1632 * be extended in the future to hold our own class with more than just 1633 * a Rect. :) 1634 */ 1635 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>(); 1636 1637 /** 1638 * Map used to store views' tags. 1639 */ 1640 private SparseArray<Object> mKeyedTags; 1641 1642 /** 1643 * The next available accessibility id. 1644 */ 1645 private static int sNextAccessibilityViewId; 1646 1647 /** 1648 * The animation currently associated with this view. 1649 * @hide 1650 */ 1651 protected Animation mCurrentAnimation = null; 1652 1653 /** 1654 * Width as measured during measure pass. 1655 * {@hide} 1656 */ 1657 @ViewDebug.ExportedProperty(category = "measurement") 1658 int mMeasuredWidth; 1659 1660 /** 1661 * Height as measured during measure pass. 1662 * {@hide} 1663 */ 1664 @ViewDebug.ExportedProperty(category = "measurement") 1665 int mMeasuredHeight; 1666 1667 /** 1668 * Flag to indicate that this view was marked INVALIDATED, or had its display list 1669 * invalidated, prior to the current drawing iteration. If true, the view must re-draw 1670 * its display list. This flag, used only when hw accelerated, allows us to clear the 1671 * flag while retaining this information until it's needed (at getDisplayList() time and 1672 * in drawChild(), when we decide to draw a view's children's display lists into our own). 1673 * 1674 * {@hide} 1675 */ 1676 boolean mRecreateDisplayList = false; 1677 1678 /** 1679 * The view's identifier. 1680 * {@hide} 1681 * 1682 * @see #setId(int) 1683 * @see #getId() 1684 */ 1685 @IdRes 1686 @ViewDebug.ExportedProperty(resolveId = true) 1687 int mID = NO_ID; 1688 1689 /** 1690 * The stable ID of this view for accessibility purposes. 1691 */ 1692 int mAccessibilityViewId = NO_ID; 1693 1694 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 1695 1696 SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent; 1697 1698 /** 1699 * The view's tag. 1700 * {@hide} 1701 * 1702 * @see #setTag(Object) 1703 * @see #getTag() 1704 */ 1705 protected Object mTag = null; 1706 1707 // for mPrivateFlags: 1708 /** {@hide} */ 1709 static final int PFLAG_WANTS_FOCUS = 0x00000001; 1710 /** {@hide} */ 1711 static final int PFLAG_FOCUSED = 0x00000002; 1712 /** {@hide} */ 1713 static final int PFLAG_SELECTED = 0x00000004; 1714 /** {@hide} */ 1715 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008; 1716 /** {@hide} */ 1717 static final int PFLAG_HAS_BOUNDS = 0x00000010; 1718 /** {@hide} */ 1719 static final int PFLAG_DRAWN = 0x00000020; 1720 /** 1721 * When this flag is set, this view is running an animation on behalf of its 1722 * children and should therefore not cancel invalidate requests, even if they 1723 * lie outside of this view's bounds. 1724 * 1725 * {@hide} 1726 */ 1727 static final int PFLAG_DRAW_ANIMATION = 0x00000040; 1728 /** {@hide} */ 1729 static final int PFLAG_SKIP_DRAW = 0x00000080; 1730 /** {@hide} */ 1731 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200; 1732 /** {@hide} */ 1733 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400; 1734 /** {@hide} */ 1735 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800; 1736 /** {@hide} */ 1737 static final int PFLAG_FORCE_LAYOUT = 0x00001000; 1738 /** {@hide} */ 1739 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000; 1740 1741 private static final int PFLAG_PRESSED = 0x00004000; 1742 1743 /** {@hide} */ 1744 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000; 1745 /** 1746 * Flag used to indicate that this view should be drawn once more (and only once 1747 * more) after its animation has completed. 1748 * {@hide} 1749 */ 1750 static final int PFLAG_ANIMATION_STARTED = 0x00010000; 1751 1752 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000; 1753 1754 /** 1755 * Indicates that the View returned true when onSetAlpha() was called and that 1756 * the alpha must be restored. 1757 * {@hide} 1758 */ 1759 static final int PFLAG_ALPHA_SET = 0x00040000; 1760 1761 /** 1762 * Set by {@link #setScrollContainer(boolean)}. 1763 */ 1764 static final int PFLAG_SCROLL_CONTAINER = 0x00080000; 1765 1766 /** 1767 * Set by {@link #setScrollContainer(boolean)}. 1768 */ 1769 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000; 1770 1771 /** 1772 * View flag indicating whether this view was invalidated (fully or partially.) 1773 * 1774 * @hide 1775 */ 1776 static final int PFLAG_DIRTY = 0x00200000; 1777 1778 /** 1779 * View flag indicating whether this view was invalidated by an opaque 1780 * invalidate request. 1781 * 1782 * @hide 1783 */ 1784 static final int PFLAG_DIRTY_OPAQUE = 0x00400000; 1785 1786 /** 1787 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}. 1788 * 1789 * @hide 1790 */ 1791 static final int PFLAG_DIRTY_MASK = 0x00600000; 1792 1793 /** 1794 * Indicates whether the background is opaque. 1795 * 1796 * @hide 1797 */ 1798 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000; 1799 1800 /** 1801 * Indicates whether the scrollbars are opaque. 1802 * 1803 * @hide 1804 */ 1805 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000; 1806 1807 /** 1808 * Indicates whether the view is opaque. 1809 * 1810 * @hide 1811 */ 1812 static final int PFLAG_OPAQUE_MASK = 0x01800000; 1813 1814 /** 1815 * Indicates a prepressed state; 1816 * the short time between ACTION_DOWN and recognizing 1817 * a 'real' press. Prepressed is used to recognize quick taps 1818 * even when they are shorter than ViewConfiguration.getTapTimeout(). 1819 * 1820 * @hide 1821 */ 1822 private static final int PFLAG_PREPRESSED = 0x02000000; 1823 1824 /** 1825 * Indicates whether the view is temporarily detached. 1826 * 1827 * @hide 1828 */ 1829 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000; 1830 1831 /** 1832 * Indicates that we should awaken scroll bars once attached 1833 * 1834 * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged 1835 * during window attachment and it is no longer needed. Feel free to repurpose it. 1836 * 1837 * @hide 1838 */ 1839 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; 1840 1841 /** 1842 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT. 1843 * @hide 1844 */ 1845 private static final int PFLAG_HOVERED = 0x10000000; 1846 1847 /** 1848 * no longer needed, should be reused 1849 */ 1850 private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000; 1851 1852 /** {@hide} */ 1853 static final int PFLAG_ACTIVATED = 0x40000000; 1854 1855 /** 1856 * Indicates that this view was specifically invalidated, not just dirtied because some 1857 * child view was invalidated. The flag is used to determine when we need to recreate 1858 * a view's display list (as opposed to just returning a reference to its existing 1859 * display list). 1860 * 1861 * @hide 1862 */ 1863 static final int PFLAG_INVALIDATED = 0x80000000; 1864 1865 /** 1866 * Masks for mPrivateFlags2, as generated by dumpFlags(): 1867 * 1868 * |-------|-------|-------|-------| 1869 * 1 PFLAG2_DRAG_CAN_ACCEPT 1870 * 1 PFLAG2_DRAG_HOVERED 1871 * 11 PFLAG2_LAYOUT_DIRECTION_MASK 1872 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 1873 * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED 1874 * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 1875 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] 1876 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] 1877 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] 1878 * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] 1879 * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] 1880 * 11 PFLAG2_TEXT_DIRECTION_FLAGS[6] 1881 * 111 PFLAG2_TEXT_DIRECTION_FLAGS[7] 1882 * 111 PFLAG2_TEXT_DIRECTION_MASK 1883 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED 1884 * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT 1885 * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK 1886 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] 1887 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] 1888 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] 1889 * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] 1890 * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] 1891 * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] 1892 * 111 PFLAG2_TEXT_ALIGNMENT_MASK 1893 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED 1894 * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT 1895 * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK 1896 * 111 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK 1897 * 11 PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK 1898 * 1 PFLAG2_ACCESSIBILITY_FOCUSED 1899 * 1 PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED 1900 * 1 PFLAG2_VIEW_QUICK_REJECTED 1901 * 1 PFLAG2_PADDING_RESOLVED 1902 * 1 PFLAG2_DRAWABLE_RESOLVED 1903 * 1 PFLAG2_HAS_TRANSIENT_STATE 1904 * |-------|-------|-------|-------| 1905 */ 1906 1907 /** 1908 * Indicates that this view has reported that it can accept the current drag's content. 1909 * Cleared when the drag operation concludes. 1910 * @hide 1911 */ 1912 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001; 1913 1914 /** 1915 * Indicates that this view is currently directly under the drag location in a 1916 * drag-and-drop operation involving content that it can accept. Cleared when 1917 * the drag exits the view, or when the drag operation concludes. 1918 * @hide 1919 */ 1920 static final int PFLAG2_DRAG_HOVERED = 0x00000002; 1921 1922 /** @hide */ 1923 @IntDef({ 1924 LAYOUT_DIRECTION_LTR, 1925 LAYOUT_DIRECTION_RTL, 1926 LAYOUT_DIRECTION_INHERIT, 1927 LAYOUT_DIRECTION_LOCALE 1928 }) 1929 @Retention(RetentionPolicy.SOURCE) 1930 // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection 1931 public @interface LayoutDir {} 1932 1933 /** @hide */ 1934 @IntDef({ 1935 LAYOUT_DIRECTION_LTR, 1936 LAYOUT_DIRECTION_RTL 1937 }) 1938 @Retention(RetentionPolicy.SOURCE) 1939 public @interface ResolvedLayoutDir {} 1940 1941 /** 1942 * A flag to indicate that the layout direction of this view has not been defined yet. 1943 * @hide 1944 */ 1945 public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED; 1946 1947 /** 1948 * Horizontal layout direction of this view is from Left to Right. 1949 * Use with {@link #setLayoutDirection}. 1950 */ 1951 public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR; 1952 1953 /** 1954 * Horizontal layout direction of this view is from Right to Left. 1955 * Use with {@link #setLayoutDirection}. 1956 */ 1957 public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL; 1958 1959 /** 1960 * Horizontal layout direction of this view is inherited from its parent. 1961 * Use with {@link #setLayoutDirection}. 1962 */ 1963 public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT; 1964 1965 /** 1966 * Horizontal layout direction of this view is from deduced from the default language 1967 * script for the locale. Use with {@link #setLayoutDirection}. 1968 */ 1969 public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE; 1970 1971 /** 1972 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 1973 * @hide 1974 */ 1975 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2; 1976 1977 /** 1978 * Mask for use with private flags indicating bits used for horizontal layout direction. 1979 * @hide 1980 */ 1981 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1982 1983 /** 1984 * Indicates whether the view horizontal layout direction has been resolved and drawn to the 1985 * right-to-left direction. 1986 * @hide 1987 */ 1988 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1989 1990 /** 1991 * Indicates whether the view horizontal layout direction has been resolved. 1992 * @hide 1993 */ 1994 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 1995 1996 /** 1997 * Mask for use with private flags indicating bits used for resolved horizontal layout direction. 1998 * @hide 1999 */ 2000 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C 2001 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 2002 2003 /* 2004 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct 2005 * flag value. 2006 * @hide 2007 */ 2008 private static final int[] LAYOUT_DIRECTION_FLAGS = { 2009 LAYOUT_DIRECTION_LTR, 2010 LAYOUT_DIRECTION_RTL, 2011 LAYOUT_DIRECTION_INHERIT, 2012 LAYOUT_DIRECTION_LOCALE 2013 }; 2014 2015 /** 2016 * Default horizontal layout direction. 2017 */ 2018 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT; 2019 2020 /** 2021 * Default horizontal layout direction. 2022 * @hide 2023 */ 2024 static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR; 2025 2026 /** 2027 * Text direction is inherited through {@link ViewGroup} 2028 */ 2029 public static final int TEXT_DIRECTION_INHERIT = 0; 2030 2031 /** 2032 * Text direction is using "first strong algorithm". The first strong directional character 2033 * determines the paragraph direction. If there is no strong directional character, the 2034 * paragraph direction is the view's resolved layout direction. 2035 */ 2036 public static final int TEXT_DIRECTION_FIRST_STRONG = 1; 2037 2038 /** 2039 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains 2040 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters. 2041 * If there are neither, the paragraph direction is the view's resolved layout direction. 2042 */ 2043 public static final int TEXT_DIRECTION_ANY_RTL = 2; 2044 2045 /** 2046 * Text direction is forced to LTR. 2047 */ 2048 public static final int TEXT_DIRECTION_LTR = 3; 2049 2050 /** 2051 * Text direction is forced to RTL. 2052 */ 2053 public static final int TEXT_DIRECTION_RTL = 4; 2054 2055 /** 2056 * Text direction is coming from the system Locale. 2057 */ 2058 public static final int TEXT_DIRECTION_LOCALE = 5; 2059 2060 /** 2061 * Text direction is using "first strong algorithm". The first strong directional character 2062 * determines the paragraph direction. If there is no strong directional character, the 2063 * paragraph direction is LTR. 2064 */ 2065 public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6; 2066 2067 /** 2068 * Text direction is using "first strong algorithm". The first strong directional character 2069 * determines the paragraph direction. If there is no strong directional character, the 2070 * paragraph direction is RTL. 2071 */ 2072 public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7; 2073 2074 /** 2075 * Default text direction is inherited 2076 */ 2077 private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT; 2078 2079 /** 2080 * Default resolved text direction 2081 * @hide 2082 */ 2083 static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG; 2084 2085 /** 2086 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED) 2087 * @hide 2088 */ 2089 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6; 2090 2091 /** 2092 * Mask for use with private flags indicating bits used for text direction. 2093 * @hide 2094 */ 2095 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007 2096 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2097 2098 /** 2099 * Array of text direction flags for mapping attribute "textDirection" to correct 2100 * flag value. 2101 * @hide 2102 */ 2103 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = { 2104 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2105 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2106 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2107 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2108 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2109 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2110 TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT, 2111 TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT 2112 }; 2113 2114 /** 2115 * Indicates whether the view text direction has been resolved. 2116 * @hide 2117 */ 2118 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008 2119 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 2120 2121 /** 2122 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2123 * @hide 2124 */ 2125 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10; 2126 2127 /** 2128 * Mask for use with private flags indicating bits used for resolved text direction. 2129 * @hide 2130 */ 2131 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007 2132 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2133 2134 /** 2135 * Indicates whether the view text direction has been resolved to the "first strong" heuristic. 2136 * @hide 2137 */ 2138 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT = 2139 TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 2140 2141 /** @hide */ 2142 @IntDef({ 2143 TEXT_ALIGNMENT_INHERIT, 2144 TEXT_ALIGNMENT_GRAVITY, 2145 TEXT_ALIGNMENT_CENTER, 2146 TEXT_ALIGNMENT_TEXT_START, 2147 TEXT_ALIGNMENT_TEXT_END, 2148 TEXT_ALIGNMENT_VIEW_START, 2149 TEXT_ALIGNMENT_VIEW_END 2150 }) 2151 @Retention(RetentionPolicy.SOURCE) 2152 public @interface TextAlignment {} 2153 2154 /** 2155 * Default text alignment. The text alignment of this View is inherited from its parent. 2156 * Use with {@link #setTextAlignment(int)} 2157 */ 2158 public static final int TEXT_ALIGNMENT_INHERIT = 0; 2159 2160 /** 2161 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, 2162 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. 2163 * 2164 * Use with {@link #setTextAlignment(int)} 2165 */ 2166 public static final int TEXT_ALIGNMENT_GRAVITY = 1; 2167 2168 /** 2169 * Align to the start of the paragraph, e.g. ALIGN_NORMAL. 2170 * 2171 * Use with {@link #setTextAlignment(int)} 2172 */ 2173 public static final int TEXT_ALIGNMENT_TEXT_START = 2; 2174 2175 /** 2176 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. 2177 * 2178 * Use with {@link #setTextAlignment(int)} 2179 */ 2180 public static final int TEXT_ALIGNMENT_TEXT_END = 3; 2181 2182 /** 2183 * Center the paragraph, e.g. ALIGN_CENTER. 2184 * 2185 * Use with {@link #setTextAlignment(int)} 2186 */ 2187 public static final int TEXT_ALIGNMENT_CENTER = 4; 2188 2189 /** 2190 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved 2191 * layoutDirection is LTR, and ALIGN_RIGHT otherwise. 2192 * 2193 * Use with {@link #setTextAlignment(int)} 2194 */ 2195 public static final int TEXT_ALIGNMENT_VIEW_START = 5; 2196 2197 /** 2198 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved 2199 * layoutDirection is LTR, and ALIGN_LEFT otherwise. 2200 * 2201 * Use with {@link #setTextAlignment(int)} 2202 */ 2203 public static final int TEXT_ALIGNMENT_VIEW_END = 6; 2204 2205 /** 2206 * Default text alignment is inherited 2207 */ 2208 private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2209 2210 /** 2211 * Default resolved text alignment 2212 * @hide 2213 */ 2214 static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY; 2215 2216 /** 2217 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED) 2218 * @hide 2219 */ 2220 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13; 2221 2222 /** 2223 * Mask for use with private flags indicating bits used for text alignment. 2224 * @hide 2225 */ 2226 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2227 2228 /** 2229 * Array of text direction flags for mapping attribute "textAlignment" to correct 2230 * flag value. 2231 * @hide 2232 */ 2233 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = { 2234 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2235 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2236 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2237 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2238 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2239 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT, 2240 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT 2241 }; 2242 2243 /** 2244 * Indicates whether the view text alignment has been resolved. 2245 * @hide 2246 */ 2247 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 2248 2249 /** 2250 * Bit shift to get the resolved text alignment. 2251 * @hide 2252 */ 2253 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17; 2254 2255 /** 2256 * Mask for use with private flags indicating bits used for text alignment. 2257 * @hide 2258 */ 2259 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 2260 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2261 2262 /** 2263 * Indicates whether if the view text alignment has been resolved to gravity 2264 */ 2265 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT = 2266 TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 2267 2268 // Accessiblity constants for mPrivateFlags2 2269 2270 /** 2271 * Shift for the bits in {@link #mPrivateFlags2} related to the 2272 * "importantForAccessibility" attribute. 2273 */ 2274 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20; 2275 2276 /** 2277 * Automatically determine whether a view is important for accessibility. 2278 */ 2279 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000; 2280 2281 /** 2282 * The view is important for accessibility. 2283 */ 2284 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001; 2285 2286 /** 2287 * The view is not important for accessibility. 2288 */ 2289 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002; 2290 2291 /** 2292 * The view is not important for accessibility, nor are any of its 2293 * descendant views. 2294 */ 2295 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004; 2296 2297 /** 2298 * The default whether the view is important for accessibility. 2299 */ 2300 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO; 2301 2302 /** 2303 * Mask for obtainig the bits which specify how to determine 2304 * whether a view is important for accessibility. 2305 */ 2306 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO 2307 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO 2308 | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) 2309 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 2310 2311 /** 2312 * Shift for the bits in {@link #mPrivateFlags2} related to the 2313 * "accessibilityLiveRegion" attribute. 2314 */ 2315 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23; 2316 2317 /** 2318 * Live region mode specifying that accessibility services should not 2319 * automatically announce changes to this view. This is the default live 2320 * region mode for most views. 2321 * <p> 2322 * Use with {@link #setAccessibilityLiveRegion(int)}. 2323 */ 2324 public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000; 2325 2326 /** 2327 * Live region mode specifying that accessibility services should announce 2328 * changes to this view. 2329 * <p> 2330 * Use with {@link #setAccessibilityLiveRegion(int)}. 2331 */ 2332 public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001; 2333 2334 /** 2335 * Live region mode specifying that accessibility services should interrupt 2336 * ongoing speech to immediately announce changes to this view. 2337 * <p> 2338 * Use with {@link #setAccessibilityLiveRegion(int)}. 2339 */ 2340 public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002; 2341 2342 /** 2343 * The default whether the view is important for accessibility. 2344 */ 2345 static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE; 2346 2347 /** 2348 * Mask for obtaining the bits which specify a view's accessibility live 2349 * region mode. 2350 */ 2351 static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE 2352 | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE) 2353 << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 2354 2355 /** 2356 * Flag indicating whether a view has accessibility focus. 2357 */ 2358 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000; 2359 2360 /** 2361 * Flag whether the accessibility state of the subtree rooted at this view changed. 2362 */ 2363 static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000; 2364 2365 /** 2366 * Flag indicating whether a view failed the quickReject() check in draw(). This condition 2367 * is used to check whether later changes to the view's transform should invalidate the 2368 * view to force the quickReject test to run again. 2369 */ 2370 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000; 2371 2372 /** 2373 * Flag indicating that start/end padding has been resolved into left/right padding 2374 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()} 2375 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved 2376 * during measurement. In some special cases this is required such as when an adapter-based 2377 * view measures prospective children without attaching them to a window. 2378 */ 2379 static final int PFLAG2_PADDING_RESOLVED = 0x20000000; 2380 2381 /** 2382 * Flag indicating that the start/end drawables has been resolved into left/right ones. 2383 */ 2384 static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000; 2385 2386 /** 2387 * Indicates that the view is tracking some sort of transient state 2388 * that the app should not need to be aware of, but that the framework 2389 * should take special care to preserve. 2390 */ 2391 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000; 2392 2393 /** 2394 * Group of bits indicating that RTL properties resolution is done. 2395 */ 2396 static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED | 2397 PFLAG2_TEXT_DIRECTION_RESOLVED | 2398 PFLAG2_TEXT_ALIGNMENT_RESOLVED | 2399 PFLAG2_PADDING_RESOLVED | 2400 PFLAG2_DRAWABLE_RESOLVED; 2401 2402 // There are a couple of flags left in mPrivateFlags2 2403 2404 /* End of masks for mPrivateFlags2 */ 2405 2406 /** 2407 * Masks for mPrivateFlags3, as generated by dumpFlags(): 2408 * 2409 * |-------|-------|-------|-------| 2410 * 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM 2411 * 1 PFLAG3_VIEW_IS_ANIMATING_ALPHA 2412 * 1 PFLAG3_IS_LAID_OUT 2413 * 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT 2414 * 1 PFLAG3_CALLED_SUPER 2415 * 1 PFLAG3_APPLYING_INSETS 2416 * 1 PFLAG3_FITTING_SYSTEM_WINDOWS 2417 * 1 PFLAG3_NESTED_SCROLLING_ENABLED 2418 * 1 PFLAG3_SCROLL_INDICATOR_TOP 2419 * 1 PFLAG3_SCROLL_INDICATOR_BOTTOM 2420 * 1 PFLAG3_SCROLL_INDICATOR_LEFT 2421 * 1 PFLAG3_SCROLL_INDICATOR_RIGHT 2422 * 1 PFLAG3_SCROLL_INDICATOR_START 2423 * 1 PFLAG3_SCROLL_INDICATOR_END 2424 * 1 PFLAG3_ASSIST_BLOCKED 2425 * 1111111 PFLAG3_POINTER_ICON_MASK 2426 * 1 PFLAG3_PARTIAL_LAYOUT_REQUESTED 2427 * 1 PFLAG3_LAYOUT_PARAMS_CHANGED 2428 * |-------|-------|-------|-------| 2429 */ 2430 2431 /** 2432 * Flag indicating that view has a transform animation set on it. This is used to track whether 2433 * an animation is cleared between successive frames, in order to tell the associated 2434 * DisplayList to clear its animation matrix. 2435 */ 2436 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1; 2437 2438 /** 2439 * Flag indicating that view has an alpha animation set on it. This is used to track whether an 2440 * animation is cleared between successive frames, in order to tell the associated 2441 * DisplayList to restore its alpha value. 2442 */ 2443 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2; 2444 2445 /** 2446 * Flag indicating that the view has been through at least one layout since it 2447 * was last attached to a window. 2448 */ 2449 static final int PFLAG3_IS_LAID_OUT = 0x4; 2450 2451 /** 2452 * Flag indicating that a call to measure() was skipped and should be done 2453 * instead when layout() is invoked. 2454 */ 2455 static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8; 2456 2457 /** 2458 * Flag indicating that an overridden method correctly called down to 2459 * the superclass implementation as required by the API spec. 2460 */ 2461 static final int PFLAG3_CALLED_SUPER = 0x10; 2462 2463 /** 2464 * Flag indicating that we're in the process of applying window insets. 2465 */ 2466 static final int PFLAG3_APPLYING_INSETS = 0x20; 2467 2468 /** 2469 * Flag indicating that we're in the process of fitting system windows using the old method. 2470 */ 2471 static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40; 2472 2473 /** 2474 * Flag indicating that nested scrolling is enabled for this view. 2475 * The view will optionally cooperate with views up its parent chain to allow for 2476 * integrated nested scrolling along the same axis. 2477 */ 2478 static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80; 2479 2480 /** 2481 * Flag indicating that the bottom scroll indicator should be displayed 2482 * when this view can scroll up. 2483 */ 2484 static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100; 2485 2486 /** 2487 * Flag indicating that the bottom scroll indicator should be displayed 2488 * when this view can scroll down. 2489 */ 2490 static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200; 2491 2492 /** 2493 * Flag indicating that the left scroll indicator should be displayed 2494 * when this view can scroll left. 2495 */ 2496 static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400; 2497 2498 /** 2499 * Flag indicating that the right scroll indicator should be displayed 2500 * when this view can scroll right. 2501 */ 2502 static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800; 2503 2504 /** 2505 * Flag indicating that the start scroll indicator should be displayed 2506 * when this view can scroll in the start direction. 2507 */ 2508 static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000; 2509 2510 /** 2511 * Flag indicating that the end scroll indicator should be displayed 2512 * when this view can scroll in the end direction. 2513 */ 2514 static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000; 2515 2516 2517 /* End of masks for mPrivateFlags3 */ 2518 2519 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED; 2520 2521 static final int SCROLL_INDICATORS_NONE = 0x0000; 2522 2523 /** 2524 * Mask for use with setFlags indicating bits used for indicating which 2525 * scroll indicators are enabled. 2526 */ 2527 static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP 2528 | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT 2529 | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START 2530 | PFLAG3_SCROLL_INDICATOR_END; 2531 2532 /** 2533 * Left-shift required to translate between public scroll indicator flags 2534 * and internal PFLAGS3 flags. When used as a right-shift, translates 2535 * PFLAGS3 flags to public flags. 2536 */ 2537 static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8; 2538 2539 /** @hide */ 2540 @Retention(RetentionPolicy.SOURCE) 2541 @IntDef(flag = true, 2542 value = { 2543 SCROLL_INDICATOR_TOP, 2544 SCROLL_INDICATOR_BOTTOM, 2545 SCROLL_INDICATOR_LEFT, 2546 SCROLL_INDICATOR_RIGHT, 2547 SCROLL_INDICATOR_START, 2548 SCROLL_INDICATOR_END, 2549 }) 2550 public @interface ScrollIndicators {} 2551 2552 /** 2553 * Scroll indicator direction for the top edge of the view. 2554 * 2555 * @see #setScrollIndicators(int) 2556 * @see #setScrollIndicators(int, int) 2557 * @see #getScrollIndicators() 2558 */ 2559 public static final int SCROLL_INDICATOR_TOP = 2560 PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2561 2562 /** 2563 * Scroll indicator direction for the bottom edge of the view. 2564 * 2565 * @see #setScrollIndicators(int) 2566 * @see #setScrollIndicators(int, int) 2567 * @see #getScrollIndicators() 2568 */ 2569 public static final int SCROLL_INDICATOR_BOTTOM = 2570 PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2571 2572 /** 2573 * Scroll indicator direction for the left edge of the view. 2574 * 2575 * @see #setScrollIndicators(int) 2576 * @see #setScrollIndicators(int, int) 2577 * @see #getScrollIndicators() 2578 */ 2579 public static final int SCROLL_INDICATOR_LEFT = 2580 PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2581 2582 /** 2583 * Scroll indicator direction for the right edge of the view. 2584 * 2585 * @see #setScrollIndicators(int) 2586 * @see #setScrollIndicators(int, int) 2587 * @see #getScrollIndicators() 2588 */ 2589 public static final int SCROLL_INDICATOR_RIGHT = 2590 PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2591 2592 /** 2593 * Scroll indicator direction for the starting edge of the view. 2594 * <p> 2595 * Resolved according to the view's layout direction, see 2596 * {@link #getLayoutDirection()} for more information. 2597 * 2598 * @see #setScrollIndicators(int) 2599 * @see #setScrollIndicators(int, int) 2600 * @see #getScrollIndicators() 2601 */ 2602 public static final int SCROLL_INDICATOR_START = 2603 PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2604 2605 /** 2606 * Scroll indicator direction for the ending edge of the view. 2607 * <p> 2608 * Resolved according to the view's layout direction, see 2609 * {@link #getLayoutDirection()} for more information. 2610 * 2611 * @see #setScrollIndicators(int) 2612 * @see #setScrollIndicators(int, int) 2613 * @see #getScrollIndicators() 2614 */ 2615 public static final int SCROLL_INDICATOR_END = 2616 PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 2617 2618 /** 2619 * <p>Indicates that we are allowing {@link ViewStructure} to traverse 2620 * into this view.<p> 2621 */ 2622 static final int PFLAG3_ASSIST_BLOCKED = 0x4000; 2623 2624 /** 2625 * The mask for use with private flags indicating bits used for pointer icon shapes. 2626 */ 2627 static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000; 2628 2629 /** 2630 * Left-shift used for pointer icon shape values in private flags. 2631 */ 2632 static final int PFLAG3_POINTER_ICON_LSHIFT = 15; 2633 2634 /** 2635 * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}. 2636 */ 2637 private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT; 2638 2639 /** 2640 * Value indicating {@link PointerIcon.STYLE_NULL}. 2641 */ 2642 private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT; 2643 2644 /** 2645 * Value incicating {@link PointerIcon.STYLE_CUSTOM}. 2646 */ 2647 private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT; 2648 2649 /** 2650 * The base value for other pointer icon shapes. 2651 */ 2652 private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT; 2653 2654 /** 2655 * Flag indicating that this view has requested a partial layout and 2656 * is added to the AttachInfo's list of views that need a partial layout 2657 * request handled on the next traversal. 2658 */ 2659 static final int PFLAG3_PARTIAL_LAYOUT_REQUESTED = 0x800000; 2660 2661 /** 2662 * Flag indicating that this view's LayoutParams have been explicitly changed 2663 * since the last layout pass. 2664 */ 2665 static final int PFLAG3_LAYOUT_PARAMS_CHANGED = 0x1000000; 2666 2667 /** 2668 * Always allow a user to over-scroll this view, provided it is a 2669 * view that can scroll. 2670 * 2671 * @see #getOverScrollMode() 2672 * @see #setOverScrollMode(int) 2673 */ 2674 public static final int OVER_SCROLL_ALWAYS = 0; 2675 2676 /** 2677 * Allow a user to over-scroll this view only if the content is large 2678 * enough to meaningfully scroll, provided it is a view that can scroll. 2679 * 2680 * @see #getOverScrollMode() 2681 * @see #setOverScrollMode(int) 2682 */ 2683 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1; 2684 2685 /** 2686 * Never allow a user to over-scroll this view. 2687 * 2688 * @see #getOverScrollMode() 2689 * @see #setOverScrollMode(int) 2690 */ 2691 public static final int OVER_SCROLL_NEVER = 2; 2692 2693 /** 2694 * Special constant for {@link #setSystemUiVisibility(int)}: View has 2695 * requested the system UI (status bar) to be visible (the default). 2696 * 2697 * @see #setSystemUiVisibility(int) 2698 */ 2699 public static final int SYSTEM_UI_FLAG_VISIBLE = 0; 2700 2701 /** 2702 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the 2703 * system UI to enter an unobtrusive "low profile" mode. 2704 * 2705 * <p>This is for use in games, book readers, video players, or any other 2706 * "immersive" application where the usual system chrome is deemed too distracting. 2707 * 2708 * <p>In low profile mode, the status bar and/or navigation icons may dim. 2709 * 2710 * @see #setSystemUiVisibility(int) 2711 */ 2712 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001; 2713 2714 /** 2715 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the 2716 * system navigation be temporarily hidden. 2717 * 2718 * <p>This is an even less obtrusive state than that called for by 2719 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls 2720 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause 2721 * those to disappear. This is useful (in conjunction with the 2722 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 2723 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN} 2724 * window flags) for displaying content using every last pixel on the display. 2725 * 2726 * <p>There is a limitation: because navigation controls are so important, the least user 2727 * interaction will cause them to reappear immediately. When this happens, both 2728 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically, 2729 * so that both elements reappear at the same time. 2730 * 2731 * @see #setSystemUiVisibility(int) 2732 */ 2733 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002; 2734 2735 /** 2736 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go 2737 * into the normal fullscreen mode so that its content can take over the screen 2738 * while still allowing the user to interact with the application. 2739 * 2740 * <p>This has the same visual effect as 2741 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN 2742 * WindowManager.LayoutParams.FLAG_FULLSCREEN}, 2743 * meaning that non-critical screen decorations (such as the status bar) will be 2744 * hidden while the user is in the View's window, focusing the experience on 2745 * that content. Unlike the window flag, if you are using ActionBar in 2746 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2747 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also 2748 * hide the action bar. 2749 * 2750 * <p>This approach to going fullscreen is best used over the window flag when 2751 * it is a transient state -- that is, the application does this at certain 2752 * points in its user interaction where it wants to allow the user to focus 2753 * on content, but not as a continuous state. For situations where the application 2754 * would like to simply stay full screen the entire time (such as a game that 2755 * wants to take over the screen), the 2756 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag} 2757 * is usually a better approach. The state set here will be removed by the system 2758 * in various situations (such as the user moving to another application) like 2759 * the other system UI states. 2760 * 2761 * <p>When using this flag, the application should provide some easy facility 2762 * for the user to go out of it. A common example would be in an e-book 2763 * reader, where tapping on the screen brings back whatever screen and UI 2764 * decorations that had been hidden while the user was immersed in reading 2765 * the book. 2766 * 2767 * @see #setSystemUiVisibility(int) 2768 */ 2769 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004; 2770 2771 /** 2772 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout 2773 * flags, we would like a stable view of the content insets given to 2774 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there 2775 * will always represent the worst case that the application can expect 2776 * as a continuous state. In the stock Android UI this is the space for 2777 * the system bar, nav bar, and status bar, but not more transient elements 2778 * such as an input method. 2779 * 2780 * The stable layout your UI sees is based on the system UI modes you can 2781 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 2782 * then you will get a stable layout for changes of the 2783 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify 2784 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and 2785 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition 2786 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} 2787 * with a stable layout. (Note that you should avoid using 2788 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.) 2789 * 2790 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN} 2791 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}), 2792 * then a hidden status bar will be considered a "stable" state for purposes 2793 * here. This allows your UI to continually hide the status bar, while still 2794 * using the system UI flags to hide the action bar while still retaining 2795 * a stable layout. Note that changing the window fullscreen flag will never 2796 * provide a stable layout for a clean transition. 2797 * 2798 * <p>If you are using ActionBar in 2799 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY 2800 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the 2801 * insets it adds to those given to the application. 2802 */ 2803 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100; 2804 2805 /** 2806 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2807 * to be laid out as if it has requested 2808 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This 2809 * allows it to avoid artifacts when switching in and out of that mode, at 2810 * the expense that some of its user interface may be covered by screen 2811 * decorations when they are shown. You can perform layout of your inner 2812 * UI elements to account for the navigation system UI through the 2813 * {@link #fitSystemWindows(Rect)} method. 2814 */ 2815 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200; 2816 2817 /** 2818 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window 2819 * to be laid out as if it has requested 2820 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This 2821 * allows it to avoid artifacts when switching in and out of that mode, at 2822 * the expense that some of its user interface may be covered by screen 2823 * decorations when they are shown. You can perform layout of your inner 2824 * UI elements to account for non-fullscreen system UI through the 2825 * {@link #fitSystemWindows(Rect)} method. 2826 */ 2827 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400; 2828 2829 /** 2830 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2831 * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is 2832 * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any 2833 * user interaction. 2834 * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only 2835 * has an effect when used in combination with that flag.</p> 2836 */ 2837 public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800; 2838 2839 /** 2840 * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when 2841 * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation 2842 * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive 2843 * experience while also hiding the system bars. If this flag is not set, 2844 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user 2845 * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system 2846 * if the user swipes from the top of the screen. 2847 * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with 2848 * system gestures, such as swiping from the top of the screen. These transient system bars 2849 * will overlay app’s content, may have some degree of transparency, and will automatically 2850 * hide after a short timeout. 2851 * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and 2852 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination 2853 * with one or both of those flags.</p> 2854 */ 2855 public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000; 2856 2857 /** 2858 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that 2859 * is compatible with light status bar backgrounds. 2860 * 2861 * <p>For this to take effect, the window must request 2862 * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 2863 * FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not 2864 * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS 2865 * FLAG_TRANSLUCENT_STATUS}. 2866 * 2867 * @see android.R.attr#windowLightStatusBar 2868 */ 2869 public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000; 2870 2871 /** 2872 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead. 2873 */ 2874 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE; 2875 2876 /** 2877 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead. 2878 */ 2879 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE; 2880 2881 /** 2882 * @hide 2883 * 2884 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2885 * out of the public fields to keep the undefined bits out of the developer's way. 2886 * 2887 * Flag to make the status bar not expandable. Unless you also 2888 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show. 2889 */ 2890 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000; 2891 2892 /** 2893 * @hide 2894 * 2895 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2896 * out of the public fields to keep the undefined bits out of the developer's way. 2897 * 2898 * Flag to hide notification icons and scrolling ticker text. 2899 */ 2900 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000; 2901 2902 /** 2903 * @hide 2904 * 2905 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2906 * out of the public fields to keep the undefined bits out of the developer's way. 2907 * 2908 * Flag to disable incoming notification alerts. This will not block 2909 * icons, but it will block sound, vibrating and other visual or aural notifications. 2910 */ 2911 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000; 2912 2913 /** 2914 * @hide 2915 * 2916 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2917 * out of the public fields to keep the undefined bits out of the developer's way. 2918 * 2919 * Flag to hide only the scrolling ticker. Note that 2920 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies 2921 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}. 2922 */ 2923 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000; 2924 2925 /** 2926 * @hide 2927 * 2928 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2929 * out of the public fields to keep the undefined bits out of the developer's way. 2930 * 2931 * Flag to hide the center system info area. 2932 */ 2933 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000; 2934 2935 /** 2936 * @hide 2937 * 2938 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2939 * out of the public fields to keep the undefined bits out of the developer's way. 2940 * 2941 * Flag to hide only the home button. Don't use this 2942 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2943 */ 2944 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000; 2945 2946 /** 2947 * @hide 2948 * 2949 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2950 * out of the public fields to keep the undefined bits out of the developer's way. 2951 * 2952 * Flag to hide only the back button. Don't use this 2953 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2954 */ 2955 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 2956 2957 /** 2958 * @hide 2959 * 2960 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2961 * out of the public fields to keep the undefined bits out of the developer's way. 2962 * 2963 * Flag to hide only the clock. You might use this if your activity has 2964 * its own clock making the status bar's clock redundant. 2965 */ 2966 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000; 2967 2968 /** 2969 * @hide 2970 * 2971 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2972 * out of the public fields to keep the undefined bits out of the developer's way. 2973 * 2974 * Flag to hide only the recent apps button. Don't use this 2975 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2976 */ 2977 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000; 2978 2979 /** 2980 * @hide 2981 * 2982 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2983 * out of the public fields to keep the undefined bits out of the developer's way. 2984 * 2985 * Flag to disable the global search gesture. Don't use this 2986 * unless you're a special part of the system UI (i.e., setup wizard, keyguard). 2987 */ 2988 public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000; 2989 2990 /** 2991 * @hide 2992 * 2993 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 2994 * out of the public fields to keep the undefined bits out of the developer's way. 2995 * 2996 * Flag to specify that the status bar is displayed in transient mode. 2997 */ 2998 public static final int STATUS_BAR_TRANSIENT = 0x04000000; 2999 3000 /** 3001 * @hide 3002 * 3003 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3004 * out of the public fields to keep the undefined bits out of the developer's way. 3005 * 3006 * Flag to specify that the navigation bar is displayed in transient mode. 3007 */ 3008 public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000; 3009 3010 /** 3011 * @hide 3012 * 3013 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3014 * out of the public fields to keep the undefined bits out of the developer's way. 3015 * 3016 * Flag to specify that the hidden status bar would like to be shown. 3017 */ 3018 public static final int STATUS_BAR_UNHIDE = 0x10000000; 3019 3020 /** 3021 * @hide 3022 * 3023 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3024 * out of the public fields to keep the undefined bits out of the developer's way. 3025 * 3026 * Flag to specify that the hidden navigation bar would like to be shown. 3027 */ 3028 public static final int NAVIGATION_BAR_UNHIDE = 0x20000000; 3029 3030 /** 3031 * @hide 3032 * 3033 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3034 * out of the public fields to keep the undefined bits out of the developer's way. 3035 * 3036 * Flag to specify that the status bar is displayed in translucent mode. 3037 */ 3038 public static final int STATUS_BAR_TRANSLUCENT = 0x40000000; 3039 3040 /** 3041 * @hide 3042 * 3043 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked 3044 * out of the public fields to keep the undefined bits out of the developer's way. 3045 * 3046 * Flag to specify that the navigation bar is displayed in translucent mode. 3047 */ 3048 public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000; 3049 3050 /** 3051 * @hide 3052 * 3053 * Whether Recents is visible or not. 3054 */ 3055 public static final int RECENT_APPS_VISIBLE = 0x00004000; 3056 3057 /** 3058 * @hide 3059 * 3060 * Makes navigation bar transparent (but not the status bar). 3061 */ 3062 public static final int NAVIGATION_BAR_TRANSPARENT = 0x00008000; 3063 3064 /** 3065 * @hide 3066 * 3067 * Makes status bar transparent (but not the navigation bar). 3068 */ 3069 public static final int STATUS_BAR_TRANSPARENT = 0x0000008; 3070 3071 /** 3072 * @hide 3073 * 3074 * Makes both status bar and navigation bar transparent. 3075 */ 3076 public static final int SYSTEM_UI_TRANSPARENT = NAVIGATION_BAR_TRANSPARENT 3077 | STATUS_BAR_TRANSPARENT; 3078 3079 /** 3080 * @hide 3081 */ 3082 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FF7; 3083 3084 /** 3085 * These are the system UI flags that can be cleared by events outside 3086 * of an application. Currently this is just the ability to tap on the 3087 * screen while hiding the navigation bar to have it return. 3088 * @hide 3089 */ 3090 public static final int SYSTEM_UI_CLEARABLE_FLAGS = 3091 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION 3092 | SYSTEM_UI_FLAG_FULLSCREEN; 3093 3094 /** 3095 * Flags that can impact the layout in relation to system UI. 3096 */ 3097 public static final int SYSTEM_UI_LAYOUT_FLAGS = 3098 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 3099 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 3100 3101 /** @hide */ 3102 @IntDef(flag = true, 3103 value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION }) 3104 @Retention(RetentionPolicy.SOURCE) 3105 public @interface FindViewFlags {} 3106 3107 /** 3108 * Find views that render the specified text. 3109 * 3110 * @see #findViewsWithText(ArrayList, CharSequence, int) 3111 */ 3112 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001; 3113 3114 /** 3115 * Find find views that contain the specified content description. 3116 * 3117 * @see #findViewsWithText(ArrayList, CharSequence, int) 3118 */ 3119 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002; 3120 3121 /** 3122 * Find views that contain {@link AccessibilityNodeProvider}. Such 3123 * a View is a root of virtual view hierarchy and may contain the searched 3124 * text. If this flag is set Views with providers are automatically 3125 * added and it is a responsibility of the client to call the APIs of 3126 * the provider to determine whether the virtual tree rooted at this View 3127 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s 3128 * representing the virtual views with this text. 3129 * 3130 * @see #findViewsWithText(ArrayList, CharSequence, int) 3131 * 3132 * @hide 3133 */ 3134 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004; 3135 3136 /** 3137 * The undefined cursor position. 3138 * 3139 * @hide 3140 */ 3141 public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1; 3142 3143 /** 3144 * Indicates that the screen has changed state and is now off. 3145 * 3146 * @see #onScreenStateChanged(int) 3147 */ 3148 public static final int SCREEN_STATE_OFF = 0x0; 3149 3150 /** 3151 * Indicates that the screen has changed state and is now on. 3152 * 3153 * @see #onScreenStateChanged(int) 3154 */ 3155 public static final int SCREEN_STATE_ON = 0x1; 3156 3157 /** 3158 * Indicates no axis of view scrolling. 3159 */ 3160 public static final int SCROLL_AXIS_NONE = 0; 3161 3162 /** 3163 * Indicates scrolling along the horizontal axis. 3164 */ 3165 public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0; 3166 3167 /** 3168 * Indicates scrolling along the vertical axis. 3169 */ 3170 public static final int SCROLL_AXIS_VERTICAL = 1 << 1; 3171 3172 /** 3173 * Controls the over-scroll mode for this view. 3174 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)}, 3175 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}, 3176 * and {@link #OVER_SCROLL_NEVER}. 3177 */ 3178 private int mOverScrollMode; 3179 3180 /** 3181 * The parent this view is attached to. 3182 * {@hide} 3183 * 3184 * @see #getParent() 3185 */ 3186 protected ViewParent mParent; 3187 3188 /** 3189 * {@hide} 3190 */ 3191 AttachInfo mAttachInfo; 3192 3193 /** 3194 * {@hide} 3195 */ 3196 @ViewDebug.ExportedProperty(flagMapping = { 3197 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT, 3198 name = "FORCE_LAYOUT"), 3199 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED, 3200 name = "LAYOUT_REQUIRED"), 3201 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID, 3202 name = "DRAWING_CACHE_INVALID", outputIf = false), 3203 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true), 3204 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false), 3205 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), 3206 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY") 3207 }, formatToHexString = true) 3208 int mPrivateFlags; 3209 int mPrivateFlags2; 3210 int mPrivateFlags3; 3211 3212 /** 3213 * This view's request for the visibility of the status bar. 3214 * @hide 3215 */ 3216 @ViewDebug.ExportedProperty(flagMapping = { 3217 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, 3218 equals = SYSTEM_UI_FLAG_LOW_PROFILE, 3219 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), 3220 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3221 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, 3222 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), 3223 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, 3224 equals = SYSTEM_UI_FLAG_VISIBLE, 3225 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) 3226 }, formatToHexString = true) 3227 int mSystemUiVisibility; 3228 3229 /** 3230 * Reference count for transient state. 3231 * @see #setHasTransientState(boolean) 3232 */ 3233 int mTransientStateCount = 0; 3234 3235 /** 3236 * Count of how many windows this view has been attached to. 3237 */ 3238 int mWindowAttachCount; 3239 3240 /** 3241 * The layout parameters associated with this view and used by the parent 3242 * {@link android.view.ViewGroup} to determine how this view should be 3243 * laid out. 3244 * {@hide} 3245 */ 3246 protected ViewGroup.LayoutParams mLayoutParams; 3247 3248 /** 3249 * The view flags hold various views states. 3250 * {@hide} 3251 */ 3252 @ViewDebug.ExportedProperty(formatToHexString = true) 3253 int mViewFlags; 3254 3255 static class TransformationInfo { 3256 /** 3257 * The transform matrix for the View. This transform is calculated internally 3258 * based on the translation, rotation, and scale properties. 3259 * 3260 * Do *not* use this variable directly; instead call getMatrix(), which will 3261 * load the value from the View's RenderNode. 3262 */ 3263 private final Matrix mMatrix = new Matrix(); 3264 3265 /** 3266 * The inverse transform matrix for the View. This transform is calculated 3267 * internally based on the translation, rotation, and scale properties. 3268 * 3269 * Do *not* use this variable directly; instead call getInverseMatrix(), 3270 * which will load the value from the View's RenderNode. 3271 */ 3272 private Matrix mInverseMatrix; 3273 3274 /** 3275 * The opacity of the View. This is a value from 0 to 1, where 0 means 3276 * completely transparent and 1 means completely opaque. 3277 */ 3278 @ViewDebug.ExportedProperty 3279 float mAlpha = 1f; 3280 3281 /** 3282 * The opacity of the view as manipulated by the Fade transition. This is a hidden 3283 * property only used by transitions, which is composited with the other alpha 3284 * values to calculate the final visual alpha value. 3285 */ 3286 float mTransitionAlpha = 1f; 3287 } 3288 3289 TransformationInfo mTransformationInfo; 3290 3291 /** 3292 * Current clip bounds. to which all drawing of this view are constrained. 3293 */ 3294 Rect mClipBounds = null; 3295 3296 private boolean mLastIsOpaque; 3297 3298 /** 3299 * The distance in pixels from the left edge of this view's parent 3300 * to the left edge of this view. 3301 * {@hide} 3302 */ 3303 @ViewDebug.ExportedProperty(category = "layout") 3304 protected int mLeft; 3305 /** 3306 * The distance in pixels from the left edge of this view's parent 3307 * to the right edge of this view. 3308 * {@hide} 3309 */ 3310 @ViewDebug.ExportedProperty(category = "layout") 3311 protected int mRight; 3312 /** 3313 * The distance in pixels from the top edge of this view's parent 3314 * to the top edge of this view. 3315 * {@hide} 3316 */ 3317 @ViewDebug.ExportedProperty(category = "layout") 3318 protected int mTop; 3319 /** 3320 * The distance in pixels from the top edge of this view's parent 3321 * to the bottom edge of this view. 3322 * {@hide} 3323 */ 3324 @ViewDebug.ExportedProperty(category = "layout") 3325 protected int mBottom; 3326 3327 /** 3328 * The offset, in pixels, by which the content of this view is scrolled 3329 * horizontally. 3330 * {@hide} 3331 */ 3332 @ViewDebug.ExportedProperty(category = "scrolling") 3333 protected int mScrollX; 3334 /** 3335 * The offset, in pixels, by which the content of this view is scrolled 3336 * vertically. 3337 * {@hide} 3338 */ 3339 @ViewDebug.ExportedProperty(category = "scrolling") 3340 protected int mScrollY; 3341 3342 /** 3343 * The left padding in pixels, that is the distance in pixels between the 3344 * left edge of this view and the left edge of its content. 3345 * {@hide} 3346 */ 3347 @ViewDebug.ExportedProperty(category = "padding") 3348 protected int mPaddingLeft = 0; 3349 /** 3350 * The right padding in pixels, that is the distance in pixels between the 3351 * right edge of this view and the right edge of its content. 3352 * {@hide} 3353 */ 3354 @ViewDebug.ExportedProperty(category = "padding") 3355 protected int mPaddingRight = 0; 3356 /** 3357 * The top padding in pixels, that is the distance in pixels between the 3358 * top edge of this view and the top edge of its content. 3359 * {@hide} 3360 */ 3361 @ViewDebug.ExportedProperty(category = "padding") 3362 protected int mPaddingTop; 3363 /** 3364 * The bottom padding in pixels, that is the distance in pixels between the 3365 * bottom edge of this view and the bottom edge of its content. 3366 * {@hide} 3367 */ 3368 @ViewDebug.ExportedProperty(category = "padding") 3369 protected int mPaddingBottom; 3370 3371 /** 3372 * The layout insets in pixels, that is the distance in pixels between the 3373 * visible edges of this view its bounds. 3374 */ 3375 private Insets mLayoutInsets; 3376 3377 /** 3378 * Briefly describes the view and is primarily used for accessibility support. 3379 */ 3380 private CharSequence mContentDescription; 3381 3382 /** 3383 * Specifies the id of a view for which this view serves as a label for 3384 * accessibility purposes. 3385 */ 3386 private int mLabelForId = View.NO_ID; 3387 3388 /** 3389 * Predicate for matching labeled view id with its label for 3390 * accessibility purposes. 3391 */ 3392 private MatchLabelForPredicate mMatchLabelForPredicate; 3393 3394 /** 3395 * Specifies a view before which this one is visited in accessibility traversal. 3396 */ 3397 private int mAccessibilityTraversalBeforeId = NO_ID; 3398 3399 /** 3400 * Specifies a view after which this one is visited in accessibility traversal. 3401 */ 3402 private int mAccessibilityTraversalAfterId = NO_ID; 3403 3404 /** 3405 * Predicate for matching a view by its id. 3406 */ 3407 private MatchIdPredicate mMatchIdPredicate; 3408 3409 /** 3410 * Cache the paddingRight set by the user to append to the scrollbar's size. 3411 * 3412 * @hide 3413 */ 3414 @ViewDebug.ExportedProperty(category = "padding") 3415 protected int mUserPaddingRight; 3416 3417 /** 3418 * Cache the paddingBottom set by the user to append to the scrollbar's size. 3419 * 3420 * @hide 3421 */ 3422 @ViewDebug.ExportedProperty(category = "padding") 3423 protected int mUserPaddingBottom; 3424 3425 /** 3426 * Cache the paddingLeft set by the user to append to the scrollbar's size. 3427 * 3428 * @hide 3429 */ 3430 @ViewDebug.ExportedProperty(category = "padding") 3431 protected int mUserPaddingLeft; 3432 3433 /** 3434 * Cache the paddingStart set by the user to append to the scrollbar's size. 3435 * 3436 */ 3437 @ViewDebug.ExportedProperty(category = "padding") 3438 int mUserPaddingStart; 3439 3440 /** 3441 * Cache the paddingEnd set by the user to append to the scrollbar's size. 3442 * 3443 */ 3444 @ViewDebug.ExportedProperty(category = "padding") 3445 int mUserPaddingEnd; 3446 3447 /** 3448 * Cache initial left padding. 3449 * 3450 * @hide 3451 */ 3452 int mUserPaddingLeftInitial; 3453 3454 /** 3455 * Cache initial right padding. 3456 * 3457 * @hide 3458 */ 3459 int mUserPaddingRightInitial; 3460 3461 /** 3462 * Default undefined padding 3463 */ 3464 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; 3465 3466 /** 3467 * Cache if a left padding has been defined 3468 */ 3469 private boolean mLeftPaddingDefined = false; 3470 3471 /** 3472 * Cache if a right padding has been defined 3473 */ 3474 private boolean mRightPaddingDefined = false; 3475 3476 /** 3477 * @hide 3478 */ 3479 int mOldWidthMeasureSpec = Integer.MIN_VALUE; 3480 /** 3481 * @hide 3482 */ 3483 int mOldHeightMeasureSpec = Integer.MIN_VALUE; 3484 3485 private LongSparseLongArray mMeasureCache; 3486 3487 @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_") 3488 private Drawable mBackground; 3489 private TintInfo mBackgroundTint; 3490 3491 @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_") 3492 private ForegroundInfo mForegroundInfo; 3493 3494 private Drawable mScrollIndicatorDrawable; 3495 3496 /** 3497 * RenderNode used for backgrounds. 3498 * <p> 3499 * When non-null and valid, this is expected to contain an up-to-date copy 3500 * of the background drawable. It is cleared on temporary detach, and reset 3501 * on cleanup. 3502 */ 3503 private RenderNode mBackgroundRenderNode; 3504 3505 private int mBackgroundResource; 3506 private boolean mBackgroundSizeChanged; 3507 3508 private String mTransitionName; 3509 3510 static class TintInfo { 3511 ColorStateList mTintList; 3512 PorterDuff.Mode mTintMode; 3513 boolean mHasTintMode; 3514 boolean mHasTintList; 3515 } 3516 3517 private static class ForegroundInfo { 3518 private Drawable mDrawable; 3519 private TintInfo mTintInfo; 3520 private int mGravity = Gravity.FILL; 3521 private boolean mInsidePadding = true; 3522 private boolean mBoundsChanged = true; 3523 private final Rect mSelfBounds = new Rect(); 3524 private final Rect mOverlayBounds = new Rect(); 3525 } 3526 3527 static class ListenerInfo { 3528 /** 3529 * Listener used to dispatch focus change events. 3530 * This field should be made private, so it is hidden from the SDK. 3531 * {@hide} 3532 */ 3533 protected OnFocusChangeListener mOnFocusChangeListener; 3534 3535 /** 3536 * Listeners for layout change events. 3537 */ 3538 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners; 3539 3540 protected OnScrollChangeListener mOnScrollChangeListener; 3541 3542 /** 3543 * Listeners for attach events. 3544 */ 3545 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners; 3546 3547 /** 3548 * Listener used to dispatch click events. 3549 * This field should be made private, so it is hidden from the SDK. 3550 * {@hide} 3551 */ 3552 public OnClickListener mOnClickListener; 3553 3554 /** 3555 * Listener used to dispatch long click events. 3556 * This field should be made private, so it is hidden from the SDK. 3557 * {@hide} 3558 */ 3559 protected OnLongClickListener mOnLongClickListener; 3560 3561 /** 3562 * Listener used to dispatch context click events. This field should be made private, so it 3563 * is hidden from the SDK. 3564 * {@hide} 3565 */ 3566 protected OnContextClickListener mOnContextClickListener; 3567 3568 /** 3569 * Listener used to build the context menu. 3570 * This field should be made private, so it is hidden from the SDK. 3571 * {@hide} 3572 */ 3573 protected OnCreateContextMenuListener mOnCreateContextMenuListener; 3574 3575 private OnKeyListener mOnKeyListener; 3576 3577 private OnTouchListener mOnTouchListener; 3578 3579 private OnHoverListener mOnHoverListener; 3580 3581 private OnGenericMotionListener mOnGenericMotionListener; 3582 3583 private OnDragListener mOnDragListener; 3584 3585 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener; 3586 3587 OnApplyWindowInsetsListener mOnApplyWindowInsetsListener; 3588 } 3589 3590 ListenerInfo mListenerInfo; 3591 3592 // Temporary values used to hold (x,y) coordinates when delegating from the 3593 // two-arg performLongClick() method to the legacy no-arg version. 3594 private float mLongClickX = Float.NaN; 3595 private float mLongClickY = Float.NaN; 3596 3597 /** 3598 * The application environment this view lives in. 3599 * This field should be made private, so it is hidden from the SDK. 3600 * {@hide} 3601 */ 3602 @ViewDebug.ExportedProperty(deepExport = true) 3603 protected Context mContext; 3604 3605 private final Resources mResources; 3606 3607 private ScrollabilityCache mScrollCache; 3608 3609 private int[] mDrawableState = null; 3610 3611 ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND; 3612 3613 /** 3614 * Animator that automatically runs based on state changes. 3615 */ 3616 private StateListAnimator mStateListAnimator; 3617 3618 /** 3619 * When this view has focus and the next focus is {@link #FOCUS_LEFT}, 3620 * the user may specify which view to go to next. 3621 */ 3622 private int mNextFocusLeftId = View.NO_ID; 3623 3624 /** 3625 * When this view has focus and the next focus is {@link #FOCUS_RIGHT}, 3626 * the user may specify which view to go to next. 3627 */ 3628 private int mNextFocusRightId = View.NO_ID; 3629 3630 /** 3631 * When this view has focus and the next focus is {@link #FOCUS_UP}, 3632 * the user may specify which view to go to next. 3633 */ 3634 private int mNextFocusUpId = View.NO_ID; 3635 3636 /** 3637 * When this view has focus and the next focus is {@link #FOCUS_DOWN}, 3638 * the user may specify which view to go to next. 3639 */ 3640 private int mNextFocusDownId = View.NO_ID; 3641 3642 /** 3643 * When this view has focus and the next focus is {@link #FOCUS_FORWARD}, 3644 * the user may specify which view to go to next. 3645 */ 3646 int mNextFocusForwardId = View.NO_ID; 3647 3648 private CheckForLongPress mPendingCheckForLongPress; 3649 private CheckForTap mPendingCheckForTap = null; 3650 private PerformClick mPerformClick; 3651 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent; 3652 3653 private UnsetPressedState mUnsetPressedState; 3654 3655 /** 3656 * Whether the long press's action has been invoked. The tap's action is invoked on the 3657 * up event while a long press is invoked as soon as the long press duration is reached, so 3658 * a long press could be performed before the tap is checked, in which case the tap's action 3659 * should not be invoked. 3660 */ 3661 private boolean mHasPerformedLongPress; 3662 3663 /** 3664 * Whether a context click button is currently pressed down. This is true when the stylus is 3665 * touching the screen and the primary button has been pressed, or if a mouse's right button is 3666 * pressed. This is false once the button is released or if the stylus has been lifted. 3667 */ 3668 private boolean mInContextButtonPress; 3669 3670 /** 3671 * Whether the next up event should be ignored for the purposes of gesture recognition. This is 3672 * true after a stylus button press has occured, when the next up event should not be recognized 3673 * as a tap. 3674 */ 3675 private boolean mIgnoreNextUpEvent; 3676 3677 /** 3678 * The minimum height of the view. We'll try our best to have the height 3679 * of this view to at least this amount. 3680 */ 3681 @ViewDebug.ExportedProperty(category = "measurement") 3682 private int mMinHeight; 3683 3684 /** 3685 * The minimum width of the view. We'll try our best to have the width 3686 * of this view to at least this amount. 3687 */ 3688 @ViewDebug.ExportedProperty(category = "measurement") 3689 private int mMinWidth; 3690 3691 /** 3692 * The delegate to handle touch events that are physically in this view 3693 * but should be handled by another view. 3694 */ 3695 private TouchDelegate mTouchDelegate = null; 3696 3697 /** 3698 * Solid color to use as a background when creating the drawing cache. Enables 3699 * the cache to use 16 bit bitmaps instead of 32 bit. 3700 */ 3701 private int mDrawingCacheBackgroundColor = 0; 3702 3703 /** 3704 * Special tree observer used when mAttachInfo is null. 3705 */ 3706 private ViewTreeObserver mFloatingTreeObserver; 3707 3708 /** 3709 * Cache the touch slop from the context that created the view. 3710 */ 3711 private int mTouchSlop; 3712 3713 /** 3714 * Object that handles automatic animation of view properties. 3715 */ 3716 private ViewPropertyAnimator mAnimator = null; 3717 3718 /** 3719 * Flag indicating that a drag can cross window boundaries. When 3720 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3721 * with this flag set, all visible applications will be able to participate 3722 * in the drag operation and receive the dragged content. 3723 * 3724 * If this is the only flag set, then the drag recipient will only have access to text data 3725 * and intents contained in the {@link ClipData} object. Access to URIs contained in the 3726 * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags. 3727 */ 3728 public static final int DRAG_FLAG_GLOBAL = 1 << 8; // 256 3729 3730 /** 3731 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3732 * request read access to the content URI(s) contained in the {@link ClipData} object. 3733 * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION 3734 */ 3735 public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION; 3736 3737 /** 3738 * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to 3739 * request write access to the content URI(s) contained in the {@link ClipData} object. 3740 * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION 3741 */ 3742 public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 3743 3744 /** 3745 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3746 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device 3747 * reboots until explicitly revoked with 3748 * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}. 3749 * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION 3750 */ 3751 public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 3752 Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION; 3753 3754 /** 3755 * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link 3756 * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix 3757 * match against the original granted URI. 3758 * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION 3759 */ 3760 public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 3761 Intent.FLAG_GRANT_PREFIX_URI_PERMISSION; 3762 3763 /** 3764 * Flag indicating that the drag shadow will be opaque. When 3765 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int)} is called 3766 * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent. 3767 */ 3768 public static final int DRAG_FLAG_OPAQUE = 1 << 9; 3769 3770 /** 3771 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. 3772 */ 3773 private float mVerticalScrollFactor; 3774 3775 /** 3776 * Position of the vertical scroll bar. 3777 */ 3778 private int mVerticalScrollbarPosition; 3779 3780 /** 3781 * Position the scroll bar at the default position as determined by the system. 3782 */ 3783 public static final int SCROLLBAR_POSITION_DEFAULT = 0; 3784 3785 /** 3786 * Position the scroll bar along the left edge. 3787 */ 3788 public static final int SCROLLBAR_POSITION_LEFT = 1; 3789 3790 /** 3791 * Position the scroll bar along the right edge. 3792 */ 3793 public static final int SCROLLBAR_POSITION_RIGHT = 2; 3794 3795 /** 3796 * Indicates that the view does not have a layer. 3797 * 3798 * @see #getLayerType() 3799 * @see #setLayerType(int, android.graphics.Paint) 3800 * @see #LAYER_TYPE_SOFTWARE 3801 * @see #LAYER_TYPE_HARDWARE 3802 */ 3803 public static final int LAYER_TYPE_NONE = 0; 3804 3805 /** 3806 * <p>Indicates that the view has a software layer. A software layer is backed 3807 * by a bitmap and causes the view to be rendered using Android's software 3808 * rendering pipeline, even if hardware acceleration is enabled.</p> 3809 * 3810 * <p>Software layers have various usages:</p> 3811 * <p>When the application is not using hardware acceleration, a software layer 3812 * is useful to apply a specific color filter and/or blending mode and/or 3813 * translucency to a view and all its children.</p> 3814 * <p>When the application is using hardware acceleration, a software layer 3815 * is useful to render drawing primitives not supported by the hardware 3816 * accelerated pipeline. It can also be used to cache a complex view tree 3817 * into a texture and reduce the complexity of drawing operations. For instance, 3818 * when animating a complex view tree with a translation, a software layer can 3819 * be used to render the view tree only once.</p> 3820 * <p>Software layers should be avoided when the affected view tree updates 3821 * often. Every update will require to re-render the software layer, which can 3822 * potentially be slow (particularly when hardware acceleration is turned on 3823 * since the layer will have to be uploaded into a hardware texture after every 3824 * update.)</p> 3825 * 3826 * @see #getLayerType() 3827 * @see #setLayerType(int, android.graphics.Paint) 3828 * @see #LAYER_TYPE_NONE 3829 * @see #LAYER_TYPE_HARDWARE 3830 */ 3831 public static final int LAYER_TYPE_SOFTWARE = 1; 3832 3833 /** 3834 * <p>Indicates that the view has a hardware layer. A hardware layer is backed 3835 * by a hardware specific texture (generally Frame Buffer Objects or FBO on 3836 * OpenGL hardware) and causes the view to be rendered using Android's hardware 3837 * rendering pipeline, but only if hardware acceleration is turned on for the 3838 * view hierarchy. When hardware acceleration is turned off, hardware layers 3839 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> 3840 * 3841 * <p>A hardware layer is useful to apply a specific color filter and/or 3842 * blending mode and/or translucency to a view and all its children.</p> 3843 * <p>A hardware layer can be used to cache a complex view tree into a 3844 * texture and reduce the complexity of drawing operations. For instance, 3845 * when animating a complex view tree with a translation, a hardware layer can 3846 * be used to render the view tree only once.</p> 3847 * <p>A hardware layer can also be used to increase the rendering quality when 3848 * rotation transformations are applied on a view. It can also be used to 3849 * prevent potential clipping issues when applying 3D transforms on a view.</p> 3850 * 3851 * @see #getLayerType() 3852 * @see #setLayerType(int, android.graphics.Paint) 3853 * @see #LAYER_TYPE_NONE 3854 * @see #LAYER_TYPE_SOFTWARE 3855 */ 3856 public static final int LAYER_TYPE_HARDWARE = 2; 3857 3858 @ViewDebug.ExportedProperty(category = "drawing", mapping = { 3859 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"), 3860 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"), 3861 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE") 3862 }) 3863 int mLayerType = LAYER_TYPE_NONE; 3864 Paint mLayerPaint; 3865 3866 /** 3867 * Set to true when drawing cache is enabled and cannot be created. 3868 * 3869 * @hide 3870 */ 3871 public boolean mCachingFailed; 3872 private Bitmap mDrawingCache; 3873 private Bitmap mUnscaledDrawingCache; 3874 3875 /** 3876 * RenderNode holding View properties, potentially holding a DisplayList of View content. 3877 * <p> 3878 * When non-null and valid, this is expected to contain an up-to-date copy 3879 * of the View content. Its DisplayList content is cleared on temporary detach and reset on 3880 * cleanup. 3881 */ 3882 final RenderNode mRenderNode; 3883 3884 /** 3885 * Set to true when the view is sending hover accessibility events because it 3886 * is the innermost hovered view. 3887 */ 3888 private boolean mSendingHoverAccessibilityEvents; 3889 3890 /** 3891 * Delegate for injecting accessibility functionality. 3892 */ 3893 AccessibilityDelegate mAccessibilityDelegate; 3894 3895 /** 3896 * The view's overlay layer. Developers get a reference to the overlay via getOverlay() 3897 * and add/remove objects to/from the overlay directly through the Overlay methods. 3898 */ 3899 ViewOverlay mOverlay; 3900 3901 /** 3902 * The currently active parent view for receiving delegated nested scrolling events. 3903 * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared 3904 * by {@link #stopNestedScroll()} at the same point where we clear 3905 * requestDisallowInterceptTouchEvent. 3906 */ 3907 private ViewParent mNestedScrollingParent; 3908 3909 /** 3910 * Consistency verifier for debugging purposes. 3911 * @hide 3912 */ 3913 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier = 3914 InputEventConsistencyVerifier.isInstrumentationEnabled() ? 3915 new InputEventConsistencyVerifier(this, 0) : null; 3916 3917 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1); 3918 3919 private int[] mTempNestedScrollConsumed; 3920 3921 /** 3922 * An overlay is going to draw this View instead of being drawn as part of this 3923 * View's parent. mGhostView is the View in the Overlay that must be invalidated 3924 * when this view is invalidated. 3925 */ 3926 GhostView mGhostView; 3927 3928 /** 3929 * Holds pairs of adjacent attribute data: attribute name followed by its value. 3930 * @hide 3931 */ 3932 @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true) 3933 public String[] mAttributes; 3934 3935 /** 3936 * Maps a Resource id to its name. 3937 */ 3938 private static SparseArray<String> mAttributeMap; 3939 3940 /** 3941 * Queue of pending runnables. Used to postpone calls to post() until this 3942 * view is attached and has a handler. 3943 */ 3944 private HandlerActionQueue mRunQueue; 3945 3946 /** 3947 * @hide 3948 */ 3949 String mStartActivityRequestWho; 3950 3951 /** 3952 * Simple constructor to use when creating a view from code. 3953 * 3954 * @param context The Context the view is running in, through which it can 3955 * access the current theme, resources, etc. 3956 */ 3957 public View(Context context) { 3958 mContext = context; 3959 mResources = context != null ? context.getResources() : null; 3960 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED; 3961 // Set some flags defaults 3962 mPrivateFlags2 = 3963 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) | 3964 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) | 3965 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) | 3966 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) | 3967 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) | 3968 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT); 3969 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 3970 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); 3971 mUserPaddingStart = UNDEFINED_PADDING; 3972 mUserPaddingEnd = UNDEFINED_PADDING; 3973 mRenderNode = RenderNode.create(getClass().getName(), this); 3974 3975 if (!sCompatibilityDone && context != null) { 3976 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 3977 3978 // Older apps may need this compatibility hack for measurement. 3979 sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1; 3980 3981 // Older apps expect onMeasure() to always be called on a layout pass, regardless 3982 // of whether a layout was requested on that View. 3983 sIgnoreMeasureCache = targetSdkVersion < KITKAT; 3984 3985 Canvas.sCompatibilityRestore = targetSdkVersion < M; 3986 3987 // In M and newer, our widgets can pass a "hint" value in the size 3988 // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers 3989 // know what the expected parent size is going to be, so e.g. list items can size 3990 // themselves at 1/3 the size of their container. It breaks older apps though, 3991 // specifically apps that use some popular open source libraries. 3992 sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M; 3993 3994 // Old versions of the platform would give different results from 3995 // LinearLayout measurement passes using EXACTLY and non-EXACTLY 3996 // modes, so we always need to run an additional EXACTLY pass. 3997 sAlwaysRemeasureExactly = targetSdkVersion <= M; 3998 3999 // Prior to N, layout params could change without requiring a 4000 // subsequent call to setLayoutParams() and they would usually 4001 // work. Partial layout breaks this assumption. 4002 sLayoutParamsAlwaysChanged = targetSdkVersion <= M; 4003 4004 sCompatibilityDone = true; 4005 } 4006 } 4007 4008 /** 4009 * Constructor that is called when inflating a view from XML. This is called 4010 * when a view is being constructed from an XML file, supplying attributes 4011 * that were specified in the XML file. This version uses a default style of 4012 * 0, so the only attribute values applied are those in the Context's Theme 4013 * and the given AttributeSet. 4014 * 4015 * <p> 4016 * The method onFinishInflate() will be called after all children have been 4017 * added. 4018 * 4019 * @param context The Context the view is running in, through which it can 4020 * access the current theme, resources, etc. 4021 * @param attrs The attributes of the XML tag that is inflating the view. 4022 * @see #View(Context, AttributeSet, int) 4023 */ 4024 public View(Context context, @Nullable AttributeSet attrs) { 4025 this(context, attrs, 0); 4026 } 4027 4028 /** 4029 * Perform inflation from XML and apply a class-specific base style from a 4030 * theme attribute. This constructor of View allows subclasses to use their 4031 * own base style when they are inflating. For example, a Button class's 4032 * constructor would call this version of the super class constructor and 4033 * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this 4034 * allows the theme's button style to modify all of the base view attributes 4035 * (in particular its background) as well as the Button class's attributes. 4036 * 4037 * @param context The Context the view is running in, through which it can 4038 * access the current theme, resources, etc. 4039 * @param attrs The attributes of the XML tag that is inflating the view. 4040 * @param defStyleAttr An attribute in the current theme that contains a 4041 * reference to a style resource that supplies default values for 4042 * the view. Can be 0 to not look for defaults. 4043 * @see #View(Context, AttributeSet) 4044 */ 4045 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 4046 this(context, attrs, defStyleAttr, 0); 4047 } 4048 4049 /** 4050 * Perform inflation from XML and apply a class-specific base style from a 4051 * theme attribute or style resource. This constructor of View allows 4052 * subclasses to use their own base style when they are inflating. 4053 * <p> 4054 * When determining the final value of a particular attribute, there are 4055 * four inputs that come into play: 4056 * <ol> 4057 * <li>Any attribute values in the given AttributeSet. 4058 * <li>The style resource specified in the AttributeSet (named "style"). 4059 * <li>The default style specified by <var>defStyleAttr</var>. 4060 * <li>The default style specified by <var>defStyleRes</var>. 4061 * <li>The base values in this theme. 4062 * </ol> 4063 * <p> 4064 * Each of these inputs is considered in-order, with the first listed taking 4065 * precedence over the following ones. In other words, if in the 4066 * AttributeSet you have supplied <code><Button * textColor="#ff000000"></code> 4067 * , then the button's text will <em>always</em> be black, regardless of 4068 * what is specified in any of the styles. 4069 * 4070 * @param context The Context the view is running in, through which it can 4071 * access the current theme, resources, etc. 4072 * @param attrs The attributes of the XML tag that is inflating the view. 4073 * @param defStyleAttr An attribute in the current theme that contains a 4074 * reference to a style resource that supplies default values for 4075 * the view. Can be 0 to not look for defaults. 4076 * @param defStyleRes A resource identifier of a style resource that 4077 * supplies default values for the view, used only if 4078 * defStyleAttr is 0 or can not be found in the theme. Can be 0 4079 * to not look for defaults. 4080 * @see #View(Context, AttributeSet, int) 4081 */ 4082 public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 4083 this(context); 4084 4085 final TypedArray a = context.obtainStyledAttributes( 4086 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); 4087 4088 if (mDebugViewAttributes) { 4089 saveAttributeData(attrs, a); 4090 } 4091 4092 Drawable background = null; 4093 4094 int leftPadding = -1; 4095 int topPadding = -1; 4096 int rightPadding = -1; 4097 int bottomPadding = -1; 4098 int startPadding = UNDEFINED_PADDING; 4099 int endPadding = UNDEFINED_PADDING; 4100 4101 int padding = -1; 4102 4103 int viewFlagValues = 0; 4104 int viewFlagMasks = 0; 4105 4106 boolean setScrollContainer = false; 4107 4108 int x = 0; 4109 int y = 0; 4110 4111 float tx = 0; 4112 float ty = 0; 4113 float tz = 0; 4114 float elevation = 0; 4115 float rotation = 0; 4116 float rotationX = 0; 4117 float rotationY = 0; 4118 float sx = 1f; 4119 float sy = 1f; 4120 boolean transformSet = false; 4121 4122 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY; 4123 int overScrollMode = mOverScrollMode; 4124 boolean initializeScrollbars = false; 4125 boolean initializeScrollIndicators = false; 4126 4127 boolean startPaddingDefined = false; 4128 boolean endPaddingDefined = false; 4129 boolean leftPaddingDefined = false; 4130 boolean rightPaddingDefined = false; 4131 4132 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; 4133 4134 final int N = a.getIndexCount(); 4135 for (int i = 0; i < N; i++) { 4136 int attr = a.getIndex(i); 4137 switch (attr) { 4138 case com.android.internal.R.styleable.View_background: 4139 background = a.getDrawable(attr); 4140 break; 4141 case com.android.internal.R.styleable.View_padding: 4142 padding = a.getDimensionPixelSize(attr, -1); 4143 mUserPaddingLeftInitial = padding; 4144 mUserPaddingRightInitial = padding; 4145 leftPaddingDefined = true; 4146 rightPaddingDefined = true; 4147 break; 4148 case com.android.internal.R.styleable.View_paddingLeft: 4149 leftPadding = a.getDimensionPixelSize(attr, -1); 4150 mUserPaddingLeftInitial = leftPadding; 4151 leftPaddingDefined = true; 4152 break; 4153 case com.android.internal.R.styleable.View_paddingTop: 4154 topPadding = a.getDimensionPixelSize(attr, -1); 4155 break; 4156 case com.android.internal.R.styleable.View_paddingRight: 4157 rightPadding = a.getDimensionPixelSize(attr, -1); 4158 mUserPaddingRightInitial = rightPadding; 4159 rightPaddingDefined = true; 4160 break; 4161 case com.android.internal.R.styleable.View_paddingBottom: 4162 bottomPadding = a.getDimensionPixelSize(attr, -1); 4163 break; 4164 case com.android.internal.R.styleable.View_paddingStart: 4165 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4166 startPaddingDefined = (startPadding != UNDEFINED_PADDING); 4167 break; 4168 case com.android.internal.R.styleable.View_paddingEnd: 4169 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING); 4170 endPaddingDefined = (endPadding != UNDEFINED_PADDING); 4171 break; 4172 case com.android.internal.R.styleable.View_scrollX: 4173 x = a.getDimensionPixelOffset(attr, 0); 4174 break; 4175 case com.android.internal.R.styleable.View_scrollY: 4176 y = a.getDimensionPixelOffset(attr, 0); 4177 break; 4178 case com.android.internal.R.styleable.View_alpha: 4179 setAlpha(a.getFloat(attr, 1f)); 4180 break; 4181 case com.android.internal.R.styleable.View_transformPivotX: 4182 setPivotX(a.getDimensionPixelOffset(attr, 0)); 4183 break; 4184 case com.android.internal.R.styleable.View_transformPivotY: 4185 setPivotY(a.getDimensionPixelOffset(attr, 0)); 4186 break; 4187 case com.android.internal.R.styleable.View_translationX: 4188 tx = a.getDimensionPixelOffset(attr, 0); 4189 transformSet = true; 4190 break; 4191 case com.android.internal.R.styleable.View_translationY: 4192 ty = a.getDimensionPixelOffset(attr, 0); 4193 transformSet = true; 4194 break; 4195 case com.android.internal.R.styleable.View_translationZ: 4196 tz = a.getDimensionPixelOffset(attr, 0); 4197 transformSet = true; 4198 break; 4199 case com.android.internal.R.styleable.View_elevation: 4200 elevation = a.getDimensionPixelOffset(attr, 0); 4201 transformSet = true; 4202 break; 4203 case com.android.internal.R.styleable.View_rotation: 4204 rotation = a.getFloat(attr, 0); 4205 transformSet = true; 4206 break; 4207 case com.android.internal.R.styleable.View_rotationX: 4208 rotationX = a.getFloat(attr, 0); 4209 transformSet = true; 4210 break; 4211 case com.android.internal.R.styleable.View_rotationY: 4212 rotationY = a.getFloat(attr, 0); 4213 transformSet = true; 4214 break; 4215 case com.android.internal.R.styleable.View_scaleX: 4216 sx = a.getFloat(attr, 1f); 4217 transformSet = true; 4218 break; 4219 case com.android.internal.R.styleable.View_scaleY: 4220 sy = a.getFloat(attr, 1f); 4221 transformSet = true; 4222 break; 4223 case com.android.internal.R.styleable.View_id: 4224 mID = a.getResourceId(attr, NO_ID); 4225 break; 4226 case com.android.internal.R.styleable.View_tag: 4227 mTag = a.getText(attr); 4228 break; 4229 case com.android.internal.R.styleable.View_fitsSystemWindows: 4230 if (a.getBoolean(attr, false)) { 4231 viewFlagValues |= FITS_SYSTEM_WINDOWS; 4232 viewFlagMasks |= FITS_SYSTEM_WINDOWS; 4233 } 4234 break; 4235 case com.android.internal.R.styleable.View_focusable: 4236 if (a.getBoolean(attr, false)) { 4237 viewFlagValues |= FOCUSABLE; 4238 viewFlagMasks |= FOCUSABLE_MASK; 4239 } 4240 break; 4241 case com.android.internal.R.styleable.View_focusableInTouchMode: 4242 if (a.getBoolean(attr, false)) { 4243 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE; 4244 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK; 4245 } 4246 break; 4247 case com.android.internal.R.styleable.View_clickable: 4248 if (a.getBoolean(attr, false)) { 4249 viewFlagValues |= CLICKABLE; 4250 viewFlagMasks |= CLICKABLE; 4251 } 4252 break; 4253 case com.android.internal.R.styleable.View_longClickable: 4254 if (a.getBoolean(attr, false)) { 4255 viewFlagValues |= LONG_CLICKABLE; 4256 viewFlagMasks |= LONG_CLICKABLE; 4257 } 4258 break; 4259 case com.android.internal.R.styleable.View_contextClickable: 4260 if (a.getBoolean(attr, false)) { 4261 viewFlagValues |= CONTEXT_CLICKABLE; 4262 viewFlagMasks |= CONTEXT_CLICKABLE; 4263 } 4264 break; 4265 case com.android.internal.R.styleable.View_saveEnabled: 4266 if (!a.getBoolean(attr, true)) { 4267 viewFlagValues |= SAVE_DISABLED; 4268 viewFlagMasks |= SAVE_DISABLED_MASK; 4269 } 4270 break; 4271 case com.android.internal.R.styleable.View_duplicateParentState: 4272 if (a.getBoolean(attr, false)) { 4273 viewFlagValues |= DUPLICATE_PARENT_STATE; 4274 viewFlagMasks |= DUPLICATE_PARENT_STATE; 4275 } 4276 break; 4277 case com.android.internal.R.styleable.View_visibility: 4278 final int visibility = a.getInt(attr, 0); 4279 if (visibility != 0) { 4280 viewFlagValues |= VISIBILITY_FLAGS[visibility]; 4281 viewFlagMasks |= VISIBILITY_MASK; 4282 } 4283 break; 4284 case com.android.internal.R.styleable.View_layoutDirection: 4285 // Clear any layout direction flags (included resolved bits) already set 4286 mPrivateFlags2 &= 4287 ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK); 4288 // Set the layout direction flags depending on the value of the attribute 4289 final int layoutDirection = a.getInt(attr, -1); 4290 final int value = (layoutDirection != -1) ? 4291 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT; 4292 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT); 4293 break; 4294 case com.android.internal.R.styleable.View_drawingCacheQuality: 4295 final int cacheQuality = a.getInt(attr, 0); 4296 if (cacheQuality != 0) { 4297 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality]; 4298 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK; 4299 } 4300 break; 4301 case com.android.internal.R.styleable.View_contentDescription: 4302 setContentDescription(a.getString(attr)); 4303 break; 4304 case com.android.internal.R.styleable.View_accessibilityTraversalBefore: 4305 setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID)); 4306 break; 4307 case com.android.internal.R.styleable.View_accessibilityTraversalAfter: 4308 setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID)); 4309 break; 4310 case com.android.internal.R.styleable.View_labelFor: 4311 setLabelFor(a.getResourceId(attr, NO_ID)); 4312 break; 4313 case com.android.internal.R.styleable.View_soundEffectsEnabled: 4314 if (!a.getBoolean(attr, true)) { 4315 viewFlagValues &= ~SOUND_EFFECTS_ENABLED; 4316 viewFlagMasks |= SOUND_EFFECTS_ENABLED; 4317 } 4318 break; 4319 case com.android.internal.R.styleable.View_hapticFeedbackEnabled: 4320 if (!a.getBoolean(attr, true)) { 4321 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED; 4322 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED; 4323 } 4324 break; 4325 case R.styleable.View_scrollbars: 4326 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE); 4327 if (scrollbars != SCROLLBARS_NONE) { 4328 viewFlagValues |= scrollbars; 4329 viewFlagMasks |= SCROLLBARS_MASK; 4330 initializeScrollbars = true; 4331 } 4332 break; 4333 //noinspection deprecation 4334 case R.styleable.View_fadingEdge: 4335 if (targetSdkVersion >= ICE_CREAM_SANDWICH) { 4336 // Ignore the attribute starting with ICS 4337 break; 4338 } 4339 // With builds < ICS, fall through and apply fading edges 4340 case R.styleable.View_requiresFadingEdge: 4341 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE); 4342 if (fadingEdge != FADING_EDGE_NONE) { 4343 viewFlagValues |= fadingEdge; 4344 viewFlagMasks |= FADING_EDGE_MASK; 4345 initializeFadingEdgeInternal(a); 4346 } 4347 break; 4348 case R.styleable.View_scrollbarStyle: 4349 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY); 4350 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4351 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK; 4352 viewFlagMasks |= SCROLLBARS_STYLE_MASK; 4353 } 4354 break; 4355 case R.styleable.View_isScrollContainer: 4356 setScrollContainer = true; 4357 if (a.getBoolean(attr, false)) { 4358 setScrollContainer(true); 4359 } 4360 break; 4361 case com.android.internal.R.styleable.View_keepScreenOn: 4362 if (a.getBoolean(attr, false)) { 4363 viewFlagValues |= KEEP_SCREEN_ON; 4364 viewFlagMasks |= KEEP_SCREEN_ON; 4365 } 4366 break; 4367 case R.styleable.View_filterTouchesWhenObscured: 4368 if (a.getBoolean(attr, false)) { 4369 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED; 4370 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED; 4371 } 4372 break; 4373 case R.styleable.View_nextFocusLeft: 4374 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID); 4375 break; 4376 case R.styleable.View_nextFocusRight: 4377 mNextFocusRightId = a.getResourceId(attr, View.NO_ID); 4378 break; 4379 case R.styleable.View_nextFocusUp: 4380 mNextFocusUpId = a.getResourceId(attr, View.NO_ID); 4381 break; 4382 case R.styleable.View_nextFocusDown: 4383 mNextFocusDownId = a.getResourceId(attr, View.NO_ID); 4384 break; 4385 case R.styleable.View_nextFocusForward: 4386 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID); 4387 break; 4388 case R.styleable.View_minWidth: 4389 mMinWidth = a.getDimensionPixelSize(attr, 0); 4390 break; 4391 case R.styleable.View_minHeight: 4392 mMinHeight = a.getDimensionPixelSize(attr, 0); 4393 break; 4394 case R.styleable.View_onClick: 4395 if (context.isRestricted()) { 4396 throw new IllegalStateException("The android:onClick attribute cannot " 4397 + "be used within a restricted context"); 4398 } 4399 4400 final String handlerName = a.getString(attr); 4401 if (handlerName != null) { 4402 setOnClickListener(new DeclaredOnClickListener(this, handlerName)); 4403 } 4404 break; 4405 case R.styleable.View_overScrollMode: 4406 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS); 4407 break; 4408 case R.styleable.View_verticalScrollbarPosition: 4409 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); 4410 break; 4411 case R.styleable.View_layerType: 4412 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); 4413 break; 4414 case R.styleable.View_textDirection: 4415 // Clear any text direction flag already set 4416 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 4417 // Set the text direction flags depending on the value of the attribute 4418 final int textDirection = a.getInt(attr, -1); 4419 if (textDirection != -1) { 4420 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection]; 4421 } 4422 break; 4423 case R.styleable.View_textAlignment: 4424 // Clear any text alignment flag already set 4425 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 4426 // Set the text alignment flag depending on the value of the attribute 4427 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT); 4428 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment]; 4429 break; 4430 case R.styleable.View_importantForAccessibility: 4431 setImportantForAccessibility(a.getInt(attr, 4432 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT)); 4433 break; 4434 case R.styleable.View_accessibilityLiveRegion: 4435 setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT)); 4436 break; 4437 case R.styleable.View_transitionName: 4438 setTransitionName(a.getString(attr)); 4439 break; 4440 case R.styleable.View_nestedScrollingEnabled: 4441 setNestedScrollingEnabled(a.getBoolean(attr, false)); 4442 break; 4443 case R.styleable.View_stateListAnimator: 4444 setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, 4445 a.getResourceId(attr, 0))); 4446 break; 4447 case R.styleable.View_backgroundTint: 4448 // This will get applied later during setBackground(). 4449 if (mBackgroundTint == null) { 4450 mBackgroundTint = new TintInfo(); 4451 } 4452 mBackgroundTint.mTintList = a.getColorStateList( 4453 R.styleable.View_backgroundTint); 4454 mBackgroundTint.mHasTintList = true; 4455 break; 4456 case R.styleable.View_backgroundTintMode: 4457 // This will get applied later during setBackground(). 4458 if (mBackgroundTint == null) { 4459 mBackgroundTint = new TintInfo(); 4460 } 4461 mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt( 4462 R.styleable.View_backgroundTintMode, -1), null); 4463 mBackgroundTint.mHasTintMode = true; 4464 break; 4465 case R.styleable.View_outlineProvider: 4466 setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider, 4467 PROVIDER_BACKGROUND)); 4468 break; 4469 case R.styleable.View_foreground: 4470 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4471 setForeground(a.getDrawable(attr)); 4472 } 4473 break; 4474 case R.styleable.View_foregroundGravity: 4475 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4476 setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY)); 4477 } 4478 break; 4479 case R.styleable.View_foregroundTintMode: 4480 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4481 setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null)); 4482 } 4483 break; 4484 case R.styleable.View_foregroundTint: 4485 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4486 setForegroundTintList(a.getColorStateList(attr)); 4487 } 4488 break; 4489 case R.styleable.View_foregroundInsidePadding: 4490 if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) { 4491 if (mForegroundInfo == null) { 4492 mForegroundInfo = new ForegroundInfo(); 4493 } 4494 mForegroundInfo.mInsidePadding = a.getBoolean(attr, 4495 mForegroundInfo.mInsidePadding); 4496 } 4497 break; 4498 case R.styleable.View_scrollIndicators: 4499 final int scrollIndicators = 4500 (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT) 4501 & SCROLL_INDICATORS_PFLAG3_MASK; 4502 if (scrollIndicators != 0) { 4503 mPrivateFlags3 |= scrollIndicators; 4504 initializeScrollIndicators = true; 4505 } 4506 break; 4507 } 4508 } 4509 4510 setOverScrollMode(overScrollMode); 4511 4512 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet 4513 // the resolved layout direction). Those cached values will be used later during padding 4514 // resolution. 4515 mUserPaddingStart = startPadding; 4516 mUserPaddingEnd = endPadding; 4517 4518 if (background != null) { 4519 setBackground(background); 4520 } 4521 4522 // setBackground above will record that padding is currently provided by the background. 4523 // If we have padding specified via xml, record that here instead and use it. 4524 mLeftPaddingDefined = leftPaddingDefined; 4525 mRightPaddingDefined = rightPaddingDefined; 4526 4527 if (padding >= 0) { 4528 leftPadding = padding; 4529 topPadding = padding; 4530 rightPadding = padding; 4531 bottomPadding = padding; 4532 mUserPaddingLeftInitial = padding; 4533 mUserPaddingRightInitial = padding; 4534 } 4535 4536 if (isRtlCompatibilityMode()) { 4537 // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case. 4538 // left / right padding are used if defined (meaning here nothing to do). If they are not 4539 // defined and start / end padding are defined (e.g. in Frameworks resources), then we use 4540 // start / end and resolve them as left / right (layout direction is not taken into account). 4541 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4542 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4543 // defined. 4544 if (!mLeftPaddingDefined && startPaddingDefined) { 4545 leftPadding = startPadding; 4546 } 4547 mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; 4548 if (!mRightPaddingDefined && endPaddingDefined) { 4549 rightPadding = endPadding; 4550 } 4551 mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; 4552 } else { 4553 // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right 4554 // values defined. Otherwise, left /right values are used. 4555 // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial 4556 // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if 4557 // defined. 4558 final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; 4559 4560 if (mLeftPaddingDefined && !hasRelativePadding) { 4561 mUserPaddingLeftInitial = leftPadding; 4562 } 4563 if (mRightPaddingDefined && !hasRelativePadding) { 4564 mUserPaddingRightInitial = rightPadding; 4565 } 4566 } 4567 4568 internalSetPadding( 4569 mUserPaddingLeftInitial, 4570 topPadding >= 0 ? topPadding : mPaddingTop, 4571 mUserPaddingRightInitial, 4572 bottomPadding >= 0 ? bottomPadding : mPaddingBottom); 4573 4574 if (viewFlagMasks != 0) { 4575 setFlags(viewFlagValues, viewFlagMasks); 4576 } 4577 4578 if (initializeScrollbars) { 4579 initializeScrollbarsInternal(a); 4580 } 4581 4582 if (initializeScrollIndicators) { 4583 initializeScrollIndicatorsInternal(); 4584 } 4585 4586 a.recycle(); 4587 4588 // Needs to be called after mViewFlags is set 4589 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) { 4590 recomputePadding(); 4591 } 4592 4593 if (x != 0 || y != 0) { 4594 scrollTo(x, y); 4595 } 4596 4597 if (transformSet) { 4598 setTranslationX(tx); 4599 setTranslationY(ty); 4600 setTranslationZ(tz); 4601 setElevation(elevation); 4602 setRotation(rotation); 4603 setRotationX(rotationX); 4604 setRotationY(rotationY); 4605 setScaleX(sx); 4606 setScaleY(sy); 4607 } 4608 4609 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) { 4610 setScrollContainer(true); 4611 } 4612 4613 computeOpaqueFlags(); 4614 } 4615 4616 /** 4617 * An implementation of OnClickListener that attempts to lazily load a 4618 * named click handling method from a parent or ancestor context. 4619 */ 4620 private static class DeclaredOnClickListener implements OnClickListener { 4621 private final View mHostView; 4622 private final String mMethodName; 4623 4624 private Method mResolvedMethod; 4625 private Context mResolvedContext; 4626 4627 public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { 4628 mHostView = hostView; 4629 mMethodName = methodName; 4630 } 4631 4632 @Override 4633 public void onClick(@NonNull View v) { 4634 if (mResolvedMethod == null) { 4635 resolveMethod(mHostView.getContext(), mMethodName); 4636 } 4637 4638 try { 4639 mResolvedMethod.invoke(mResolvedContext, v); 4640 } catch (IllegalAccessException e) { 4641 throw new IllegalStateException( 4642 "Could not execute non-public method for android:onClick", e); 4643 } catch (InvocationTargetException e) { 4644 throw new IllegalStateException( 4645 "Could not execute method for android:onClick", e); 4646 } 4647 } 4648 4649 @NonNull 4650 private void resolveMethod(@Nullable Context context, @NonNull String name) { 4651 while (context != null) { 4652 try { 4653 if (!context.isRestricted()) { 4654 final Method method = context.getClass().getMethod(mMethodName, View.class); 4655 if (method != null) { 4656 mResolvedMethod = method; 4657 mResolvedContext = context; 4658 return; 4659 } 4660 } 4661 } catch (NoSuchMethodException e) { 4662 // Failed to find method, keep searching up the hierarchy. 4663 } 4664 4665 if (context instanceof ContextWrapper) { 4666 context = ((ContextWrapper) context).getBaseContext(); 4667 } else { 4668 // Can't search up the hierarchy, null out and fail. 4669 context = null; 4670 } 4671 } 4672 4673 final int id = mHostView.getId(); 4674 final String idText = id == NO_ID ? "" : " with id '" 4675 + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; 4676 throw new IllegalStateException("Could not find method " + mMethodName 4677 + "(View) in a parent or ancestor Context for android:onClick " 4678 + "attribute defined on view " + mHostView.getClass() + idText); 4679 } 4680 } 4681 4682 /** 4683 * Non-public constructor for use in testing 4684 */ 4685 View() { 4686 mResources = null; 4687 mRenderNode = RenderNode.create(getClass().getName(), this); 4688 } 4689 4690 private static SparseArray<String> getAttributeMap() { 4691 if (mAttributeMap == null) { 4692 mAttributeMap = new SparseArray<>(); 4693 } 4694 return mAttributeMap; 4695 } 4696 4697 private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) { 4698 final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount(); 4699 final int indexCount = t.getIndexCount(); 4700 final String[] attributes = new String[(attrsCount + indexCount) * 2]; 4701 4702 int i = 0; 4703 4704 // Store raw XML attributes. 4705 for (int j = 0; j < attrsCount; ++j) { 4706 attributes[i] = attrs.getAttributeName(j); 4707 attributes[i + 1] = attrs.getAttributeValue(j); 4708 i += 2; 4709 } 4710 4711 // Store resolved styleable attributes. 4712 final Resources res = t.getResources(); 4713 final SparseArray<String> attributeMap = getAttributeMap(); 4714 for (int j = 0; j < indexCount; ++j) { 4715 final int index = t.getIndex(j); 4716 if (!t.hasValueOrEmpty(index)) { 4717 // Value is undefined. Skip it. 4718 continue; 4719 } 4720 4721 final int resourceId = t.getResourceId(index, 0); 4722 if (resourceId == 0) { 4723 // Value is not a reference. Skip it. 4724 continue; 4725 } 4726 4727 String resourceName = attributeMap.get(resourceId); 4728 if (resourceName == null) { 4729 try { 4730 resourceName = res.getResourceName(resourceId); 4731 } catch (Resources.NotFoundException e) { 4732 resourceName = "0x" + Integer.toHexString(resourceId); 4733 } 4734 attributeMap.put(resourceId, resourceName); 4735 } 4736 4737 attributes[i] = resourceName; 4738 attributes[i + 1] = t.getString(index); 4739 i += 2; 4740 } 4741 4742 // Trim to fit contents. 4743 final String[] trimmed = new String[i]; 4744 System.arraycopy(attributes, 0, trimmed, 0, i); 4745 mAttributes = trimmed; 4746 } 4747 4748 public String toString() { 4749 StringBuilder out = new StringBuilder(128); 4750 out.append(getClass().getName()); 4751 out.append('{'); 4752 out.append(Integer.toHexString(System.identityHashCode(this))); 4753 out.append(' '); 4754 switch (mViewFlags&VISIBILITY_MASK) { 4755 case VISIBLE: out.append('V'); break; 4756 case INVISIBLE: out.append('I'); break; 4757 case GONE: out.append('G'); break; 4758 default: out.append('.'); break; 4759 } 4760 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.'); 4761 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.'); 4762 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D'); 4763 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.'); 4764 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.'); 4765 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.'); 4766 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.'); 4767 out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.'); 4768 out.append(' '); 4769 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.'); 4770 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.'); 4771 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.'); 4772 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) { 4773 out.append('p'); 4774 } else { 4775 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.'); 4776 } 4777 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.'); 4778 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.'); 4779 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.'); 4780 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.'); 4781 out.append(' '); 4782 out.append(mLeft); 4783 out.append(','); 4784 out.append(mTop); 4785 out.append('-'); 4786 out.append(mRight); 4787 out.append(','); 4788 out.append(mBottom); 4789 final int id = getId(); 4790 if (id != NO_ID) { 4791 out.append(" #"); 4792 out.append(Integer.toHexString(id)); 4793 final Resources r = mResources; 4794 if (id > 0 && Resources.resourceHasPackage(id) && r != null) { 4795 try { 4796 String pkgname; 4797 switch (id&0xff000000) { 4798 case 0x7f000000: 4799 pkgname="app"; 4800 break; 4801 case 0x01000000: 4802 pkgname="android"; 4803 break; 4804 default: 4805 pkgname = r.getResourcePackageName(id); 4806 break; 4807 } 4808 String typename = r.getResourceTypeName(id); 4809 String entryname = r.getResourceEntryName(id); 4810 out.append(" "); 4811 out.append(pkgname); 4812 out.append(":"); 4813 out.append(typename); 4814 out.append("/"); 4815 out.append(entryname); 4816 } catch (Resources.NotFoundException e) { 4817 } 4818 } 4819 } 4820 out.append("}"); 4821 return out.toString(); 4822 } 4823 4824 /** 4825 * <p> 4826 * Initializes the fading edges from a given set of styled attributes. This 4827 * method should be called by subclasses that need fading edges and when an 4828 * instance of these subclasses is created programmatically rather than 4829 * being inflated from XML. This method is automatically called when the XML 4830 * is inflated. 4831 * </p> 4832 * 4833 * @param a the styled attributes set to initialize the fading edges from 4834 * 4835 * @removed 4836 */ 4837 protected void initializeFadingEdge(TypedArray a) { 4838 // This method probably shouldn't have been included in the SDK to begin with. 4839 // It relies on 'a' having been initialized using an attribute filter array that is 4840 // not publicly available to the SDK. The old method has been renamed 4841 // to initializeFadingEdgeInternal and hidden for framework use only; 4842 // this one initializes using defaults to make it safe to call for apps. 4843 4844 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 4845 4846 initializeFadingEdgeInternal(arr); 4847 4848 arr.recycle(); 4849 } 4850 4851 /** 4852 * <p> 4853 * Initializes the fading edges from a given set of styled attributes. This 4854 * method should be called by subclasses that need fading edges and when an 4855 * instance of these subclasses is created programmatically rather than 4856 * being inflated from XML. This method is automatically called when the XML 4857 * is inflated. 4858 * </p> 4859 * 4860 * @param a the styled attributes set to initialize the fading edges from 4861 * @hide This is the real method; the public one is shimmed to be safe to call from apps. 4862 */ 4863 protected void initializeFadingEdgeInternal(TypedArray a) { 4864 initScrollCache(); 4865 4866 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize( 4867 R.styleable.View_fadingEdgeLength, 4868 ViewConfiguration.get(mContext).getScaledFadingEdgeLength()); 4869 } 4870 4871 /** 4872 * Returns the size of the vertical faded edges used to indicate that more 4873 * content in this view is visible. 4874 * 4875 * @return The size in pixels of the vertical faded edge or 0 if vertical 4876 * faded edges are not enabled for this view. 4877 * @attr ref android.R.styleable#View_fadingEdgeLength 4878 */ 4879 public int getVerticalFadingEdgeLength() { 4880 if (isVerticalFadingEdgeEnabled()) { 4881 ScrollabilityCache cache = mScrollCache; 4882 if (cache != null) { 4883 return cache.fadingEdgeLength; 4884 } 4885 } 4886 return 0; 4887 } 4888 4889 /** 4890 * Set the size of the faded edge used to indicate that more content in this 4891 * view is available. Will not change whether the fading edge is enabled; use 4892 * {@link #setVerticalFadingEdgeEnabled(boolean)} or 4893 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge 4894 * for the vertical or horizontal fading edges. 4895 * 4896 * @param length The size in pixels of the faded edge used to indicate that more 4897 * content in this view is visible. 4898 */ 4899 public void setFadingEdgeLength(int length) { 4900 initScrollCache(); 4901 mScrollCache.fadingEdgeLength = length; 4902 } 4903 4904 /** 4905 * Returns the size of the horizontal faded edges used to indicate that more 4906 * content in this view is visible. 4907 * 4908 * @return The size in pixels of the horizontal faded edge or 0 if horizontal 4909 * faded edges are not enabled for this view. 4910 * @attr ref android.R.styleable#View_fadingEdgeLength 4911 */ 4912 public int getHorizontalFadingEdgeLength() { 4913 if (isHorizontalFadingEdgeEnabled()) { 4914 ScrollabilityCache cache = mScrollCache; 4915 if (cache != null) { 4916 return cache.fadingEdgeLength; 4917 } 4918 } 4919 return 0; 4920 } 4921 4922 /** 4923 * Returns the width of the vertical scrollbar. 4924 * 4925 * @return The width in pixels of the vertical scrollbar or 0 if there 4926 * is no vertical scrollbar. 4927 */ 4928 public int getVerticalScrollbarWidth() { 4929 ScrollabilityCache cache = mScrollCache; 4930 if (cache != null) { 4931 ScrollBarDrawable scrollBar = cache.scrollBar; 4932 if (scrollBar != null) { 4933 int size = scrollBar.getSize(true); 4934 if (size <= 0) { 4935 size = cache.scrollBarSize; 4936 } 4937 return size; 4938 } 4939 return 0; 4940 } 4941 return 0; 4942 } 4943 4944 /** 4945 * Returns the height of the horizontal scrollbar. 4946 * 4947 * @return The height in pixels of the horizontal scrollbar or 0 if 4948 * there is no horizontal scrollbar. 4949 */ 4950 protected int getHorizontalScrollbarHeight() { 4951 ScrollabilityCache cache = mScrollCache; 4952 if (cache != null) { 4953 ScrollBarDrawable scrollBar = cache.scrollBar; 4954 if (scrollBar != null) { 4955 int size = scrollBar.getSize(false); 4956 if (size <= 0) { 4957 size = cache.scrollBarSize; 4958 } 4959 return size; 4960 } 4961 return 0; 4962 } 4963 return 0; 4964 } 4965 4966 /** 4967 * <p> 4968 * Initializes the scrollbars from a given set of styled attributes. This 4969 * method should be called by subclasses that need scrollbars and when an 4970 * instance of these subclasses is created programmatically rather than 4971 * being inflated from XML. This method is automatically called when the XML 4972 * is inflated. 4973 * </p> 4974 * 4975 * @param a the styled attributes set to initialize the scrollbars from 4976 * 4977 * @removed 4978 */ 4979 protected void initializeScrollbars(TypedArray a) { 4980 // It's not safe to use this method from apps. The parameter 'a' must have been obtained 4981 // using the View filter array which is not available to the SDK. As such, internal 4982 // framework usage now uses initializeScrollbarsInternal and we grab a default 4983 // TypedArray with the right filter instead here. 4984 TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View); 4985 4986 initializeScrollbarsInternal(arr); 4987 4988 // We ignored the method parameter. Recycle the one we actually did use. 4989 arr.recycle(); 4990 } 4991 4992 /** 4993 * <p> 4994 * Initializes the scrollbars from a given set of styled attributes. This 4995 * method should be called by subclasses that need scrollbars and when an 4996 * instance of these subclasses is created programmatically rather than 4997 * being inflated from XML. This method is automatically called when the XML 4998 * is inflated. 4999 * </p> 5000 * 5001 * @param a the styled attributes set to initialize the scrollbars from 5002 * @hide 5003 */ 5004 protected void initializeScrollbarsInternal(TypedArray a) { 5005 initScrollCache(); 5006 5007 final ScrollabilityCache scrollabilityCache = mScrollCache; 5008 5009 if (scrollabilityCache.scrollBar == null) { 5010 scrollabilityCache.scrollBar = new ScrollBarDrawable(); 5011 scrollabilityCache.scrollBar.setCallback(this); 5012 scrollabilityCache.scrollBar.setState(getDrawableState()); 5013 } 5014 5015 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true); 5016 5017 if (!fadeScrollbars) { 5018 scrollabilityCache.state = ScrollabilityCache.ON; 5019 } 5020 scrollabilityCache.fadeScrollBars = fadeScrollbars; 5021 5022 5023 scrollabilityCache.scrollBarFadeDuration = a.getInt( 5024 R.styleable.View_scrollbarFadeDuration, ViewConfiguration 5025 .getScrollBarFadeDuration()); 5026 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt( 5027 R.styleable.View_scrollbarDefaultDelayBeforeFade, 5028 ViewConfiguration.getScrollDefaultDelay()); 5029 5030 5031 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize( 5032 com.android.internal.R.styleable.View_scrollbarSize, 5033 ViewConfiguration.get(mContext).getScaledScrollBarSize()); 5034 5035 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal); 5036 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track); 5037 5038 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal); 5039 if (thumb != null) { 5040 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb); 5041 } 5042 5043 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack, 5044 false); 5045 if (alwaysDraw) { 5046 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true); 5047 } 5048 5049 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical); 5050 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track); 5051 5052 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical); 5053 if (thumb != null) { 5054 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb); 5055 } 5056 5057 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack, 5058 false); 5059 if (alwaysDraw) { 5060 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true); 5061 } 5062 5063 // Apply layout direction to the new Drawables if needed 5064 final int layoutDirection = getLayoutDirection(); 5065 if (track != null) { 5066 track.setLayoutDirection(layoutDirection); 5067 } 5068 if (thumb != null) { 5069 thumb.setLayoutDirection(layoutDirection); 5070 } 5071 5072 // Re-apply user/background padding so that scrollbar(s) get added 5073 resolvePadding(); 5074 } 5075 5076 private void initializeScrollIndicatorsInternal() { 5077 // Some day maybe we'll break this into top/left/start/etc. and let the 5078 // client control it. Until then, you can have any scroll indicator you 5079 // want as long as it's a 1dp foreground-colored rectangle. 5080 if (mScrollIndicatorDrawable == null) { 5081 mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); 5082 } 5083 } 5084 5085 /** 5086 * <p> 5087 * Initalizes the scrollability cache if necessary. 5088 * </p> 5089 */ 5090 private void initScrollCache() { 5091 if (mScrollCache == null) { 5092 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this); 5093 } 5094 } 5095 5096 private ScrollabilityCache getScrollCache() { 5097 initScrollCache(); 5098 return mScrollCache; 5099 } 5100 5101 /** 5102 * Set the position of the vertical scroll bar. Should be one of 5103 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or 5104 * {@link #SCROLLBAR_POSITION_RIGHT}. 5105 * 5106 * @param position Where the vertical scroll bar should be positioned. 5107 */ 5108 public void setVerticalScrollbarPosition(int position) { 5109 if (mVerticalScrollbarPosition != position) { 5110 mVerticalScrollbarPosition = position; 5111 computeOpaqueFlags(); 5112 resolvePadding(); 5113 } 5114 } 5115 5116 /** 5117 * @return The position where the vertical scroll bar will show, if applicable. 5118 * @see #setVerticalScrollbarPosition(int) 5119 */ 5120 public int getVerticalScrollbarPosition() { 5121 return mVerticalScrollbarPosition; 5122 } 5123 5124 /** 5125 * Sets the state of all scroll indicators. 5126 * <p> 5127 * See {@link #setScrollIndicators(int, int)} for usage information. 5128 * 5129 * @param indicators a bitmask of indicators that should be enabled, or 5130 * {@code 0} to disable all indicators 5131 * @see #setScrollIndicators(int, int) 5132 * @see #getScrollIndicators() 5133 * @attr ref android.R.styleable#View_scrollIndicators 5134 */ 5135 public void setScrollIndicators(@ScrollIndicators int indicators) { 5136 setScrollIndicators(indicators, 5137 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT); 5138 } 5139 5140 /** 5141 * Sets the state of the scroll indicators specified by the mask. To change 5142 * all scroll indicators at once, see {@link #setScrollIndicators(int)}. 5143 * <p> 5144 * When a scroll indicator is enabled, it will be displayed if the view 5145 * can scroll in the direction of the indicator. 5146 * <p> 5147 * Multiple indicator types may be enabled or disabled by passing the 5148 * logical OR of the desired types. If multiple types are specified, they 5149 * will all be set to the same enabled state. 5150 * <p> 5151 * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators 5152 * 5153 * @param indicators the indicator direction, or the logical OR of multiple 5154 * indicator directions. One or more of: 5155 * <ul> 5156 * <li>{@link #SCROLL_INDICATOR_TOP}</li> 5157 * <li>{@link #SCROLL_INDICATOR_BOTTOM}</li> 5158 * <li>{@link #SCROLL_INDICATOR_LEFT}</li> 5159 * <li>{@link #SCROLL_INDICATOR_RIGHT}</li> 5160 * <li>{@link #SCROLL_INDICATOR_START}</li> 5161 * <li>{@link #SCROLL_INDICATOR_END}</li> 5162 * </ul> 5163 * @see #setScrollIndicators(int) 5164 * @see #getScrollIndicators() 5165 * @attr ref android.R.styleable#View_scrollIndicators 5166 */ 5167 public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) { 5168 // Shift and sanitize mask. 5169 mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5170 mask &= SCROLL_INDICATORS_PFLAG3_MASK; 5171 5172 // Shift and mask indicators. 5173 indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5174 indicators &= mask; 5175 5176 // Merge with non-masked flags. 5177 final int updatedFlags = indicators | (mPrivateFlags3 & ~mask); 5178 5179 if (mPrivateFlags3 != updatedFlags) { 5180 mPrivateFlags3 = updatedFlags; 5181 5182 if (indicators != 0) { 5183 initializeScrollIndicatorsInternal(); 5184 } 5185 invalidate(); 5186 } 5187 } 5188 5189 /** 5190 * Returns a bitmask representing the enabled scroll indicators. 5191 * <p> 5192 * For example, if the top and left scroll indicators are enabled and all 5193 * other indicators are disabled, the return value will be 5194 * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}. 5195 * <p> 5196 * To check whether the bottom scroll indicator is enabled, use the value 5197 * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}. 5198 * 5199 * @return a bitmask representing the enabled scroll indicators 5200 */ 5201 @ScrollIndicators 5202 public int getScrollIndicators() { 5203 return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) 5204 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT; 5205 } 5206 5207 ListenerInfo getListenerInfo() { 5208 if (mListenerInfo != null) { 5209 return mListenerInfo; 5210 } 5211 mListenerInfo = new ListenerInfo(); 5212 return mListenerInfo; 5213 } 5214 5215 /** 5216 * Register a callback to be invoked when the scroll X or Y positions of 5217 * this view change. 5218 * <p> 5219 * <b>Note:</b> Some views handle scrolling independently from View and may 5220 * have their own separate listeners for scroll-type events. For example, 5221 * {@link android.widget.ListView ListView} allows clients to register an 5222 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 5223 * to listen for changes in list scroll position. 5224 * 5225 * @param l The listener to notify when the scroll X or Y position changes. 5226 * @see android.view.View#getScrollX() 5227 * @see android.view.View#getScrollY() 5228 */ 5229 public void setOnScrollChangeListener(OnScrollChangeListener l) { 5230 getListenerInfo().mOnScrollChangeListener = l; 5231 } 5232 5233 /** 5234 * Register a callback to be invoked when focus of this view changed. 5235 * 5236 * @param l The callback that will run. 5237 */ 5238 public void setOnFocusChangeListener(OnFocusChangeListener l) { 5239 getListenerInfo().mOnFocusChangeListener = l; 5240 } 5241 5242 /** 5243 * Add a listener that will be called when the bounds of the view change due to 5244 * layout processing. 5245 * 5246 * @param listener The listener that will be called when layout bounds change. 5247 */ 5248 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) { 5249 ListenerInfo li = getListenerInfo(); 5250 if (li.mOnLayoutChangeListeners == null) { 5251 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>(); 5252 } 5253 if (!li.mOnLayoutChangeListeners.contains(listener)) { 5254 li.mOnLayoutChangeListeners.add(listener); 5255 } 5256 } 5257 5258 /** 5259 * Remove a listener for layout changes. 5260 * 5261 * @param listener The listener for layout bounds change. 5262 */ 5263 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) { 5264 ListenerInfo li = mListenerInfo; 5265 if (li == null || li.mOnLayoutChangeListeners == null) { 5266 return; 5267 } 5268 li.mOnLayoutChangeListeners.remove(listener); 5269 } 5270 5271 /** 5272 * Add a listener for attach state changes. 5273 * 5274 * This listener will be called whenever this view is attached or detached 5275 * from a window. Remove the listener using 5276 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}. 5277 * 5278 * @param listener Listener to attach 5279 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener) 5280 */ 5281 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5282 ListenerInfo li = getListenerInfo(); 5283 if (li.mOnAttachStateChangeListeners == null) { 5284 li.mOnAttachStateChangeListeners 5285 = new CopyOnWriteArrayList<OnAttachStateChangeListener>(); 5286 } 5287 li.mOnAttachStateChangeListeners.add(listener); 5288 } 5289 5290 /** 5291 * Remove a listener for attach state changes. The listener will receive no further 5292 * notification of window attach/detach events. 5293 * 5294 * @param listener Listener to remove 5295 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener) 5296 */ 5297 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) { 5298 ListenerInfo li = mListenerInfo; 5299 if (li == null || li.mOnAttachStateChangeListeners == null) { 5300 return; 5301 } 5302 li.mOnAttachStateChangeListeners.remove(listener); 5303 } 5304 5305 /** 5306 * Returns the focus-change callback registered for this view. 5307 * 5308 * @return The callback, or null if one is not registered. 5309 */ 5310 public OnFocusChangeListener getOnFocusChangeListener() { 5311 ListenerInfo li = mListenerInfo; 5312 return li != null ? li.mOnFocusChangeListener : null; 5313 } 5314 5315 /** 5316 * Register a callback to be invoked when this view is clicked. If this view is not 5317 * clickable, it becomes clickable. 5318 * 5319 * @param l The callback that will run 5320 * 5321 * @see #setClickable(boolean) 5322 */ 5323 public void setOnClickListener(@Nullable OnClickListener l) { 5324 if (!isClickable()) { 5325 setClickable(true); 5326 } 5327 getListenerInfo().mOnClickListener = l; 5328 } 5329 5330 /** 5331 * Return whether this view has an attached OnClickListener. Returns 5332 * true if there is a listener, false if there is none. 5333 */ 5334 public boolean hasOnClickListeners() { 5335 ListenerInfo li = mListenerInfo; 5336 return (li != null && li.mOnClickListener != null); 5337 } 5338 5339 /** 5340 * Register a callback to be invoked when this view is clicked and held. If this view is not 5341 * long clickable, it becomes long clickable. 5342 * 5343 * @param l The callback that will run 5344 * 5345 * @see #setLongClickable(boolean) 5346 */ 5347 public void setOnLongClickListener(@Nullable OnLongClickListener l) { 5348 if (!isLongClickable()) { 5349 setLongClickable(true); 5350 } 5351 getListenerInfo().mOnLongClickListener = l; 5352 } 5353 5354 /** 5355 * Register a callback to be invoked when this view is context clicked. If the view is not 5356 * context clickable, it becomes context clickable. 5357 * 5358 * @param l The callback that will run 5359 * @see #setContextClickable(boolean) 5360 */ 5361 public void setOnContextClickListener(@Nullable OnContextClickListener l) { 5362 if (!isContextClickable()) { 5363 setContextClickable(true); 5364 } 5365 getListenerInfo().mOnContextClickListener = l; 5366 } 5367 5368 /** 5369 * Register a callback to be invoked when the context menu for this view is 5370 * being built. If this view is not long clickable, it becomes long clickable. 5371 * 5372 * @param l The callback that will run 5373 * 5374 */ 5375 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) { 5376 if (!isLongClickable()) { 5377 setLongClickable(true); 5378 } 5379 getListenerInfo().mOnCreateContextMenuListener = l; 5380 } 5381 5382 /** 5383 * Call this view's OnClickListener, if it is defined. Performs all normal 5384 * actions associated with clicking: reporting accessibility event, playing 5385 * a sound, etc. 5386 * 5387 * @return True there was an assigned OnClickListener that was called, false 5388 * otherwise is returned. 5389 */ 5390 public boolean performClick() { 5391 final boolean result; 5392 final ListenerInfo li = mListenerInfo; 5393 if (li != null && li.mOnClickListener != null) { 5394 playSoundEffect(SoundEffectConstants.CLICK); 5395 li.mOnClickListener.onClick(this); 5396 result = true; 5397 } else { 5398 result = false; 5399 } 5400 5401 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 5402 return result; 5403 } 5404 5405 /** 5406 * Directly call any attached OnClickListener. Unlike {@link #performClick()}, 5407 * this only calls the listener, and does not do any associated clicking 5408 * actions like reporting an accessibility event. 5409 * 5410 * @return True there was an assigned OnClickListener that was called, false 5411 * otherwise is returned. 5412 */ 5413 public boolean callOnClick() { 5414 ListenerInfo li = mListenerInfo; 5415 if (li != null && li.mOnClickListener != null) { 5416 li.mOnClickListener.onClick(this); 5417 return true; 5418 } 5419 return false; 5420 } 5421 5422 /** 5423 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5424 * context menu if the OnLongClickListener did not consume the event. 5425 * 5426 * @return {@code true} if one of the above receivers consumed the event, 5427 * {@code false} otherwise 5428 */ 5429 public boolean performLongClick() { 5430 return performLongClickInternal(mLongClickX, mLongClickY); 5431 } 5432 5433 /** 5434 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5435 * context menu if the OnLongClickListener did not consume the event, 5436 * anchoring it to an (x,y) coordinate. 5437 * 5438 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5439 * to disable anchoring 5440 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5441 * to disable anchoring 5442 * @return {@code true} if one of the above receivers consumed the event, 5443 * {@code false} otherwise 5444 */ 5445 public boolean performLongClick(float x, float y) { 5446 mLongClickX = x; 5447 mLongClickY = y; 5448 final boolean handled = performLongClick(); 5449 mLongClickX = Float.NaN; 5450 mLongClickY = Float.NaN; 5451 return handled; 5452 } 5453 5454 /** 5455 * Calls this view's OnLongClickListener, if it is defined. Invokes the 5456 * context menu if the OnLongClickListener did not consume the event, 5457 * optionally anchoring it to an (x,y) coordinate. 5458 * 5459 * @param x x coordinate of the anchoring touch event, or {@link Float#NaN} 5460 * to disable anchoring 5461 * @param y y coordinate of the anchoring touch event, or {@link Float#NaN} 5462 * to disable anchoring 5463 * @return {@code true} if one of the above receivers consumed the event, 5464 * {@code false} otherwise 5465 */ 5466 private boolean performLongClickInternal(float x, float y) { 5467 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 5468 5469 boolean handled = false; 5470 final ListenerInfo li = mListenerInfo; 5471 if (li != null && li.mOnLongClickListener != null) { 5472 handled = li.mOnLongClickListener.onLongClick(View.this); 5473 } 5474 if (!handled) { 5475 final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y); 5476 handled = isAnchored ? showContextMenu(x, y) : showContextMenu(); 5477 } 5478 if (handled) { 5479 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 5480 } 5481 return handled; 5482 } 5483 5484 /** 5485 * Call this view's OnContextClickListener, if it is defined. 5486 * 5487 * @return True if there was an assigned OnContextClickListener that consumed the event, false 5488 * otherwise. 5489 */ 5490 public boolean performContextClick() { 5491 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED); 5492 5493 boolean handled = false; 5494 ListenerInfo li = mListenerInfo; 5495 if (li != null && li.mOnContextClickListener != null) { 5496 handled = li.mOnContextClickListener.onContextClick(View.this); 5497 } 5498 if (handled) { 5499 performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK); 5500 } 5501 return handled; 5502 } 5503 5504 /** 5505 * Performs button-related actions during a touch down event. 5506 * 5507 * @param event The event. 5508 * @return True if the down was consumed. 5509 * 5510 * @hide 5511 */ 5512 protected boolean performButtonActionOnTouchDown(MotionEvent event) { 5513 if (event.isFromSource(InputDevice.SOURCE_MOUSE) && 5514 (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) { 5515 showContextMenu(event.getX(), event.getY()); 5516 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 5517 return true; 5518 } 5519 return false; 5520 } 5521 5522 /** 5523 * Shows the context menu for this view. 5524 * 5525 * @return {@code true} if the context menu was shown, {@code false} 5526 * otherwise 5527 * @see #showContextMenu(float, float) 5528 */ 5529 public boolean showContextMenu() { 5530 return getParent().showContextMenuForChild(this); 5531 } 5532 5533 /** 5534 * Shows the context menu for this view anchored to the specified 5535 * view-relative coordinate. 5536 * 5537 * @param x the X coordinate in pixels relative to the view to which the 5538 * menu should be anchored 5539 * @param y the Y coordinate in pixels relative to the view to which the 5540 * menu should be anchored 5541 * @return {@code true} if the context menu was shown, {@code false} 5542 * otherwise 5543 */ 5544 public boolean showContextMenu(float x, float y) { 5545 return getParent().showContextMenuForChild(this, x, y); 5546 } 5547 5548 /** 5549 * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}. 5550 * 5551 * @param callback Callback that will control the lifecycle of the action mode 5552 * @return The new action mode if it is started, null otherwise 5553 * 5554 * @see ActionMode 5555 * @see #startActionMode(android.view.ActionMode.Callback, int) 5556 */ 5557 public ActionMode startActionMode(ActionMode.Callback callback) { 5558 return startActionMode(callback, ActionMode.TYPE_PRIMARY); 5559 } 5560 5561 /** 5562 * Start an action mode with the given type. 5563 * 5564 * @param callback Callback that will control the lifecycle of the action mode 5565 * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}. 5566 * @return The new action mode if it is started, null otherwise 5567 * 5568 * @see ActionMode 5569 */ 5570 public ActionMode startActionMode(ActionMode.Callback callback, int type) { 5571 ViewParent parent = getParent(); 5572 if (parent == null) return null; 5573 try { 5574 return parent.startActionModeForChild(this, callback, type); 5575 } catch (AbstractMethodError ame) { 5576 // Older implementations of custom views might not implement this. 5577 return parent.startActionModeForChild(this, callback); 5578 } 5579 } 5580 5581 /** 5582 * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's 5583 * Context, creating a unique View identifier to retrieve the result. 5584 * 5585 * @param intent The Intent to be started. 5586 * @param requestCode The request code to use. 5587 * @hide 5588 */ 5589 public void startActivityForResult(Intent intent, int requestCode) { 5590 mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this); 5591 getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null); 5592 } 5593 5594 /** 5595 * If this View corresponds to the calling who, dispatches the activity result. 5596 * @param who The identifier for the targeted View to receive the result. 5597 * @param requestCode The integer request code originally supplied to 5598 * startActivityForResult(), allowing you to identify who this 5599 * result came from. 5600 * @param resultCode The integer result code returned by the child activity 5601 * through its setResult(). 5602 * @param data An Intent, which can return result data to the caller 5603 * (various data can be attached to Intent "extras"). 5604 * @return {@code true} if the activity result was dispatched. 5605 * @hide 5606 */ 5607 public boolean dispatchActivityResult( 5608 String who, int requestCode, int resultCode, Intent data) { 5609 if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) { 5610 onActivityResult(requestCode, resultCode, data); 5611 mStartActivityRequestWho = null; 5612 return true; 5613 } 5614 return false; 5615 } 5616 5617 /** 5618 * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. 5619 * 5620 * @param requestCode The integer request code originally supplied to 5621 * startActivityForResult(), allowing you to identify who this 5622 * result came from. 5623 * @param resultCode The integer result code returned by the child activity 5624 * through its setResult(). 5625 * @param data An Intent, which can return result data to the caller 5626 * (various data can be attached to Intent "extras"). 5627 * @hide 5628 */ 5629 public void onActivityResult(int requestCode, int resultCode, Intent data) { 5630 // Do nothing. 5631 } 5632 5633 /** 5634 * Register a callback to be invoked when a hardware key is pressed in this view. 5635 * Key presses in software input methods will generally not trigger the methods of 5636 * this listener. 5637 * @param l the key listener to attach to this view 5638 */ 5639 public void setOnKeyListener(OnKeyListener l) { 5640 getListenerInfo().mOnKeyListener = l; 5641 } 5642 5643 /** 5644 * Register a callback to be invoked when a touch event is sent to this view. 5645 * @param l the touch listener to attach to this view 5646 */ 5647 public void setOnTouchListener(OnTouchListener l) { 5648 getListenerInfo().mOnTouchListener = l; 5649 } 5650 5651 /** 5652 * Register a callback to be invoked when a generic motion event is sent to this view. 5653 * @param l the generic motion listener to attach to this view 5654 */ 5655 public void setOnGenericMotionListener(OnGenericMotionListener l) { 5656 getListenerInfo().mOnGenericMotionListener = l; 5657 } 5658 5659 /** 5660 * Register a callback to be invoked when a hover event is sent to this view. 5661 * @param l the hover listener to attach to this view 5662 */ 5663 public void setOnHoverListener(OnHoverListener l) { 5664 getListenerInfo().mOnHoverListener = l; 5665 } 5666 5667 /** 5668 * Register a drag event listener callback object for this View. The parameter is 5669 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a 5670 * View, the system calls the 5671 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method. 5672 * @param l An implementation of {@link android.view.View.OnDragListener}. 5673 */ 5674 public void setOnDragListener(OnDragListener l) { 5675 getListenerInfo().mOnDragListener = l; 5676 } 5677 5678 /** 5679 * Give this view focus. This will cause 5680 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called. 5681 * 5682 * Note: this does not check whether this {@link View} should get focus, it just 5683 * gives it focus no matter what. It should only be called internally by framework 5684 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}. 5685 * 5686 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN}, 5687 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which 5688 * focus moved when requestFocus() is called. It may not always 5689 * apply, in which case use the default View.FOCUS_DOWN. 5690 * @param previouslyFocusedRect The rectangle of the view that had focus 5691 * prior in this View's coordinate system. 5692 */ 5693 void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) { 5694 if (DBG) { 5695 System.out.println(this + " requestFocus()"); 5696 } 5697 5698 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) { 5699 mPrivateFlags |= PFLAG_FOCUSED; 5700 5701 View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null; 5702 5703 if (mParent != null) { 5704 mParent.requestChildFocus(this, this); 5705 } 5706 5707 if (mAttachInfo != null) { 5708 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this); 5709 } 5710 5711 onFocusChanged(true, direction, previouslyFocusedRect); 5712 refreshDrawableState(); 5713 } 5714 } 5715 5716 /** 5717 * Populates <code>outRect</code> with the hotspot bounds. By default, 5718 * the hotspot bounds are identical to the screen bounds. 5719 * 5720 * @param outRect rect to populate with hotspot bounds 5721 * @hide Only for internal use by views and widgets. 5722 */ 5723 public void getHotspotBounds(Rect outRect) { 5724 final Drawable background = getBackground(); 5725 if (background != null) { 5726 background.getHotspotBounds(outRect); 5727 } else { 5728 getBoundsOnScreen(outRect); 5729 } 5730 } 5731 5732 /** 5733 * Request that a rectangle of this view be visible on the screen, 5734 * scrolling if necessary just enough. 5735 * 5736 * <p>A View should call this if it maintains some notion of which part 5737 * of its content is interesting. For example, a text editing view 5738 * should call this when its cursor moves. 5739 * 5740 * @param rectangle The rectangle. 5741 * @return Whether any parent scrolled. 5742 */ 5743 public boolean requestRectangleOnScreen(Rect rectangle) { 5744 return requestRectangleOnScreen(rectangle, false); 5745 } 5746 5747 /** 5748 * Request that a rectangle of this view be visible on the screen, 5749 * scrolling if necessary just enough. 5750 * 5751 * <p>A View should call this if it maintains some notion of which part 5752 * of its content is interesting. For example, a text editing view 5753 * should call this when its cursor moves. 5754 * 5755 * <p>When <code>immediate</code> is set to true, scrolling will not be 5756 * animated. 5757 * 5758 * @param rectangle The rectangle. 5759 * @param immediate True to forbid animated scrolling, false otherwise 5760 * @return Whether any parent scrolled. 5761 */ 5762 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) { 5763 if (mParent == null) { 5764 return false; 5765 } 5766 5767 View child = this; 5768 5769 RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF(); 5770 position.set(rectangle); 5771 5772 ViewParent parent = mParent; 5773 boolean scrolled = false; 5774 while (parent != null) { 5775 rectangle.set((int) position.left, (int) position.top, 5776 (int) position.right, (int) position.bottom); 5777 5778 scrolled |= parent.requestChildRectangleOnScreen(child, 5779 rectangle, immediate); 5780 5781 if (!child.hasIdentityMatrix()) { 5782 child.getMatrix().mapRect(position); 5783 } 5784 5785 position.offset(child.mLeft, child.mTop); 5786 5787 if (!(parent instanceof View)) { 5788 break; 5789 } 5790 5791 View parentView = (View) parent; 5792 5793 position.offset(-parentView.getScrollX(), -parentView.getScrollY()); 5794 5795 child = parentView; 5796 parent = child.getParent(); 5797 } 5798 5799 return scrolled; 5800 } 5801 5802 /** 5803 * Called when this view wants to give up focus. If focus is cleared 5804 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called. 5805 * <p> 5806 * <strong>Note:</strong> When a View clears focus the framework is trying 5807 * to give focus to the first focusable View from the top. Hence, if this 5808 * View is the first from the top that can take focus, then all callbacks 5809 * related to clearing focus will be invoked after which the framework will 5810 * give focus to this view. 5811 * </p> 5812 */ 5813 public void clearFocus() { 5814 if (DBG) { 5815 System.out.println(this + " clearFocus()"); 5816 } 5817 5818 clearFocusInternal(null, true, true); 5819 } 5820 5821 /** 5822 * Clears focus from the view, optionally propagating the change up through 5823 * the parent hierarchy and requesting that the root view place new focus. 5824 * 5825 * @param propagate whether to propagate the change up through the parent 5826 * hierarchy 5827 * @param refocus when propagate is true, specifies whether to request the 5828 * root view place new focus 5829 */ 5830 void clearFocusInternal(View focused, boolean propagate, boolean refocus) { 5831 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 5832 mPrivateFlags &= ~PFLAG_FOCUSED; 5833 5834 if (propagate && mParent != null) { 5835 mParent.clearChildFocus(this); 5836 } 5837 5838 onFocusChanged(false, 0, null); 5839 refreshDrawableState(); 5840 5841 if (propagate && (!refocus || !rootViewRequestFocus())) { 5842 notifyGlobalFocusCleared(this); 5843 } 5844 } 5845 } 5846 5847 void notifyGlobalFocusCleared(View oldFocus) { 5848 if (oldFocus != null && mAttachInfo != null) { 5849 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null); 5850 } 5851 } 5852 5853 boolean rootViewRequestFocus() { 5854 final View root = getRootView(); 5855 return root != null && root.requestFocus(); 5856 } 5857 5858 /** 5859 * Called internally by the view system when a new view is getting focus. 5860 * This is what clears the old focus. 5861 * <p> 5862 * <b>NOTE:</b> The parent view's focused child must be updated manually 5863 * after calling this method. Otherwise, the view hierarchy may be left in 5864 * an inconstent state. 5865 */ 5866 void unFocus(View focused) { 5867 if (DBG) { 5868 System.out.println(this + " unFocus()"); 5869 } 5870 5871 clearFocusInternal(focused, false, false); 5872 } 5873 5874 /** 5875 * Returns true if this view has focus itself, or is the ancestor of the 5876 * view that has focus. 5877 * 5878 * @return True if this view has or contains focus, false otherwise. 5879 */ 5880 @ViewDebug.ExportedProperty(category = "focus") 5881 public boolean hasFocus() { 5882 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 5883 } 5884 5885 /** 5886 * Returns true if this view is focusable or if it contains a reachable View 5887 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()" 5888 * is a View whose parents do not block descendants focus. 5889 * 5890 * Only {@link #VISIBLE} views are considered focusable. 5891 * 5892 * @return True if the view is focusable or if the view contains a focusable 5893 * View, false otherwise. 5894 * 5895 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS 5896 * @see ViewGroup#getTouchscreenBlocksFocus() 5897 */ 5898 public boolean hasFocusable() { 5899 if (!isFocusableInTouchMode()) { 5900 for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) { 5901 final ViewGroup g = (ViewGroup) p; 5902 if (g.shouldBlockFocusForTouchscreen()) { 5903 return false; 5904 } 5905 } 5906 } 5907 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable(); 5908 } 5909 5910 /** 5911 * Called by the view system when the focus state of this view changes. 5912 * When the focus change event is caused by directional navigation, direction 5913 * and previouslyFocusedRect provide insight into where the focus is coming from. 5914 * When overriding, be sure to call up through to the super class so that 5915 * the standard focus handling will occur. 5916 * 5917 * @param gainFocus True if the View has focus; false otherwise. 5918 * @param direction The direction focus has moved when requestFocus() 5919 * is called to give this view focus. Values are 5920 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT}, 5921 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}. 5922 * It may not always apply, in which case use the default. 5923 * @param previouslyFocusedRect The rectangle, in this view's coordinate 5924 * system, of the previously focused view. If applicable, this will be 5925 * passed in as finer grained information about where the focus is coming 5926 * from (in addition to direction). Will be <code>null</code> otherwise. 5927 */ 5928 @CallSuper 5929 protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, 5930 @Nullable Rect previouslyFocusedRect) { 5931 if (gainFocus) { 5932 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); 5933 } else { 5934 notifyViewAccessibilityStateChangedIfNeeded( 5935 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 5936 } 5937 5938 InputMethodManager imm = InputMethodManager.peekInstance(); 5939 if (!gainFocus) { 5940 if (isPressed()) { 5941 setPressed(false); 5942 } 5943 if (imm != null && mAttachInfo != null 5944 && mAttachInfo.mHasWindowFocus) { 5945 imm.focusOut(this); 5946 } 5947 onFocusLost(); 5948 } else if (imm != null && mAttachInfo != null 5949 && mAttachInfo.mHasWindowFocus) { 5950 imm.focusIn(this); 5951 } 5952 5953 invalidate(true); 5954 ListenerInfo li = mListenerInfo; 5955 if (li != null && li.mOnFocusChangeListener != null) { 5956 li.mOnFocusChangeListener.onFocusChange(this, gainFocus); 5957 } 5958 5959 if (mAttachInfo != null) { 5960 mAttachInfo.mKeyDispatchState.reset(this); 5961 } 5962 } 5963 5964 /** 5965 * Sends an accessibility event of the given type. If accessibility is 5966 * not enabled this method has no effect. The default implementation calls 5967 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first 5968 * to populate information about the event source (this View), then calls 5969 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to 5970 * populate the text content of the event source including its descendants, 5971 * and last calls 5972 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)} 5973 * on its parent to request sending of the event to interested parties. 5974 * <p> 5975 * If an {@link AccessibilityDelegate} has been specified via calling 5976 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 5977 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is 5978 * responsible for handling this call. 5979 * </p> 5980 * 5981 * @param eventType The type of the event to send, as defined by several types from 5982 * {@link android.view.accessibility.AccessibilityEvent}, such as 5983 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or 5984 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}. 5985 * 5986 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 5987 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 5988 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent) 5989 * @see AccessibilityDelegate 5990 */ 5991 public void sendAccessibilityEvent(int eventType) { 5992 if (mAccessibilityDelegate != null) { 5993 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType); 5994 } else { 5995 sendAccessibilityEventInternal(eventType); 5996 } 5997 } 5998 5999 /** 6000 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT} 6001 * {@link AccessibilityEvent} to make an announcement which is related to some 6002 * sort of a context change for which none of the events representing UI transitions 6003 * is a good fit. For example, announcing a new page in a book. If accessibility 6004 * is not enabled this method does nothing. 6005 * 6006 * @param text The announcement text. 6007 */ 6008 public void announceForAccessibility(CharSequence text) { 6009 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) { 6010 AccessibilityEvent event = AccessibilityEvent.obtain( 6011 AccessibilityEvent.TYPE_ANNOUNCEMENT); 6012 onInitializeAccessibilityEvent(event); 6013 event.getText().add(text); 6014 event.setContentDescription(null); 6015 mParent.requestSendAccessibilityEvent(this, event); 6016 } 6017 } 6018 6019 /** 6020 * @see #sendAccessibilityEvent(int) 6021 * 6022 * Note: Called from the default {@link AccessibilityDelegate}. 6023 * 6024 * @hide 6025 */ 6026 public void sendAccessibilityEventInternal(int eventType) { 6027 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 6028 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType)); 6029 } 6030 } 6031 6032 /** 6033 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but 6034 * takes as an argument an empty {@link AccessibilityEvent} and does not 6035 * perform a check whether accessibility is enabled. 6036 * <p> 6037 * If an {@link AccessibilityDelegate} has been specified via calling 6038 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6039 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)} 6040 * is responsible for handling this call. 6041 * </p> 6042 * 6043 * @param event The event to send. 6044 * 6045 * @see #sendAccessibilityEvent(int) 6046 */ 6047 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) { 6048 if (mAccessibilityDelegate != null) { 6049 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event); 6050 } else { 6051 sendAccessibilityEventUncheckedInternal(event); 6052 } 6053 } 6054 6055 /** 6056 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent) 6057 * 6058 * Note: Called from the default {@link AccessibilityDelegate}. 6059 * 6060 * @hide 6061 */ 6062 public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) { 6063 if (!isShown()) { 6064 return; 6065 } 6066 onInitializeAccessibilityEvent(event); 6067 // Only a subset of accessibility events populates text content. 6068 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) { 6069 dispatchPopulateAccessibilityEvent(event); 6070 } 6071 // In the beginning we called #isShown(), so we know that getParent() is not null. 6072 getParent().requestSendAccessibilityEvent(this, event); 6073 } 6074 6075 /** 6076 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then 6077 * to its children for adding their text content to the event. Note that the 6078 * event text is populated in a separate dispatch path since we add to the 6079 * event not only the text of the source but also the text of all its descendants. 6080 * A typical implementation will call 6081 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view 6082 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6083 * on each child. Override this method if custom population of the event text 6084 * content is required. 6085 * <p> 6086 * If an {@link AccessibilityDelegate} has been specified via calling 6087 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6088 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)} 6089 * is responsible for handling this call. 6090 * </p> 6091 * <p> 6092 * <em>Note:</em> Accessibility events of certain types are not dispatched for 6093 * populating the event text via this method. For details refer to {@link AccessibilityEvent}. 6094 * </p> 6095 * 6096 * @param event The event. 6097 * 6098 * @return True if the event population was completed. 6099 */ 6100 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 6101 if (mAccessibilityDelegate != null) { 6102 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event); 6103 } else { 6104 return dispatchPopulateAccessibilityEventInternal(event); 6105 } 6106 } 6107 6108 /** 6109 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6110 * 6111 * Note: Called from the default {@link AccessibilityDelegate}. 6112 * 6113 * @hide 6114 */ 6115 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6116 onPopulateAccessibilityEvent(event); 6117 return false; 6118 } 6119 6120 /** 6121 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} 6122 * giving a chance to this View to populate the accessibility event with its 6123 * text content. While this method is free to modify event 6124 * attributes other than text content, doing so should normally be performed in 6125 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}. 6126 * <p> 6127 * Example: Adding formatted date string to an accessibility event in addition 6128 * to the text added by the super implementation: 6129 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6130 * super.onPopulateAccessibilityEvent(event); 6131 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY; 6132 * String selectedDateUtterance = DateUtils.formatDateTime(mContext, 6133 * mCurrentDate.getTimeInMillis(), flags); 6134 * event.getText().add(selectedDateUtterance); 6135 * }</pre> 6136 * <p> 6137 * If an {@link AccessibilityDelegate} has been specified via calling 6138 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6139 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)} 6140 * is responsible for handling this call. 6141 * </p> 6142 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6143 * information to the event, in case the default implementation has basic information to add. 6144 * </p> 6145 * 6146 * @param event The accessibility event which to populate. 6147 * 6148 * @see #sendAccessibilityEvent(int) 6149 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6150 */ 6151 @CallSuper 6152 public void onPopulateAccessibilityEvent(AccessibilityEvent event) { 6153 if (mAccessibilityDelegate != null) { 6154 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event); 6155 } else { 6156 onPopulateAccessibilityEventInternal(event); 6157 } 6158 } 6159 6160 /** 6161 * @see #onPopulateAccessibilityEvent(AccessibilityEvent) 6162 * 6163 * Note: Called from the default {@link AccessibilityDelegate}. 6164 * 6165 * @hide 6166 */ 6167 public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) { 6168 } 6169 6170 /** 6171 * Initializes an {@link AccessibilityEvent} with information about 6172 * this View which is the event source. In other words, the source of 6173 * an accessibility event is the view whose state change triggered firing 6174 * the event. 6175 * <p> 6176 * Example: Setting the password property of an event in addition 6177 * to properties set by the super implementation: 6178 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6179 * super.onInitializeAccessibilityEvent(event); 6180 * event.setPassword(true); 6181 * }</pre> 6182 * <p> 6183 * If an {@link AccessibilityDelegate} has been specified via calling 6184 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6185 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)} 6186 * is responsible for handling this call. 6187 * </p> 6188 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding 6189 * information to the event, in case the default implementation has basic information to add. 6190 * </p> 6191 * @param event The event to initialize. 6192 * 6193 * @see #sendAccessibilityEvent(int) 6194 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent) 6195 */ 6196 @CallSuper 6197 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 6198 if (mAccessibilityDelegate != null) { 6199 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event); 6200 } else { 6201 onInitializeAccessibilityEventInternal(event); 6202 } 6203 } 6204 6205 /** 6206 * @see #onInitializeAccessibilityEvent(AccessibilityEvent) 6207 * 6208 * Note: Called from the default {@link AccessibilityDelegate}. 6209 * 6210 * @hide 6211 */ 6212 public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) { 6213 event.setSource(this); 6214 event.setClassName(getAccessibilityClassName()); 6215 event.setPackageName(getContext().getPackageName()); 6216 event.setEnabled(isEnabled()); 6217 event.setContentDescription(mContentDescription); 6218 6219 switch (event.getEventType()) { 6220 case AccessibilityEvent.TYPE_VIEW_FOCUSED: { 6221 ArrayList<View> focusablesTempList = (mAttachInfo != null) 6222 ? mAttachInfo.mTempArrayList : new ArrayList<View>(); 6223 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL); 6224 event.setItemCount(focusablesTempList.size()); 6225 event.setCurrentItemIndex(focusablesTempList.indexOf(this)); 6226 if (mAttachInfo != null) { 6227 focusablesTempList.clear(); 6228 } 6229 } break; 6230 case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: { 6231 CharSequence text = getIterableTextForAccessibility(); 6232 if (text != null && text.length() > 0) { 6233 event.setFromIndex(getAccessibilitySelectionStart()); 6234 event.setToIndex(getAccessibilitySelectionEnd()); 6235 event.setItemCount(text.length()); 6236 } 6237 } break; 6238 } 6239 } 6240 6241 /** 6242 * Returns an {@link AccessibilityNodeInfo} representing this view from the 6243 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 6244 * This method is responsible for obtaining an accessibility node info from a 6245 * pool of reusable instances and calling 6246 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to 6247 * initialize the former. 6248 * <p> 6249 * Note: The client is responsible for recycling the obtained instance by calling 6250 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation. 6251 * </p> 6252 * 6253 * @return A populated {@link AccessibilityNodeInfo}. 6254 * 6255 * @see AccessibilityNodeInfo 6256 */ 6257 public AccessibilityNodeInfo createAccessibilityNodeInfo() { 6258 if (mAccessibilityDelegate != null) { 6259 return mAccessibilityDelegate.createAccessibilityNodeInfo(this); 6260 } else { 6261 return createAccessibilityNodeInfoInternal(); 6262 } 6263 } 6264 6265 /** 6266 * @see #createAccessibilityNodeInfo() 6267 * 6268 * @hide 6269 */ 6270 public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() { 6271 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6272 if (provider != null) { 6273 return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID); 6274 } else { 6275 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this); 6276 onInitializeAccessibilityNodeInfo(info); 6277 return info; 6278 } 6279 } 6280 6281 /** 6282 * Initializes an {@link AccessibilityNodeInfo} with information about this view. 6283 * The base implementation sets: 6284 * <ul> 6285 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li> 6286 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li> 6287 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li> 6288 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li> 6289 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li> 6290 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li> 6291 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li> 6292 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li> 6293 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li> 6294 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li> 6295 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li> 6296 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li> 6297 * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li> 6298 * </ul> 6299 * <p> 6300 * Subclasses should override this method, call the super implementation, 6301 * and set additional attributes. 6302 * </p> 6303 * <p> 6304 * If an {@link AccessibilityDelegate} has been specified via calling 6305 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6306 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)} 6307 * is responsible for handling this call. 6308 * </p> 6309 * 6310 * @param info The instance to initialize. 6311 */ 6312 @CallSuper 6313 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 6314 if (mAccessibilityDelegate != null) { 6315 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info); 6316 } else { 6317 onInitializeAccessibilityNodeInfoInternal(info); 6318 } 6319 } 6320 6321 /** 6322 * Gets the location of this view in screen coordinates. 6323 * 6324 * @param outRect The output location 6325 * @hide 6326 */ 6327 public void getBoundsOnScreen(Rect outRect) { 6328 getBoundsOnScreen(outRect, false); 6329 } 6330 6331 /** 6332 * Gets the location of this view in screen coordinates. 6333 * 6334 * @param outRect The output location 6335 * @param clipToParent Whether to clip child bounds to the parent ones. 6336 * @hide 6337 */ 6338 public void getBoundsOnScreen(Rect outRect, boolean clipToParent) { 6339 if (mAttachInfo == null) { 6340 return; 6341 } 6342 6343 RectF position = mAttachInfo.mTmpTransformRect; 6344 position.set(0, 0, mRight - mLeft, mBottom - mTop); 6345 6346 if (!hasIdentityMatrix()) { 6347 getMatrix().mapRect(position); 6348 } 6349 6350 position.offset(mLeft, mTop); 6351 6352 ViewParent parent = mParent; 6353 while (parent instanceof View) { 6354 View parentView = (View) parent; 6355 6356 position.offset(-parentView.mScrollX, -parentView.mScrollY); 6357 6358 if (clipToParent) { 6359 position.left = Math.max(position.left, 0); 6360 position.top = Math.max(position.top, 0); 6361 position.right = Math.min(position.right, parentView.getWidth()); 6362 position.bottom = Math.min(position.bottom, parentView.getHeight()); 6363 } 6364 6365 if (!parentView.hasIdentityMatrix()) { 6366 parentView.getMatrix().mapRect(position); 6367 } 6368 6369 position.offset(parentView.mLeft, parentView.mTop); 6370 6371 parent = parentView.mParent; 6372 } 6373 6374 if (parent instanceof ViewRootImpl) { 6375 ViewRootImpl viewRootImpl = (ViewRootImpl) parent; 6376 position.offset(0, -viewRootImpl.mCurScrollY); 6377 } 6378 6379 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop); 6380 6381 outRect.set(Math.round(position.left), Math.round(position.top), 6382 Math.round(position.right), Math.round(position.bottom)); 6383 } 6384 6385 /** 6386 * Return the class name of this object to be used for accessibility purposes. 6387 * Subclasses should only override this if they are implementing something that 6388 * should be seen as a completely new class of view when used by accessibility, 6389 * unrelated to the class it is deriving from. This is used to fill in 6390 * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}. 6391 */ 6392 public CharSequence getAccessibilityClassName() { 6393 return View.class.getName(); 6394 } 6395 6396 /** 6397 * Called when assist structure is being retrieved from a view as part of 6398 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. 6399 * @param structure Fill in with structured view data. The default implementation 6400 * fills in all data that can be inferred from the view itself. 6401 */ 6402 public void onProvideStructure(ViewStructure structure) { 6403 final int id = mID; 6404 if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0 6405 && (id&0x0000ffff) != 0) { 6406 String pkg, type, entry; 6407 try { 6408 final Resources res = getResources(); 6409 entry = res.getResourceEntryName(id); 6410 type = res.getResourceTypeName(id); 6411 pkg = res.getResourcePackageName(id); 6412 } catch (Resources.NotFoundException e) { 6413 entry = type = pkg = null; 6414 } 6415 structure.setId(id, pkg, type, entry); 6416 } else { 6417 structure.setId(id, null, null, null); 6418 } 6419 structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); 6420 if (!hasIdentityMatrix()) { 6421 structure.setTransformation(getMatrix()); 6422 } 6423 structure.setElevation(getZ()); 6424 structure.setVisibility(getVisibility()); 6425 structure.setEnabled(isEnabled()); 6426 if (isClickable()) { 6427 structure.setClickable(true); 6428 } 6429 if (isFocusable()) { 6430 structure.setFocusable(true); 6431 } 6432 if (isFocused()) { 6433 structure.setFocused(true); 6434 } 6435 if (isAccessibilityFocused()) { 6436 structure.setAccessibilityFocused(true); 6437 } 6438 if (isSelected()) { 6439 structure.setSelected(true); 6440 } 6441 if (isActivated()) { 6442 structure.setActivated(true); 6443 } 6444 if (isLongClickable()) { 6445 structure.setLongClickable(true); 6446 } 6447 if (this instanceof Checkable) { 6448 structure.setCheckable(true); 6449 if (((Checkable)this).isChecked()) { 6450 structure.setChecked(true); 6451 } 6452 } 6453 if (isContextClickable()) { 6454 structure.setContextClickable(true); 6455 } 6456 structure.setClassName(getAccessibilityClassName().toString()); 6457 structure.setContentDescription(getContentDescription()); 6458 } 6459 6460 /** 6461 * Called when assist structure is being retrieved from a view as part of 6462 * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to 6463 * generate additional virtual structure under this view. The defaullt implementation 6464 * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the 6465 * view's virtual accessibility nodes, if any. You can override this for a more 6466 * optimal implementation providing this data. 6467 */ 6468 public void onProvideVirtualStructure(ViewStructure structure) { 6469 AccessibilityNodeProvider provider = getAccessibilityNodeProvider(); 6470 if (provider != null) { 6471 AccessibilityNodeInfo info = createAccessibilityNodeInfo(); 6472 structure.setChildCount(1); 6473 ViewStructure root = structure.newChild(0); 6474 populateVirtualStructure(root, provider, info); 6475 info.recycle(); 6476 } 6477 } 6478 6479 private void populateVirtualStructure(ViewStructure structure, 6480 AccessibilityNodeProvider provider, AccessibilityNodeInfo info) { 6481 structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()), 6482 null, null, null); 6483 Rect rect = structure.getTempRect(); 6484 info.getBoundsInParent(rect); 6485 structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height()); 6486 structure.setVisibility(VISIBLE); 6487 structure.setEnabled(info.isEnabled()); 6488 if (info.isClickable()) { 6489 structure.setClickable(true); 6490 } 6491 if (info.isFocusable()) { 6492 structure.setFocusable(true); 6493 } 6494 if (info.isFocused()) { 6495 structure.setFocused(true); 6496 } 6497 if (info.isAccessibilityFocused()) { 6498 structure.setAccessibilityFocused(true); 6499 } 6500 if (info.isSelected()) { 6501 structure.setSelected(true); 6502 } 6503 if (info.isLongClickable()) { 6504 structure.setLongClickable(true); 6505 } 6506 if (info.isCheckable()) { 6507 structure.setCheckable(true); 6508 if (info.isChecked()) { 6509 structure.setChecked(true); 6510 } 6511 } 6512 if (info.isContextClickable()) { 6513 structure.setContextClickable(true); 6514 } 6515 CharSequence cname = info.getClassName(); 6516 structure.setClassName(cname != null ? cname.toString() : null); 6517 structure.setContentDescription(info.getContentDescription()); 6518 if (info.getText() != null || info.getError() != null) { 6519 structure.setText(info.getText(), info.getTextSelectionStart(), 6520 info.getTextSelectionEnd()); 6521 } 6522 final int NCHILDREN = info.getChildCount(); 6523 if (NCHILDREN > 0) { 6524 structure.setChildCount(NCHILDREN); 6525 for (int i=0; i<NCHILDREN; i++) { 6526 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo( 6527 AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i))); 6528 ViewStructure child = structure.newChild(i); 6529 populateVirtualStructure(child, provider, cinfo); 6530 cinfo.recycle(); 6531 } 6532 } 6533 } 6534 6535 /** 6536 * Dispatch creation of {@link ViewStructure} down the hierarchy. The default 6537 * implementation calls {@link #onProvideStructure} and 6538 * {@link #onProvideVirtualStructure}. 6539 */ 6540 public void dispatchProvideStructure(ViewStructure structure) { 6541 if (!isAssistBlocked()) { 6542 onProvideStructure(structure); 6543 onProvideVirtualStructure(structure); 6544 } else { 6545 structure.setClassName(getAccessibilityClassName().toString()); 6546 structure.setAssistBlocked(true); 6547 } 6548 } 6549 6550 /** 6551 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 6552 * 6553 * Note: Called from the default {@link AccessibilityDelegate}. 6554 * 6555 * @hide 6556 */ 6557 public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 6558 if (mAttachInfo == null) { 6559 return; 6560 } 6561 6562 Rect bounds = mAttachInfo.mTmpInvalRect; 6563 6564 getDrawingRect(bounds); 6565 info.setBoundsInParent(bounds); 6566 6567 getBoundsOnScreen(bounds, true); 6568 info.setBoundsInScreen(bounds); 6569 6570 ViewParent parent = getParentForAccessibility(); 6571 if (parent instanceof View) { 6572 info.setParent((View) parent); 6573 } 6574 6575 if (mID != View.NO_ID) { 6576 View rootView = getRootView(); 6577 if (rootView == null) { 6578 rootView = this; 6579 } 6580 6581 View label = rootView.findLabelForView(this, mID); 6582 if (label != null) { 6583 info.setLabeledBy(label); 6584 } 6585 6586 if ((mAttachInfo.mAccessibilityFetchFlags 6587 & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0 6588 && Resources.resourceHasPackage(mID)) { 6589 try { 6590 String viewId = getResources().getResourceName(mID); 6591 info.setViewIdResourceName(viewId); 6592 } catch (Resources.NotFoundException nfe) { 6593 /* ignore */ 6594 } 6595 } 6596 } 6597 6598 if (mLabelForId != View.NO_ID) { 6599 View rootView = getRootView(); 6600 if (rootView == null) { 6601 rootView = this; 6602 } 6603 View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId); 6604 if (labeled != null) { 6605 info.setLabelFor(labeled); 6606 } 6607 } 6608 6609 if (mAccessibilityTraversalBeforeId != View.NO_ID) { 6610 View rootView = getRootView(); 6611 if (rootView == null) { 6612 rootView = this; 6613 } 6614 View next = rootView.findViewInsideOutShouldExist(this, 6615 mAccessibilityTraversalBeforeId); 6616 if (next != null && next.includeForAccessibility()) { 6617 info.setTraversalBefore(next); 6618 } 6619 } 6620 6621 if (mAccessibilityTraversalAfterId != View.NO_ID) { 6622 View rootView = getRootView(); 6623 if (rootView == null) { 6624 rootView = this; 6625 } 6626 View next = rootView.findViewInsideOutShouldExist(this, 6627 mAccessibilityTraversalAfterId); 6628 if (next != null && next.includeForAccessibility()) { 6629 info.setTraversalAfter(next); 6630 } 6631 } 6632 6633 info.setVisibleToUser(isVisibleToUser()); 6634 6635 info.setPackageName(mContext.getPackageName()); 6636 info.setClassName(getAccessibilityClassName()); 6637 info.setContentDescription(getContentDescription()); 6638 6639 info.setEnabled(isEnabled()); 6640 info.setClickable(isClickable()); 6641 info.setFocusable(isFocusable()); 6642 info.setFocused(isFocused()); 6643 info.setAccessibilityFocused(isAccessibilityFocused()); 6644 info.setSelected(isSelected()); 6645 info.setLongClickable(isLongClickable()); 6646 info.setContextClickable(isContextClickable()); 6647 info.setLiveRegion(getAccessibilityLiveRegion()); 6648 6649 // TODO: These make sense only if we are in an AdapterView but all 6650 // views can be selected. Maybe from accessibility perspective 6651 // we should report as selectable view in an AdapterView. 6652 info.addAction(AccessibilityNodeInfo.ACTION_SELECT); 6653 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION); 6654 6655 if (isFocusable()) { 6656 if (isFocused()) { 6657 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); 6658 } else { 6659 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS); 6660 } 6661 } 6662 6663 if (!isAccessibilityFocused()) { 6664 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 6665 } else { 6666 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS); 6667 } 6668 6669 if (isClickable() && isEnabled()) { 6670 info.addAction(AccessibilityNodeInfo.ACTION_CLICK); 6671 } 6672 6673 if (isLongClickable() && isEnabled()) { 6674 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); 6675 } 6676 6677 if (isContextClickable() && isEnabled()) { 6678 info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK); 6679 } 6680 6681 CharSequence text = getIterableTextForAccessibility(); 6682 if (text != null && text.length() > 0) { 6683 info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd()); 6684 6685 info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); 6686 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY); 6687 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY); 6688 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER 6689 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD 6690 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH); 6691 } 6692 6693 info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); 6694 } 6695 6696 private View findLabelForView(View view, int labeledId) { 6697 if (mMatchLabelForPredicate == null) { 6698 mMatchLabelForPredicate = new MatchLabelForPredicate(); 6699 } 6700 mMatchLabelForPredicate.mLabeledId = labeledId; 6701 return findViewByPredicateInsideOut(view, mMatchLabelForPredicate); 6702 } 6703 6704 /** 6705 * Computes whether this view is visible to the user. Such a view is 6706 * attached, visible, all its predecessors are visible, it is not clipped 6707 * entirely by its predecessors, and has an alpha greater than zero. 6708 * 6709 * @return Whether the view is visible on the screen. 6710 * 6711 * @hide 6712 */ 6713 protected boolean isVisibleToUser() { 6714 return isVisibleToUser(null); 6715 } 6716 6717 /** 6718 * Computes whether the given portion of this view is visible to the user. 6719 * Such a view is attached, visible, all its predecessors are visible, 6720 * has an alpha greater than zero, and the specified portion is not 6721 * clipped entirely by its predecessors. 6722 * 6723 * @param boundInView the portion of the view to test; coordinates should be relative; may be 6724 * <code>null</code>, and the entire view will be tested in this case. 6725 * When <code>true</code> is returned by the function, the actual visible 6726 * region will be stored in this parameter; that is, if boundInView is fully 6727 * contained within the view, no modification will be made, otherwise regions 6728 * outside of the visible area of the view will be clipped. 6729 * 6730 * @return Whether the specified portion of the view is visible on the screen. 6731 * 6732 * @hide 6733 */ 6734 protected boolean isVisibleToUser(Rect boundInView) { 6735 if (mAttachInfo != null) { 6736 // Attached to invisible window means this view is not visible. 6737 if (mAttachInfo.mWindowVisibility != View.VISIBLE) { 6738 return false; 6739 } 6740 // An invisible predecessor or one with alpha zero means 6741 // that this view is not visible to the user. 6742 Object current = this; 6743 while (current instanceof View) { 6744 View view = (View) current; 6745 // We have attach info so this view is attached and there is no 6746 // need to check whether we reach to ViewRootImpl on the way up. 6747 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 || 6748 view.getVisibility() != VISIBLE) { 6749 return false; 6750 } 6751 current = view.mParent; 6752 } 6753 // Check if the view is entirely covered by its predecessors. 6754 Rect visibleRect = mAttachInfo.mTmpInvalRect; 6755 Point offset = mAttachInfo.mPoint; 6756 if (!getGlobalVisibleRect(visibleRect, offset)) { 6757 return false; 6758 } 6759 // Check if the visible portion intersects the rectangle of interest. 6760 if (boundInView != null) { 6761 visibleRect.offset(-offset.x, -offset.y); 6762 return boundInView.intersect(visibleRect); 6763 } 6764 return true; 6765 } 6766 return false; 6767 } 6768 6769 /** 6770 * Returns the delegate for implementing accessibility support via 6771 * composition. For more details see {@link AccessibilityDelegate}. 6772 * 6773 * @return The delegate, or null if none set. 6774 * 6775 * @hide 6776 */ 6777 public AccessibilityDelegate getAccessibilityDelegate() { 6778 return mAccessibilityDelegate; 6779 } 6780 6781 /** 6782 * Sets a delegate for implementing accessibility support via composition 6783 * (as opposed to inheritance). For more details, see 6784 * {@link AccessibilityDelegate}. 6785 * <p> 6786 * <strong>Note:</strong> On platform versions prior to 6787 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 6788 * views in the {@code android.widget.*} package are called <i>before</i> 6789 * host methods. This prevents certain properties such as class name from 6790 * being modified by overriding 6791 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 6792 * as any changes will be overwritten by the host class. 6793 * <p> 6794 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 6795 * methods are called <i>after</i> host methods, which all properties to be 6796 * modified without being overwritten by the host class. 6797 * 6798 * @param delegate the object to which accessibility method calls should be 6799 * delegated 6800 * @see AccessibilityDelegate 6801 */ 6802 public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) { 6803 mAccessibilityDelegate = delegate; 6804 } 6805 6806 /** 6807 * Gets the provider for managing a virtual view hierarchy rooted at this View 6808 * and reported to {@link android.accessibilityservice.AccessibilityService}s 6809 * that explore the window content. 6810 * <p> 6811 * If this method returns an instance, this instance is responsible for managing 6812 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this 6813 * View including the one representing the View itself. Similarly the returned 6814 * instance is responsible for performing accessibility actions on any virtual 6815 * view or the root view itself. 6816 * </p> 6817 * <p> 6818 * If an {@link AccessibilityDelegate} has been specified via calling 6819 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 6820 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)} 6821 * is responsible for handling this call. 6822 * </p> 6823 * 6824 * @return The provider. 6825 * 6826 * @see AccessibilityNodeProvider 6827 */ 6828 public AccessibilityNodeProvider getAccessibilityNodeProvider() { 6829 if (mAccessibilityDelegate != null) { 6830 return mAccessibilityDelegate.getAccessibilityNodeProvider(this); 6831 } else { 6832 return null; 6833 } 6834 } 6835 6836 /** 6837 * Gets the unique identifier of this view on the screen for accessibility purposes. 6838 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned. 6839 * 6840 * @return The view accessibility id. 6841 * 6842 * @hide 6843 */ 6844 public int getAccessibilityViewId() { 6845 if (mAccessibilityViewId == NO_ID) { 6846 mAccessibilityViewId = sNextAccessibilityViewId++; 6847 } 6848 return mAccessibilityViewId; 6849 } 6850 6851 /** 6852 * Gets the unique identifier of the window in which this View reseides. 6853 * 6854 * @return The window accessibility id. 6855 * 6856 * @hide 6857 */ 6858 public int getAccessibilityWindowId() { 6859 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId 6860 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 6861 } 6862 6863 /** 6864 * Returns the {@link View}'s content description. 6865 * <p> 6866 * <strong>Note:</strong> Do not override this method, as it will have no 6867 * effect on the content description presented to accessibility services. 6868 * You must call {@link #setContentDescription(CharSequence)} to modify the 6869 * content description. 6870 * 6871 * @return the content description 6872 * @see #setContentDescription(CharSequence) 6873 * @attr ref android.R.styleable#View_contentDescription 6874 */ 6875 @ViewDebug.ExportedProperty(category = "accessibility") 6876 public CharSequence getContentDescription() { 6877 return mContentDescription; 6878 } 6879 6880 /** 6881 * Sets the {@link View}'s content description. 6882 * <p> 6883 * A content description briefly describes the view and is primarily used 6884 * for accessibility support to determine how a view should be presented to 6885 * the user. In the case of a view with no textual representation, such as 6886 * {@link android.widget.ImageButton}, a useful content description 6887 * explains what the view does. For example, an image button with a phone 6888 * icon that is used to place a call may use "Call" as its content 6889 * description. An image of a floppy disk that is used to save a file may 6890 * use "Save". 6891 * 6892 * @param contentDescription The content description. 6893 * @see #getContentDescription() 6894 * @attr ref android.R.styleable#View_contentDescription 6895 */ 6896 @RemotableViewMethod 6897 public void setContentDescription(CharSequence contentDescription) { 6898 if (mContentDescription == null) { 6899 if (contentDescription == null) { 6900 return; 6901 } 6902 } else if (mContentDescription.equals(contentDescription)) { 6903 return; 6904 } 6905 mContentDescription = contentDescription; 6906 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0; 6907 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { 6908 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); 6909 notifySubtreeAccessibilityStateChangedIfNeeded(); 6910 } else { 6911 notifyViewAccessibilityStateChangedIfNeeded( 6912 AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); 6913 } 6914 } 6915 6916 /** 6917 * Sets the id of a view before which this one is visited in accessibility traversal. 6918 * A screen-reader must visit the content of this view before the content of the one 6919 * it precedes. For example, if view B is set to be before view A, then a screen-reader 6920 * will traverse the entire content of B before traversing the entire content of A, 6921 * regardles of what traversal strategy it is using. 6922 * <p> 6923 * Views that do not have specified before/after relationships are traversed in order 6924 * determined by the screen-reader. 6925 * </p> 6926 * <p> 6927 * Setting that this view is before a view that is not important for accessibility 6928 * or if this view is not important for accessibility will have no effect as the 6929 * screen-reader is not aware of unimportant views. 6930 * </p> 6931 * 6932 * @param beforeId The id of a view this one precedes in accessibility traversal. 6933 * 6934 * @attr ref android.R.styleable#View_accessibilityTraversalBefore 6935 * 6936 * @see #setImportantForAccessibility(int) 6937 */ 6938 @RemotableViewMethod 6939 public void setAccessibilityTraversalBefore(int beforeId) { 6940 if (mAccessibilityTraversalBeforeId == beforeId) { 6941 return; 6942 } 6943 mAccessibilityTraversalBeforeId = beforeId; 6944 notifyViewAccessibilityStateChangedIfNeeded( 6945 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 6946 } 6947 6948 /** 6949 * Gets the id of a view before which this one is visited in accessibility traversal. 6950 * 6951 * @return The id of a view this one precedes in accessibility traversal if 6952 * specified, otherwise {@link #NO_ID}. 6953 * 6954 * @see #setAccessibilityTraversalBefore(int) 6955 */ 6956 public int getAccessibilityTraversalBefore() { 6957 return mAccessibilityTraversalBeforeId; 6958 } 6959 6960 /** 6961 * Sets the id of a view after which this one is visited in accessibility traversal. 6962 * A screen-reader must visit the content of the other view before the content of this 6963 * one. For example, if view B is set to be after view A, then a screen-reader 6964 * will traverse the entire content of A before traversing the entire content of B, 6965 * regardles of what traversal strategy it is using. 6966 * <p> 6967 * Views that do not have specified before/after relationships are traversed in order 6968 * determined by the screen-reader. 6969 * </p> 6970 * <p> 6971 * Setting that this view is after a view that is not important for accessibility 6972 * or if this view is not important for accessibility will have no effect as the 6973 * screen-reader is not aware of unimportant views. 6974 * </p> 6975 * 6976 * @param afterId The id of a view this one succedees in accessibility traversal. 6977 * 6978 * @attr ref android.R.styleable#View_accessibilityTraversalAfter 6979 * 6980 * @see #setImportantForAccessibility(int) 6981 */ 6982 @RemotableViewMethod 6983 public void setAccessibilityTraversalAfter(int afterId) { 6984 if (mAccessibilityTraversalAfterId == afterId) { 6985 return; 6986 } 6987 mAccessibilityTraversalAfterId = afterId; 6988 notifyViewAccessibilityStateChangedIfNeeded( 6989 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 6990 } 6991 6992 /** 6993 * Gets the id of a view after which this one is visited in accessibility traversal. 6994 * 6995 * @return The id of a view this one succeedes in accessibility traversal if 6996 * specified, otherwise {@link #NO_ID}. 6997 * 6998 * @see #setAccessibilityTraversalAfter(int) 6999 */ 7000 public int getAccessibilityTraversalAfter() { 7001 return mAccessibilityTraversalAfterId; 7002 } 7003 7004 /** 7005 * Gets the id of a view for which this view serves as a label for 7006 * accessibility purposes. 7007 * 7008 * @return The labeled view id. 7009 */ 7010 @ViewDebug.ExportedProperty(category = "accessibility") 7011 public int getLabelFor() { 7012 return mLabelForId; 7013 } 7014 7015 /** 7016 * Sets the id of a view for which this view serves as a label for 7017 * accessibility purposes. 7018 * 7019 * @param id The labeled view id. 7020 */ 7021 @RemotableViewMethod 7022 public void setLabelFor(@IdRes int id) { 7023 if (mLabelForId == id) { 7024 return; 7025 } 7026 mLabelForId = id; 7027 if (mLabelForId != View.NO_ID 7028 && mID == View.NO_ID) { 7029 mID = generateViewId(); 7030 } 7031 notifyViewAccessibilityStateChangedIfNeeded( 7032 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 7033 } 7034 7035 /** 7036 * Invoked whenever this view loses focus, either by losing window focus or by losing 7037 * focus within its window. This method can be used to clear any state tied to the 7038 * focus. For instance, if a button is held pressed with the trackball and the window 7039 * loses focus, this method can be used to cancel the press. 7040 * 7041 * Subclasses of View overriding this method should always call super.onFocusLost(). 7042 * 7043 * @see #onFocusChanged(boolean, int, android.graphics.Rect) 7044 * @see #onWindowFocusChanged(boolean) 7045 * 7046 * @hide pending API council approval 7047 */ 7048 @CallSuper 7049 protected void onFocusLost() { 7050 resetPressedState(); 7051 } 7052 7053 private void resetPressedState() { 7054 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 7055 return; 7056 } 7057 7058 if (isPressed()) { 7059 setPressed(false); 7060 7061 if (!mHasPerformedLongPress) { 7062 removeLongPressCallback(); 7063 } 7064 } 7065 } 7066 7067 /** 7068 * Returns true if this view has focus 7069 * 7070 * @return True if this view has focus, false otherwise. 7071 */ 7072 @ViewDebug.ExportedProperty(category = "focus") 7073 public boolean isFocused() { 7074 return (mPrivateFlags & PFLAG_FOCUSED) != 0; 7075 } 7076 7077 /** 7078 * Find the view in the hierarchy rooted at this view that currently has 7079 * focus. 7080 * 7081 * @return The view that currently has focus, or null if no focused view can 7082 * be found. 7083 */ 7084 public View findFocus() { 7085 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null; 7086 } 7087 7088 /** 7089 * Indicates whether this view is one of the set of scrollable containers in 7090 * its window. 7091 * 7092 * @return whether this view is one of the set of scrollable containers in 7093 * its window 7094 * 7095 * @attr ref android.R.styleable#View_isScrollContainer 7096 */ 7097 public boolean isScrollContainer() { 7098 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0; 7099 } 7100 7101 /** 7102 * Change whether this view is one of the set of scrollable containers in 7103 * its window. This will be used to determine whether the window can 7104 * resize or must pan when a soft input area is open -- scrollable 7105 * containers allow the window to use resize mode since the container 7106 * will appropriately shrink. 7107 * 7108 * @attr ref android.R.styleable#View_isScrollContainer 7109 */ 7110 public void setScrollContainer(boolean isScrollContainer) { 7111 if (isScrollContainer) { 7112 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) { 7113 mAttachInfo.mScrollContainers.add(this); 7114 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 7115 } 7116 mPrivateFlags |= PFLAG_SCROLL_CONTAINER; 7117 } else { 7118 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 7119 mAttachInfo.mScrollContainers.remove(this); 7120 } 7121 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED); 7122 } 7123 } 7124 7125 /** 7126 * Returns the quality of the drawing cache. 7127 * 7128 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7129 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7130 * 7131 * @see #setDrawingCacheQuality(int) 7132 * @see #setDrawingCacheEnabled(boolean) 7133 * @see #isDrawingCacheEnabled() 7134 * 7135 * @attr ref android.R.styleable#View_drawingCacheQuality 7136 */ 7137 @DrawingCacheQuality 7138 public int getDrawingCacheQuality() { 7139 return mViewFlags & DRAWING_CACHE_QUALITY_MASK; 7140 } 7141 7142 /** 7143 * Set the drawing cache quality of this view. This value is used only when the 7144 * drawing cache is enabled 7145 * 7146 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO}, 7147 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH} 7148 * 7149 * @see #getDrawingCacheQuality() 7150 * @see #setDrawingCacheEnabled(boolean) 7151 * @see #isDrawingCacheEnabled() 7152 * 7153 * @attr ref android.R.styleable#View_drawingCacheQuality 7154 */ 7155 public void setDrawingCacheQuality(@DrawingCacheQuality int quality) { 7156 setFlags(quality, DRAWING_CACHE_QUALITY_MASK); 7157 } 7158 7159 /** 7160 * Returns whether the screen should remain on, corresponding to the current 7161 * value of {@link #KEEP_SCREEN_ON}. 7162 * 7163 * @return Returns true if {@link #KEEP_SCREEN_ON} is set. 7164 * 7165 * @see #setKeepScreenOn(boolean) 7166 * 7167 * @attr ref android.R.styleable#View_keepScreenOn 7168 */ 7169 public boolean getKeepScreenOn() { 7170 return (mViewFlags & KEEP_SCREEN_ON) != 0; 7171 } 7172 7173 /** 7174 * Controls whether the screen should remain on, modifying the 7175 * value of {@link #KEEP_SCREEN_ON}. 7176 * 7177 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}. 7178 * 7179 * @see #getKeepScreenOn() 7180 * 7181 * @attr ref android.R.styleable#View_keepScreenOn 7182 */ 7183 public void setKeepScreenOn(boolean keepScreenOn) { 7184 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON); 7185 } 7186 7187 /** 7188 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7189 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7190 * 7191 * @attr ref android.R.styleable#View_nextFocusLeft 7192 */ 7193 public int getNextFocusLeftId() { 7194 return mNextFocusLeftId; 7195 } 7196 7197 /** 7198 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}. 7199 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should 7200 * decide automatically. 7201 * 7202 * @attr ref android.R.styleable#View_nextFocusLeft 7203 */ 7204 public void setNextFocusLeftId(int nextFocusLeftId) { 7205 mNextFocusLeftId = nextFocusLeftId; 7206 } 7207 7208 /** 7209 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7210 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7211 * 7212 * @attr ref android.R.styleable#View_nextFocusRight 7213 */ 7214 public int getNextFocusRightId() { 7215 return mNextFocusRightId; 7216 } 7217 7218 /** 7219 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}. 7220 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should 7221 * decide automatically. 7222 * 7223 * @attr ref android.R.styleable#View_nextFocusRight 7224 */ 7225 public void setNextFocusRightId(int nextFocusRightId) { 7226 mNextFocusRightId = nextFocusRightId; 7227 } 7228 7229 /** 7230 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7231 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7232 * 7233 * @attr ref android.R.styleable#View_nextFocusUp 7234 */ 7235 public int getNextFocusUpId() { 7236 return mNextFocusUpId; 7237 } 7238 7239 /** 7240 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}. 7241 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should 7242 * decide automatically. 7243 * 7244 * @attr ref android.R.styleable#View_nextFocusUp 7245 */ 7246 public void setNextFocusUpId(int nextFocusUpId) { 7247 mNextFocusUpId = nextFocusUpId; 7248 } 7249 7250 /** 7251 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7252 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7253 * 7254 * @attr ref android.R.styleable#View_nextFocusDown 7255 */ 7256 public int getNextFocusDownId() { 7257 return mNextFocusDownId; 7258 } 7259 7260 /** 7261 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}. 7262 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should 7263 * decide automatically. 7264 * 7265 * @attr ref android.R.styleable#View_nextFocusDown 7266 */ 7267 public void setNextFocusDownId(int nextFocusDownId) { 7268 mNextFocusDownId = nextFocusDownId; 7269 } 7270 7271 /** 7272 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7273 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically. 7274 * 7275 * @attr ref android.R.styleable#View_nextFocusForward 7276 */ 7277 public int getNextFocusForwardId() { 7278 return mNextFocusForwardId; 7279 } 7280 7281 /** 7282 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}. 7283 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should 7284 * decide automatically. 7285 * 7286 * @attr ref android.R.styleable#View_nextFocusForward 7287 */ 7288 public void setNextFocusForwardId(int nextFocusForwardId) { 7289 mNextFocusForwardId = nextFocusForwardId; 7290 } 7291 7292 /** 7293 * Returns the visibility of this view and all of its ancestors 7294 * 7295 * @return True if this view and all of its ancestors are {@link #VISIBLE} 7296 */ 7297 public boolean isShown() { 7298 View current = this; 7299 //noinspection ConstantConditions 7300 do { 7301 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) { 7302 return false; 7303 } 7304 ViewParent parent = current.mParent; 7305 if (parent == null) { 7306 return false; // We are not attached to the view root 7307 } 7308 if (!(parent instanceof View)) { 7309 return true; 7310 } 7311 current = (View) parent; 7312 } while (current != null); 7313 7314 return false; 7315 } 7316 7317 /** 7318 * Called by the view hierarchy when the content insets for a window have 7319 * changed, to allow it to adjust its content to fit within those windows. 7320 * The content insets tell you the space that the status bar, input method, 7321 * and other system windows infringe on the application's window. 7322 * 7323 * <p>You do not normally need to deal with this function, since the default 7324 * window decoration given to applications takes care of applying it to the 7325 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} 7326 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case, 7327 * and your content can be placed under those system elements. You can then 7328 * use this method within your view hierarchy if you have parts of your UI 7329 * which you would like to ensure are not being covered. 7330 * 7331 * <p>The default implementation of this method simply applies the content 7332 * insets to the view's padding, consuming that content (modifying the 7333 * insets to be 0), and returning true. This behavior is off by default, but can 7334 * be enabled through {@link #setFitsSystemWindows(boolean)}. 7335 * 7336 * <p>This function's traversal down the hierarchy is depth-first. The same content 7337 * insets object is propagated down the hierarchy, so any changes made to it will 7338 * be seen by all following views (including potentially ones above in 7339 * the hierarchy since this is a depth-first traversal). The first view 7340 * that returns true will abort the entire traversal. 7341 * 7342 * <p>The default implementation works well for a situation where it is 7343 * used with a container that covers the entire window, allowing it to 7344 * apply the appropriate insets to its content on all edges. If you need 7345 * a more complicated layout (such as two different views fitting system 7346 * windows, one on the top of the window, and one on the bottom), 7347 * you can override the method and handle the insets however you would like. 7348 * Note that the insets provided by the framework are always relative to the 7349 * far edges of the window, not accounting for the location of the called view 7350 * within that window. (In fact when this method is called you do not yet know 7351 * where the layout will place the view, as it is done before layout happens.) 7352 * 7353 * <p>Note: unlike many View methods, there is no dispatch phase to this 7354 * call. If you are overriding it in a ViewGroup and want to allow the 7355 * call to continue to your children, you must be sure to call the super 7356 * implementation. 7357 * 7358 * <p>Here is a sample layout that makes use of fitting system windows 7359 * to have controls for a video view placed inside of the window decorations 7360 * that it hides and shows. This can be used with code like the second 7361 * sample (video player) shown in {@link #setSystemUiVisibility(int)}. 7362 * 7363 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete} 7364 * 7365 * @param insets Current content insets of the window. Prior to 7366 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify 7367 * the insets or else you and Android will be unhappy. 7368 * 7369 * @return {@code true} if this view applied the insets and it should not 7370 * continue propagating further down the hierarchy, {@code false} otherwise. 7371 * @see #getFitsSystemWindows() 7372 * @see #setFitsSystemWindows(boolean) 7373 * @see #setSystemUiVisibility(int) 7374 * 7375 * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply 7376 * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use 7377 * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)} 7378 * to implement handling their own insets. 7379 */ 7380 protected boolean fitSystemWindows(Rect insets) { 7381 if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) { 7382 if (insets == null) { 7383 // Null insets by definition have already been consumed. 7384 // This call cannot apply insets since there are none to apply, 7385 // so return false. 7386 return false; 7387 } 7388 // If we're not in the process of dispatching the newer apply insets call, 7389 // that means we're not in the compatibility path. Dispatch into the newer 7390 // apply insets path and take things from there. 7391 try { 7392 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS; 7393 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed(); 7394 } finally { 7395 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS; 7396 } 7397 } else { 7398 // We're being called from the newer apply insets path. 7399 // Perform the standard fallback behavior. 7400 return fitSystemWindowsInt(insets); 7401 } 7402 } 7403 7404 private boolean fitSystemWindowsInt(Rect insets) { 7405 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) { 7406 mUserPaddingStart = UNDEFINED_PADDING; 7407 mUserPaddingEnd = UNDEFINED_PADDING; 7408 Rect localInsets = sThreadLocal.get(); 7409 if (localInsets == null) { 7410 localInsets = new Rect(); 7411 sThreadLocal.set(localInsets); 7412 } 7413 boolean res = computeFitSystemWindows(insets, localInsets); 7414 mUserPaddingLeftInitial = localInsets.left; 7415 mUserPaddingRightInitial = localInsets.right; 7416 internalSetPadding(localInsets.left, localInsets.top, 7417 localInsets.right, localInsets.bottom); 7418 return res; 7419 } 7420 return false; 7421 } 7422 7423 /** 7424 * Called when the view should apply {@link WindowInsets} according to its internal policy. 7425 * 7426 * <p>This method should be overridden by views that wish to apply a policy different from or 7427 * in addition to the default behavior. Clients that wish to force a view subtree 7428 * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p> 7429 * 7430 * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set 7431 * it will be called during dispatch instead of this method. The listener may optionally 7432 * call this method from its own implementation if it wishes to apply the view's default 7433 * insets policy in addition to its own.</p> 7434 * 7435 * <p>Implementations of this method should either return the insets parameter unchanged 7436 * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed 7437 * that this view applied itself. This allows new inset types added in future platform 7438 * versions to pass through existing implementations unchanged without being erroneously 7439 * consumed.</p> 7440 * 7441 * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows} 7442 * property is set then the view will consume the system window insets and apply them 7443 * as padding for the view.</p> 7444 * 7445 * @param insets Insets to apply 7446 * @return The supplied insets with any applied insets consumed 7447 */ 7448 public WindowInsets onApplyWindowInsets(WindowInsets insets) { 7449 if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) { 7450 // We weren't called from within a direct call to fitSystemWindows, 7451 // call into it as a fallback in case we're in a class that overrides it 7452 // and has logic to perform. 7453 if (fitSystemWindows(insets.getSystemWindowInsets())) { 7454 return insets.consumeSystemWindowInsets(); 7455 } 7456 } else { 7457 // We were called from within a direct call to fitSystemWindows. 7458 if (fitSystemWindowsInt(insets.getSystemWindowInsets())) { 7459 return insets.consumeSystemWindowInsets(); 7460 } 7461 } 7462 return insets; 7463 } 7464 7465 /** 7466 * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying 7467 * window insets to this view. The listener's 7468 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 7469 * method will be called instead of the view's 7470 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 7471 * 7472 * @param listener Listener to set 7473 * 7474 * @see #onApplyWindowInsets(WindowInsets) 7475 */ 7476 public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) { 7477 getListenerInfo().mOnApplyWindowInsetsListener = listener; 7478 } 7479 7480 /** 7481 * Request to apply the given window insets to this view or another view in its subtree. 7482 * 7483 * <p>This method should be called by clients wishing to apply insets corresponding to areas 7484 * obscured by window decorations or overlays. This can include the status and navigation bars, 7485 * action bars, input methods and more. New inset categories may be added in the future. 7486 * The method returns the insets provided minus any that were applied by this view or its 7487 * children.</p> 7488 * 7489 * <p>Clients wishing to provide custom behavior should override the 7490 * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a 7491 * {@link OnApplyWindowInsetsListener} via the 7492 * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener} 7493 * method.</p> 7494 * 7495 * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method. 7496 * </p> 7497 * 7498 * @param insets Insets to apply 7499 * @return The provided insets minus the insets that were consumed 7500 */ 7501 public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) { 7502 try { 7503 mPrivateFlags3 |= PFLAG3_APPLYING_INSETS; 7504 if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) { 7505 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets); 7506 } else { 7507 return onApplyWindowInsets(insets); 7508 } 7509 } finally { 7510 mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS; 7511 } 7512 } 7513 7514 /** 7515 * Compute the view's coordinate within the surface. 7516 * 7517 * <p>Computes the coordinates of this view in its surface. The argument 7518 * must be an array of two integers. After the method returns, the array 7519 * contains the x and y location in that order.</p> 7520 * @hide 7521 * @param location an array of two integers in which to hold the coordinates 7522 */ 7523 public void getLocationInSurface(@Size(2) int[] location) { 7524 getLocationInWindow(location); 7525 if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) { 7526 location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left; 7527 location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top; 7528 } 7529 } 7530 7531 /** 7532 * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are 7533 * only available if the view is attached. 7534 * 7535 * @return WindowInsets from the top of the view hierarchy or null if View is detached 7536 */ 7537 public WindowInsets getRootWindowInsets() { 7538 if (mAttachInfo != null) { 7539 return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */); 7540 } 7541 return null; 7542 } 7543 7544 /** 7545 * @hide Compute the insets that should be consumed by this view and the ones 7546 * that should propagate to those under it. 7547 */ 7548 protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) { 7549 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7550 || mAttachInfo == null 7551 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0 7552 && !mAttachInfo.mOverscanRequested)) { 7553 outLocalInsets.set(inoutInsets); 7554 inoutInsets.set(0, 0, 0, 0); 7555 return true; 7556 } else { 7557 // The application wants to take care of fitting system window for 7558 // the content... however we still need to take care of any overscan here. 7559 final Rect overscan = mAttachInfo.mOverscanInsets; 7560 outLocalInsets.set(overscan); 7561 inoutInsets.left -= overscan.left; 7562 inoutInsets.top -= overscan.top; 7563 inoutInsets.right -= overscan.right; 7564 inoutInsets.bottom -= overscan.bottom; 7565 return false; 7566 } 7567 } 7568 7569 /** 7570 * Compute insets that should be consumed by this view and the ones that should propagate 7571 * to those under it. 7572 * 7573 * @param in Insets currently being processed by this View, likely received as a parameter 7574 * to {@link #onApplyWindowInsets(WindowInsets)}. 7575 * @param outLocalInsets A Rect that will receive the insets that should be consumed 7576 * by this view 7577 * @return Insets that should be passed along to views under this one 7578 */ 7579 public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) { 7580 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0 7581 || mAttachInfo == null 7582 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) { 7583 outLocalInsets.set(in.getSystemWindowInsets()); 7584 return in.consumeSystemWindowInsets(); 7585 } else { 7586 outLocalInsets.set(0, 0, 0, 0); 7587 return in; 7588 } 7589 } 7590 7591 /** 7592 * Sets whether or not this view should account for system screen decorations 7593 * such as the status bar and inset its content; that is, controlling whether 7594 * the default implementation of {@link #fitSystemWindows(Rect)} will be 7595 * executed. See that method for more details. 7596 * 7597 * <p>Note that if you are providing your own implementation of 7598 * {@link #fitSystemWindows(Rect)}, then there is no need to set this 7599 * flag to true -- your implementation will be overriding the default 7600 * implementation that checks this flag. 7601 * 7602 * @param fitSystemWindows If true, then the default implementation of 7603 * {@link #fitSystemWindows(Rect)} will be executed. 7604 * 7605 * @attr ref android.R.styleable#View_fitsSystemWindows 7606 * @see #getFitsSystemWindows() 7607 * @see #fitSystemWindows(Rect) 7608 * @see #setSystemUiVisibility(int) 7609 */ 7610 public void setFitsSystemWindows(boolean fitSystemWindows) { 7611 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS); 7612 } 7613 7614 /** 7615 * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method 7616 * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)} 7617 * will be executed. 7618 * 7619 * @return {@code true} if the default implementation of 7620 * {@link #fitSystemWindows(Rect)} will be executed. 7621 * 7622 * @attr ref android.R.styleable#View_fitsSystemWindows 7623 * @see #setFitsSystemWindows(boolean) 7624 * @see #fitSystemWindows(Rect) 7625 * @see #setSystemUiVisibility(int) 7626 */ 7627 @ViewDebug.ExportedProperty 7628 public boolean getFitsSystemWindows() { 7629 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS; 7630 } 7631 7632 /** @hide */ 7633 public boolean fitsSystemWindows() { 7634 return getFitsSystemWindows(); 7635 } 7636 7637 /** 7638 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed. 7639 * @deprecated Use {@link #requestApplyInsets()} for newer platform versions. 7640 */ 7641 public void requestFitSystemWindows() { 7642 if (mParent != null) { 7643 mParent.requestFitSystemWindows(); 7644 } 7645 } 7646 7647 /** 7648 * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed. 7649 */ 7650 public void requestApplyInsets() { 7651 requestFitSystemWindows(); 7652 } 7653 7654 /** 7655 * For use by PhoneWindow to make its own system window fitting optional. 7656 * @hide 7657 */ 7658 public void makeOptionalFitsSystemWindows() { 7659 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS); 7660 } 7661 7662 /** 7663 * Returns the outsets, which areas of the device that aren't a surface, but we would like to 7664 * treat them as such. 7665 * @hide 7666 */ 7667 public void getOutsets(Rect outOutsetRect) { 7668 if (mAttachInfo != null) { 7669 outOutsetRect.set(mAttachInfo.mOutsets); 7670 } else { 7671 outOutsetRect.setEmpty(); 7672 } 7673 } 7674 7675 /** 7676 * Returns the visibility status for this view. 7677 * 7678 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 7679 * @attr ref android.R.styleable#View_visibility 7680 */ 7681 @ViewDebug.ExportedProperty(mapping = { 7682 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"), 7683 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"), 7684 @ViewDebug.IntToString(from = GONE, to = "GONE") 7685 }) 7686 @Visibility 7687 public int getVisibility() { 7688 return mViewFlags & VISIBILITY_MASK; 7689 } 7690 7691 /** 7692 * Set the enabled state of this view. 7693 * 7694 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 7695 * @attr ref android.R.styleable#View_visibility 7696 */ 7697 @RemotableViewMethod 7698 public void setVisibility(@Visibility int visibility) { 7699 setFlags(visibility, VISIBILITY_MASK); 7700 } 7701 7702 /** 7703 * Returns the enabled status for this view. The interpretation of the 7704 * enabled state varies by subclass. 7705 * 7706 * @return True if this view is enabled, false otherwise. 7707 */ 7708 @ViewDebug.ExportedProperty 7709 public boolean isEnabled() { 7710 return (mViewFlags & ENABLED_MASK) == ENABLED; 7711 } 7712 7713 /** 7714 * Set the enabled state of this view. The interpretation of the enabled 7715 * state varies by subclass. 7716 * 7717 * @param enabled True if this view is enabled, false otherwise. 7718 */ 7719 @RemotableViewMethod 7720 public void setEnabled(boolean enabled) { 7721 if (enabled == isEnabled()) return; 7722 7723 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); 7724 7725 /* 7726 * The View most likely has to change its appearance, so refresh 7727 * the drawable state. 7728 */ 7729 refreshDrawableState(); 7730 7731 // Invalidate too, since the default behavior for views is to be 7732 // be drawn at 50% alpha rather than to change the drawable. 7733 invalidate(true); 7734 7735 if (!enabled) { 7736 cancelPendingInputEvents(); 7737 } 7738 } 7739 7740 /** 7741 * Set whether this view can receive the focus. 7742 * 7743 * Setting this to false will also ensure that this view is not focusable 7744 * in touch mode. 7745 * 7746 * @param focusable If true, this view can receive the focus. 7747 * 7748 * @see #setFocusableInTouchMode(boolean) 7749 * @attr ref android.R.styleable#View_focusable 7750 */ 7751 public void setFocusable(boolean focusable) { 7752 if (!focusable) { 7753 setFlags(0, FOCUSABLE_IN_TOUCH_MODE); 7754 } 7755 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK); 7756 } 7757 7758 /** 7759 * Set whether this view can receive focus while in touch mode. 7760 * 7761 * Setting this to true will also ensure that this view is focusable. 7762 * 7763 * @param focusableInTouchMode If true, this view can receive the focus while 7764 * in touch mode. 7765 * 7766 * @see #setFocusable(boolean) 7767 * @attr ref android.R.styleable#View_focusableInTouchMode 7768 */ 7769 public void setFocusableInTouchMode(boolean focusableInTouchMode) { 7770 // Focusable in touch mode should always be set before the focusable flag 7771 // otherwise, setting the focusable flag will trigger a focusableViewAvailable() 7772 // which, in touch mode, will not successfully request focus on this view 7773 // because the focusable in touch mode flag is not set 7774 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE); 7775 if (focusableInTouchMode) { 7776 setFlags(FOCUSABLE, FOCUSABLE_MASK); 7777 } 7778 } 7779 7780 /** 7781 * Set whether this view should have sound effects enabled for events such as 7782 * clicking and touching. 7783 * 7784 * <p>You may wish to disable sound effects for a view if you already play sounds, 7785 * for instance, a dial key that plays dtmf tones. 7786 * 7787 * @param soundEffectsEnabled whether sound effects are enabled for this view. 7788 * @see #isSoundEffectsEnabled() 7789 * @see #playSoundEffect(int) 7790 * @attr ref android.R.styleable#View_soundEffectsEnabled 7791 */ 7792 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) { 7793 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED); 7794 } 7795 7796 /** 7797 * @return whether this view should have sound effects enabled for events such as 7798 * clicking and touching. 7799 * 7800 * @see #setSoundEffectsEnabled(boolean) 7801 * @see #playSoundEffect(int) 7802 * @attr ref android.R.styleable#View_soundEffectsEnabled 7803 */ 7804 @ViewDebug.ExportedProperty 7805 public boolean isSoundEffectsEnabled() { 7806 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED); 7807 } 7808 7809 /** 7810 * Set whether this view should have haptic feedback for events such as 7811 * long presses. 7812 * 7813 * <p>You may wish to disable haptic feedback if your view already controls 7814 * its own haptic feedback. 7815 * 7816 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view. 7817 * @see #isHapticFeedbackEnabled() 7818 * @see #performHapticFeedback(int) 7819 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 7820 */ 7821 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) { 7822 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED); 7823 } 7824 7825 /** 7826 * @return whether this view should have haptic feedback enabled for events 7827 * long presses. 7828 * 7829 * @see #setHapticFeedbackEnabled(boolean) 7830 * @see #performHapticFeedback(int) 7831 * @attr ref android.R.styleable#View_hapticFeedbackEnabled 7832 */ 7833 @ViewDebug.ExportedProperty 7834 public boolean isHapticFeedbackEnabled() { 7835 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED); 7836 } 7837 7838 /** 7839 * Returns the layout direction for this view. 7840 * 7841 * @return One of {@link #LAYOUT_DIRECTION_LTR}, 7842 * {@link #LAYOUT_DIRECTION_RTL}, 7843 * {@link #LAYOUT_DIRECTION_INHERIT} or 7844 * {@link #LAYOUT_DIRECTION_LOCALE}. 7845 * 7846 * @attr ref android.R.styleable#View_layoutDirection 7847 * 7848 * @hide 7849 */ 7850 @ViewDebug.ExportedProperty(category = "layout", mapping = { 7851 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"), 7852 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"), 7853 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"), 7854 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE") 7855 }) 7856 @LayoutDir 7857 public int getRawLayoutDirection() { 7858 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT; 7859 } 7860 7861 /** 7862 * Set the layout direction for this view. This will propagate a reset of layout direction 7863 * resolution to the view's children and resolve layout direction for this view. 7864 * 7865 * @param layoutDirection the layout direction to set. Should be one of: 7866 * 7867 * {@link #LAYOUT_DIRECTION_LTR}, 7868 * {@link #LAYOUT_DIRECTION_RTL}, 7869 * {@link #LAYOUT_DIRECTION_INHERIT}, 7870 * {@link #LAYOUT_DIRECTION_LOCALE}. 7871 * 7872 * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution 7873 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 7874 * will return the default {@link #LAYOUT_DIRECTION_LTR}. 7875 * 7876 * @attr ref android.R.styleable#View_layoutDirection 7877 */ 7878 @RemotableViewMethod 7879 public void setLayoutDirection(@LayoutDir int layoutDirection) { 7880 if (getRawLayoutDirection() != layoutDirection) { 7881 // Reset the current layout direction and the resolved one 7882 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK; 7883 resetRtlProperties(); 7884 // Set the new layout direction (filtered) 7885 mPrivateFlags2 |= 7886 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK); 7887 // We need to resolve all RTL properties as they all depend on layout direction 7888 resolveRtlPropertiesIfNeeded(); 7889 requestLayout(); 7890 invalidate(true); 7891 } 7892 } 7893 7894 /** 7895 * Returns the resolved layout direction for this view. 7896 * 7897 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns 7898 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL. 7899 * 7900 * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version 7901 * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. 7902 * 7903 * @attr ref android.R.styleable#View_layoutDirection 7904 */ 7905 @ViewDebug.ExportedProperty(category = "layout", mapping = { 7906 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), 7907 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL") 7908 }) 7909 @ResolvedLayoutDir 7910 public int getLayoutDirection() { 7911 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 7912 if (targetSdkVersion < JELLY_BEAN_MR1) { 7913 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 7914 return LAYOUT_DIRECTION_RESOLVED_DEFAULT; 7915 } 7916 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == 7917 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR; 7918 } 7919 7920 /** 7921 * Indicates whether or not this view's layout is right-to-left. This is resolved from 7922 * layout attribute and/or the inherited value from the parent 7923 * 7924 * @return true if the layout is right-to-left. 7925 * 7926 * @hide 7927 */ 7928 @ViewDebug.ExportedProperty(category = "layout") 7929 public boolean isLayoutRtl() { 7930 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL); 7931 } 7932 7933 /** 7934 * Indicates whether the view is currently tracking transient state that the 7935 * app should not need to concern itself with saving and restoring, but that 7936 * the framework should take special note to preserve when possible. 7937 * 7938 * <p>A view with transient state cannot be trivially rebound from an external 7939 * data source, such as an adapter binding item views in a list. This may be 7940 * because the view is performing an animation, tracking user selection 7941 * of content, or similar.</p> 7942 * 7943 * @return true if the view has transient state 7944 */ 7945 @ViewDebug.ExportedProperty(category = "layout") 7946 public boolean hasTransientState() { 7947 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE; 7948 } 7949 7950 /** 7951 * Set whether this view is currently tracking transient state that the 7952 * framework should attempt to preserve when possible. This flag is reference counted, 7953 * so every call to setHasTransientState(true) should be paired with a later call 7954 * to setHasTransientState(false). 7955 * 7956 * <p>A view with transient state cannot be trivially rebound from an external 7957 * data source, such as an adapter binding item views in a list. This may be 7958 * because the view is performing an animation, tracking user selection 7959 * of content, or similar.</p> 7960 * 7961 * @param hasTransientState true if this view has transient state 7962 */ 7963 public void setHasTransientState(boolean hasTransientState) { 7964 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 : 7965 mTransientStateCount - 1; 7966 if (mTransientStateCount < 0) { 7967 mTransientStateCount = 0; 7968 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " + 7969 "unmatched pair of setHasTransientState calls"); 7970 } else if ((hasTransientState && mTransientStateCount == 1) || 7971 (!hasTransientState && mTransientStateCount == 0)) { 7972 // update flag if we've just incremented up from 0 or decremented down to 0 7973 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) | 7974 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0); 7975 if (mParent != null) { 7976 try { 7977 mParent.childHasTransientStateChanged(this, hasTransientState); 7978 } catch (AbstractMethodError e) { 7979 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 7980 " does not fully implement ViewParent", e); 7981 } 7982 } 7983 } 7984 } 7985 7986 /** 7987 * Returns true if this view is currently attached to a window. 7988 */ 7989 public boolean isAttachedToWindow() { 7990 return mAttachInfo != null; 7991 } 7992 7993 /** 7994 * Returns true if this view has been through at least one layout since it 7995 * was last attached to or detached from a window. 7996 */ 7997 public boolean isLaidOut() { 7998 return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT; 7999 } 8000 8001 /** 8002 * If this view doesn't do any drawing on its own, set this flag to 8003 * allow further optimizations. By default, this flag is not set on 8004 * View, but could be set on some View subclasses such as ViewGroup. 8005 * 8006 * Typically, if you override {@link #onDraw(android.graphics.Canvas)} 8007 * you should clear this flag. 8008 * 8009 * @param willNotDraw whether or not this View draw on its own 8010 */ 8011 public void setWillNotDraw(boolean willNotDraw) { 8012 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK); 8013 } 8014 8015 /** 8016 * Returns whether or not this View draws on its own. 8017 * 8018 * @return true if this view has nothing to draw, false otherwise 8019 */ 8020 @ViewDebug.ExportedProperty(category = "drawing") 8021 public boolean willNotDraw() { 8022 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW; 8023 } 8024 8025 /** 8026 * When a View's drawing cache is enabled, drawing is redirected to an 8027 * offscreen bitmap. Some views, like an ImageView, must be able to 8028 * bypass this mechanism if they already draw a single bitmap, to avoid 8029 * unnecessary usage of the memory. 8030 * 8031 * @param willNotCacheDrawing true if this view does not cache its 8032 * drawing, false otherwise 8033 */ 8034 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) { 8035 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING); 8036 } 8037 8038 /** 8039 * Returns whether or not this View can cache its drawing or not. 8040 * 8041 * @return true if this view does not cache its drawing, false otherwise 8042 */ 8043 @ViewDebug.ExportedProperty(category = "drawing") 8044 public boolean willNotCacheDrawing() { 8045 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING; 8046 } 8047 8048 /** 8049 * Indicates whether this view reacts to click events or not. 8050 * 8051 * @return true if the view is clickable, false otherwise 8052 * 8053 * @see #setClickable(boolean) 8054 * @attr ref android.R.styleable#View_clickable 8055 */ 8056 @ViewDebug.ExportedProperty 8057 public boolean isClickable() { 8058 return (mViewFlags & CLICKABLE) == CLICKABLE; 8059 } 8060 8061 /** 8062 * Enables or disables click events for this view. When a view 8063 * is clickable it will change its state to "pressed" on every click. 8064 * Subclasses should set the view clickable to visually react to 8065 * user's clicks. 8066 * 8067 * @param clickable true to make the view clickable, false otherwise 8068 * 8069 * @see #isClickable() 8070 * @attr ref android.R.styleable#View_clickable 8071 */ 8072 public void setClickable(boolean clickable) { 8073 setFlags(clickable ? CLICKABLE : 0, CLICKABLE); 8074 } 8075 8076 /** 8077 * Indicates whether this view reacts to long click events or not. 8078 * 8079 * @return true if the view is long clickable, false otherwise 8080 * 8081 * @see #setLongClickable(boolean) 8082 * @attr ref android.R.styleable#View_longClickable 8083 */ 8084 public boolean isLongClickable() { 8085 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE; 8086 } 8087 8088 /** 8089 * Enables or disables long click events for this view. When a view is long 8090 * clickable it reacts to the user holding down the button for a longer 8091 * duration than a tap. This event can either launch the listener or a 8092 * context menu. 8093 * 8094 * @param longClickable true to make the view long clickable, false otherwise 8095 * @see #isLongClickable() 8096 * @attr ref android.R.styleable#View_longClickable 8097 */ 8098 public void setLongClickable(boolean longClickable) { 8099 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE); 8100 } 8101 8102 /** 8103 * Indicates whether this view reacts to context clicks or not. 8104 * 8105 * @return true if the view is context clickable, false otherwise 8106 * @see #setContextClickable(boolean) 8107 * @attr ref android.R.styleable#View_contextClickable 8108 */ 8109 public boolean isContextClickable() { 8110 return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 8111 } 8112 8113 /** 8114 * Enables or disables context clicking for this view. This event can launch the listener. 8115 * 8116 * @param contextClickable true to make the view react to a context click, false otherwise 8117 * @see #isContextClickable() 8118 * @attr ref android.R.styleable#View_contextClickable 8119 */ 8120 public void setContextClickable(boolean contextClickable) { 8121 setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE); 8122 } 8123 8124 /** 8125 * Sets the pressed state for this view and provides a touch coordinate for 8126 * animation hinting. 8127 * 8128 * @param pressed Pass true to set the View's internal state to "pressed", 8129 * or false to reverts the View's internal state from a 8130 * previously set "pressed" state. 8131 * @param x The x coordinate of the touch that caused the press 8132 * @param y The y coordinate of the touch that caused the press 8133 */ 8134 private void setPressed(boolean pressed, float x, float y) { 8135 if (pressed) { 8136 drawableHotspotChanged(x, y); 8137 } 8138 8139 setPressed(pressed); 8140 } 8141 8142 /** 8143 * Sets the pressed state for this view. 8144 * 8145 * @see #isClickable() 8146 * @see #setClickable(boolean) 8147 * 8148 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts 8149 * the View's internal state from a previously set "pressed" state. 8150 */ 8151 public void setPressed(boolean pressed) { 8152 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED); 8153 8154 if (pressed) { 8155 mPrivateFlags |= PFLAG_PRESSED; 8156 } else { 8157 mPrivateFlags &= ~PFLAG_PRESSED; 8158 } 8159 8160 if (needsRefresh) { 8161 refreshDrawableState(); 8162 } 8163 dispatchSetPressed(pressed); 8164 } 8165 8166 /** 8167 * Dispatch setPressed to all of this View's children. 8168 * 8169 * @see #setPressed(boolean) 8170 * 8171 * @param pressed The new pressed state 8172 */ 8173 protected void dispatchSetPressed(boolean pressed) { 8174 } 8175 8176 /** 8177 * Indicates whether the view is currently in pressed state. Unless 8178 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter 8179 * the pressed state. 8180 * 8181 * @see #setPressed(boolean) 8182 * @see #isClickable() 8183 * @see #setClickable(boolean) 8184 * 8185 * @return true if the view is currently pressed, false otherwise 8186 */ 8187 @ViewDebug.ExportedProperty 8188 public boolean isPressed() { 8189 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED; 8190 } 8191 8192 /** 8193 * @hide 8194 * Indicates whether this view will participate in data collection through 8195 * {@link ViewStructure}. If true, it will not provide any data 8196 * for itself or its children. If false, the normal data collection will be allowed. 8197 * 8198 * @return Returns false if assist data collection is not blocked, else true. 8199 * 8200 * @see #setAssistBlocked(boolean) 8201 * @attr ref android.R.styleable#View_assistBlocked 8202 */ 8203 public boolean isAssistBlocked() { 8204 return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0; 8205 } 8206 8207 /** 8208 * @hide 8209 * Controls whether assist data collection from this view and its children is enabled 8210 * (that is, whether {@link #onProvideStructure} and 8211 * {@link #onProvideVirtualStructure} will be called). The default value is false, 8212 * allowing normal assist collection. Setting this to false will disable assist collection. 8213 * 8214 * @param enabled Set to true to <em>disable</em> assist data collection, or false 8215 * (the default) to allow it. 8216 * 8217 * @see #isAssistBlocked() 8218 * @see #onProvideStructure 8219 * @see #onProvideVirtualStructure 8220 * @attr ref android.R.styleable#View_assistBlocked 8221 */ 8222 public void setAssistBlocked(boolean enabled) { 8223 if (enabled) { 8224 mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED; 8225 } else { 8226 mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED; 8227 } 8228 } 8229 8230 /** 8231 * Indicates whether this view will save its state (that is, 8232 * whether its {@link #onSaveInstanceState} method will be called). 8233 * 8234 * @return Returns true if the view state saving is enabled, else false. 8235 * 8236 * @see #setSaveEnabled(boolean) 8237 * @attr ref android.R.styleable#View_saveEnabled 8238 */ 8239 public boolean isSaveEnabled() { 8240 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED; 8241 } 8242 8243 /** 8244 * Controls whether the saving of this view's state is 8245 * enabled (that is, whether its {@link #onSaveInstanceState} method 8246 * will be called). Note that even if freezing is enabled, the 8247 * view still must have an id assigned to it (via {@link #setId(int)}) 8248 * for its state to be saved. This flag can only disable the 8249 * saving of this view; any child views may still have their state saved. 8250 * 8251 * @param enabled Set to false to <em>disable</em> state saving, or true 8252 * (the default) to allow it. 8253 * 8254 * @see #isSaveEnabled() 8255 * @see #setId(int) 8256 * @see #onSaveInstanceState() 8257 * @attr ref android.R.styleable#View_saveEnabled 8258 */ 8259 public void setSaveEnabled(boolean enabled) { 8260 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK); 8261 } 8262 8263 /** 8264 * Gets whether the framework should discard touches when the view's 8265 * window is obscured by another visible window. 8266 * Refer to the {@link View} security documentation for more details. 8267 * 8268 * @return True if touch filtering is enabled. 8269 * 8270 * @see #setFilterTouchesWhenObscured(boolean) 8271 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8272 */ 8273 @ViewDebug.ExportedProperty 8274 public boolean getFilterTouchesWhenObscured() { 8275 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0; 8276 } 8277 8278 /** 8279 * Sets whether the framework should discard touches when the view's 8280 * window is obscured by another visible window. 8281 * Refer to the {@link View} security documentation for more details. 8282 * 8283 * @param enabled True if touch filtering should be enabled. 8284 * 8285 * @see #getFilterTouchesWhenObscured 8286 * @attr ref android.R.styleable#View_filterTouchesWhenObscured 8287 */ 8288 public void setFilterTouchesWhenObscured(boolean enabled) { 8289 setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0, 8290 FILTER_TOUCHES_WHEN_OBSCURED); 8291 } 8292 8293 /** 8294 * Indicates whether the entire hierarchy under this view will save its 8295 * state when a state saving traversal occurs from its parent. The default 8296 * is true; if false, these views will not be saved unless 8297 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8298 * 8299 * @return Returns true if the view state saving from parent is enabled, else false. 8300 * 8301 * @see #setSaveFromParentEnabled(boolean) 8302 */ 8303 public boolean isSaveFromParentEnabled() { 8304 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED; 8305 } 8306 8307 /** 8308 * Controls whether the entire hierarchy under this view will save its 8309 * state when a state saving traversal occurs from its parent. The default 8310 * is true; if false, these views will not be saved unless 8311 * {@link #saveHierarchyState(SparseArray)} is called directly on this view. 8312 * 8313 * @param enabled Set to false to <em>disable</em> state saving, or true 8314 * (the default) to allow it. 8315 * 8316 * @see #isSaveFromParentEnabled() 8317 * @see #setId(int) 8318 * @see #onSaveInstanceState() 8319 */ 8320 public void setSaveFromParentEnabled(boolean enabled) { 8321 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK); 8322 } 8323 8324 8325 /** 8326 * Returns whether this View is able to take focus. 8327 * 8328 * @return True if this view can take focus, or false otherwise. 8329 * @attr ref android.R.styleable#View_focusable 8330 */ 8331 @ViewDebug.ExportedProperty(category = "focus") 8332 public final boolean isFocusable() { 8333 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK); 8334 } 8335 8336 /** 8337 * When a view is focusable, it may not want to take focus when in touch mode. 8338 * For example, a button would like focus when the user is navigating via a D-pad 8339 * so that the user can click on it, but once the user starts touching the screen, 8340 * the button shouldn't take focus 8341 * @return Whether the view is focusable in touch mode. 8342 * @attr ref android.R.styleable#View_focusableInTouchMode 8343 */ 8344 @ViewDebug.ExportedProperty 8345 public final boolean isFocusableInTouchMode() { 8346 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE); 8347 } 8348 8349 /** 8350 * Find the nearest view in the specified direction that can take focus. 8351 * This does not actually give focus to that view. 8352 * 8353 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 8354 * 8355 * @return The nearest focusable in the specified direction, or null if none 8356 * can be found. 8357 */ 8358 public View focusSearch(@FocusRealDirection int direction) { 8359 if (mParent != null) { 8360 return mParent.focusSearch(this, direction); 8361 } else { 8362 return null; 8363 } 8364 } 8365 8366 /** 8367 * This method is the last chance for the focused view and its ancestors to 8368 * respond to an arrow key. This is called when the focused view did not 8369 * consume the key internally, nor could the view system find a new view in 8370 * the requested direction to give focus to. 8371 * 8372 * @param focused The currently focused view. 8373 * @param direction The direction focus wants to move. One of FOCUS_UP, 8374 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT. 8375 * @return True if the this view consumed this unhandled move. 8376 */ 8377 public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) { 8378 return false; 8379 } 8380 8381 /** 8382 * If a user manually specified the next view id for a particular direction, 8383 * use the root to look up the view. 8384 * @param root The root view of the hierarchy containing this view. 8385 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, 8386 * or FOCUS_BACKWARD. 8387 * @return The user specified next view, or null if there is none. 8388 */ 8389 View findUserSetNextFocus(View root, @FocusDirection int direction) { 8390 switch (direction) { 8391 case FOCUS_LEFT: 8392 if (mNextFocusLeftId == View.NO_ID) return null; 8393 return findViewInsideOutShouldExist(root, mNextFocusLeftId); 8394 case FOCUS_RIGHT: 8395 if (mNextFocusRightId == View.NO_ID) return null; 8396 return findViewInsideOutShouldExist(root, mNextFocusRightId); 8397 case FOCUS_UP: 8398 if (mNextFocusUpId == View.NO_ID) return null; 8399 return findViewInsideOutShouldExist(root, mNextFocusUpId); 8400 case FOCUS_DOWN: 8401 if (mNextFocusDownId == View.NO_ID) return null; 8402 return findViewInsideOutShouldExist(root, mNextFocusDownId); 8403 case FOCUS_FORWARD: 8404 if (mNextFocusForwardId == View.NO_ID) return null; 8405 return findViewInsideOutShouldExist(root, mNextFocusForwardId); 8406 case FOCUS_BACKWARD: { 8407 if (mID == View.NO_ID) return null; 8408 final int id = mID; 8409 return root.findViewByPredicateInsideOut(this, new Predicate<View>() { 8410 @Override 8411 public boolean apply(View t) { 8412 return t.mNextFocusForwardId == id; 8413 } 8414 }); 8415 } 8416 } 8417 return null; 8418 } 8419 8420 private View findViewInsideOutShouldExist(View root, int id) { 8421 if (mMatchIdPredicate == null) { 8422 mMatchIdPredicate = new MatchIdPredicate(); 8423 } 8424 mMatchIdPredicate.mId = id; 8425 View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate); 8426 if (result == null) { 8427 Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id); 8428 } 8429 return result; 8430 } 8431 8432 /** 8433 * Find and return all focusable views that are descendants of this view, 8434 * possibly including this view if it is focusable itself. 8435 * 8436 * @param direction The direction of the focus 8437 * @return A list of focusable views 8438 */ 8439 public ArrayList<View> getFocusables(@FocusDirection int direction) { 8440 ArrayList<View> result = new ArrayList<View>(24); 8441 addFocusables(result, direction); 8442 return result; 8443 } 8444 8445 /** 8446 * Add any focusable views that are descendants of this view (possibly 8447 * including this view if it is focusable itself) to views. If we are in touch mode, 8448 * only add views that are also focusable in touch mode. 8449 * 8450 * @param views Focusable views found so far 8451 * @param direction The direction of the focus 8452 */ 8453 public void addFocusables(ArrayList<View> views, @FocusDirection int direction) { 8454 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE); 8455 } 8456 8457 /** 8458 * Adds any focusable views that are descendants of this view (possibly 8459 * including this view if it is focusable itself) to views. This method 8460 * adds all focusable views regardless if we are in touch mode or 8461 * only views focusable in touch mode if we are in touch mode or 8462 * only views that can take accessibility focus if accessibility is enabled 8463 * depending on the focusable mode parameter. 8464 * 8465 * @param views Focusable views found so far or null if all we are interested is 8466 * the number of focusables. 8467 * @param direction The direction of the focus. 8468 * @param focusableMode The type of focusables to be added. 8469 * 8470 * @see #FOCUSABLES_ALL 8471 * @see #FOCUSABLES_TOUCH_MODE 8472 */ 8473 public void addFocusables(ArrayList<View> views, @FocusDirection int direction, 8474 @FocusableMode int focusableMode) { 8475 if (views == null) { 8476 return; 8477 } 8478 if (!isFocusable()) { 8479 return; 8480 } 8481 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE 8482 && isInTouchMode() && !isFocusableInTouchMode()) { 8483 return; 8484 } 8485 views.add(this); 8486 } 8487 8488 /** 8489 * Finds the Views that contain given text. The containment is case insensitive. 8490 * The search is performed by either the text that the View renders or the content 8491 * description that describes the view for accessibility purposes and the view does 8492 * not render or both. Clients can specify how the search is to be performed via 8493 * passing the {@link #FIND_VIEWS_WITH_TEXT} and 8494 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags. 8495 * 8496 * @param outViews The output list of matching Views. 8497 * @param searched The text to match against. 8498 * 8499 * @see #FIND_VIEWS_WITH_TEXT 8500 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION 8501 * @see #setContentDescription(CharSequence) 8502 */ 8503 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, 8504 @FindViewFlags int flags) { 8505 if (getAccessibilityNodeProvider() != null) { 8506 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) { 8507 outViews.add(this); 8508 } 8509 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 8510 && (searched != null && searched.length() > 0) 8511 && (mContentDescription != null && mContentDescription.length() > 0)) { 8512 String searchedLowerCase = searched.toString().toLowerCase(); 8513 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase(); 8514 if (contentDescriptionLowerCase.contains(searchedLowerCase)) { 8515 outViews.add(this); 8516 } 8517 } 8518 } 8519 8520 /** 8521 * Find and return all touchable views that are descendants of this view, 8522 * possibly including this view if it is touchable itself. 8523 * 8524 * @return A list of touchable views 8525 */ 8526 public ArrayList<View> getTouchables() { 8527 ArrayList<View> result = new ArrayList<View>(); 8528 addTouchables(result); 8529 return result; 8530 } 8531 8532 /** 8533 * Add any touchable views that are descendants of this view (possibly 8534 * including this view if it is touchable itself) to views. 8535 * 8536 * @param views Touchable views found so far 8537 */ 8538 public void addTouchables(ArrayList<View> views) { 8539 final int viewFlags = mViewFlags; 8540 8541 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 8542 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) 8543 && (viewFlags & ENABLED_MASK) == ENABLED) { 8544 views.add(this); 8545 } 8546 } 8547 8548 /** 8549 * Returns whether this View is accessibility focused. 8550 * 8551 * @return True if this View is accessibility focused. 8552 */ 8553 public boolean isAccessibilityFocused() { 8554 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0; 8555 } 8556 8557 /** 8558 * Call this to try to give accessibility focus to this view. 8559 * 8560 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()} 8561 * returns false or the view is no visible or the view already has accessibility 8562 * focus. 8563 * 8564 * See also {@link #focusSearch(int)}, which is what you call to say that you 8565 * have focus, and you want your parent to look for the next one. 8566 * 8567 * @return Whether this view actually took accessibility focus. 8568 * 8569 * @hide 8570 */ 8571 public boolean requestAccessibilityFocus() { 8572 AccessibilityManager manager = AccessibilityManager.getInstance(mContext); 8573 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) { 8574 return false; 8575 } 8576 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) { 8577 return false; 8578 } 8579 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) { 8580 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED; 8581 ViewRootImpl viewRootImpl = getViewRootImpl(); 8582 if (viewRootImpl != null) { 8583 viewRootImpl.setAccessibilityFocus(this, null); 8584 } 8585 invalidate(); 8586 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 8587 return true; 8588 } 8589 return false; 8590 } 8591 8592 /** 8593 * Call this to try to clear accessibility focus of this view. 8594 * 8595 * See also {@link #focusSearch(int)}, which is what you call to say that you 8596 * have focus, and you want your parent to look for the next one. 8597 * 8598 * @hide 8599 */ 8600 public void clearAccessibilityFocus() { 8601 clearAccessibilityFocusNoCallbacks(); 8602 8603 // Clear the global reference of accessibility focus if this view or 8604 // any of its descendants had accessibility focus. This will NOT send 8605 // an event or update internal state if focus is cleared from a 8606 // descendant view, which may leave views in inconsistent states. 8607 final ViewRootImpl viewRootImpl = getViewRootImpl(); 8608 if (viewRootImpl != null) { 8609 final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 8610 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 8611 viewRootImpl.setAccessibilityFocus(null, null); 8612 } 8613 } 8614 } 8615 8616 private void sendAccessibilityHoverEvent(int eventType) { 8617 // Since we are not delivering to a client accessibility events from not 8618 // important views (unless the clinet request that) we need to fire the 8619 // event from the deepest view exposed to the client. As a consequence if 8620 // the user crosses a not exposed view the client will see enter and exit 8621 // of the exposed predecessor followed by and enter and exit of that same 8622 // predecessor when entering and exiting the not exposed descendant. This 8623 // is fine since the client has a clear idea which view is hovered at the 8624 // price of a couple more events being sent. This is a simple and 8625 // working solution. 8626 View source = this; 8627 while (true) { 8628 if (source.includeForAccessibility()) { 8629 source.sendAccessibilityEvent(eventType); 8630 return; 8631 } 8632 ViewParent parent = source.getParent(); 8633 if (parent instanceof View) { 8634 source = (View) parent; 8635 } else { 8636 return; 8637 } 8638 } 8639 } 8640 8641 /** 8642 * Clears accessibility focus without calling any callback methods 8643 * normally invoked in {@link #clearAccessibilityFocus()}. This method 8644 * is used for clearing accessibility focus when giving this focus to 8645 * another view. 8646 */ 8647 void clearAccessibilityFocusNoCallbacks() { 8648 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) { 8649 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED; 8650 invalidate(); 8651 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 8652 } 8653 } 8654 8655 /** 8656 * Call this to try to give focus to a specific view or to one of its 8657 * descendants. 8658 * 8659 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 8660 * false), or if it is focusable and it is not focusable in touch mode 8661 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 8662 * 8663 * See also {@link #focusSearch(int)}, which is what you call to say that you 8664 * have focus, and you want your parent to look for the next one. 8665 * 8666 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments 8667 * {@link #FOCUS_DOWN} and <code>null</code>. 8668 * 8669 * @return Whether this view or one of its descendants actually took focus. 8670 */ 8671 public final boolean requestFocus() { 8672 return requestFocus(View.FOCUS_DOWN); 8673 } 8674 8675 /** 8676 * Call this to try to give focus to a specific view or to one of its 8677 * descendants and give it a hint about what direction focus is heading. 8678 * 8679 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 8680 * false), or if it is focusable and it is not focusable in touch mode 8681 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 8682 * 8683 * See also {@link #focusSearch(int)}, which is what you call to say that you 8684 * have focus, and you want your parent to look for the next one. 8685 * 8686 * This is equivalent to calling {@link #requestFocus(int, Rect)} with 8687 * <code>null</code> set for the previously focused rectangle. 8688 * 8689 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 8690 * @return Whether this view or one of its descendants actually took focus. 8691 */ 8692 public final boolean requestFocus(int direction) { 8693 return requestFocus(direction, null); 8694 } 8695 8696 /** 8697 * Call this to try to give focus to a specific view or to one of its descendants 8698 * and give it hints about the direction and a specific rectangle that the focus 8699 * is coming from. The rectangle can help give larger views a finer grained hint 8700 * about where focus is coming from, and therefore, where to show selection, or 8701 * forward focus change internally. 8702 * 8703 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns 8704 * false), or if it is focusable and it is not focusable in touch mode 8705 * ({@link #isFocusableInTouchMode}) while the device is in touch mode. 8706 * 8707 * A View will not take focus if it is not visible. 8708 * 8709 * A View will not take focus if one of its parents has 8710 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to 8711 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}. 8712 * 8713 * See also {@link #focusSearch(int)}, which is what you call to say that you 8714 * have focus, and you want your parent to look for the next one. 8715 * 8716 * You may wish to override this method if your custom {@link View} has an internal 8717 * {@link View} that it wishes to forward the request to. 8718 * 8719 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT 8720 * @param previouslyFocusedRect The rectangle (in this View's coordinate system) 8721 * to give a finer grained hint about where focus is coming from. May be null 8722 * if there is no hint. 8723 * @return Whether this view or one of its descendants actually took focus. 8724 */ 8725 public boolean requestFocus(int direction, Rect previouslyFocusedRect) { 8726 return requestFocusNoSearch(direction, previouslyFocusedRect); 8727 } 8728 8729 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) { 8730 // need to be focusable 8731 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE || 8732 (mViewFlags & VISIBILITY_MASK) != VISIBLE) { 8733 return false; 8734 } 8735 8736 // need to be focusable in touch mode if in touch mode 8737 if (isInTouchMode() && 8738 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) { 8739 return false; 8740 } 8741 8742 // need to not have any parents blocking us 8743 if (hasAncestorThatBlocksDescendantFocus()) { 8744 return false; 8745 } 8746 8747 handleFocusGainInternal(direction, previouslyFocusedRect); 8748 return true; 8749 } 8750 8751 /** 8752 * Call this to try to give focus to a specific view or to one of its descendants. This is a 8753 * special variant of {@link #requestFocus() } that will allow views that are not focusable in 8754 * touch mode to request focus when they are touched. 8755 * 8756 * @return Whether this view or one of its descendants actually took focus. 8757 * 8758 * @see #isInTouchMode() 8759 * 8760 */ 8761 public final boolean requestFocusFromTouch() { 8762 // Leave touch mode if we need to 8763 if (isInTouchMode()) { 8764 ViewRootImpl viewRoot = getViewRootImpl(); 8765 if (viewRoot != null) { 8766 viewRoot.ensureTouchMode(false); 8767 } 8768 } 8769 return requestFocus(View.FOCUS_DOWN); 8770 } 8771 8772 /** 8773 * @return Whether any ancestor of this view blocks descendant focus. 8774 */ 8775 private boolean hasAncestorThatBlocksDescendantFocus() { 8776 final boolean focusableInTouchMode = isFocusableInTouchMode(); 8777 ViewParent ancestor = mParent; 8778 while (ancestor instanceof ViewGroup) { 8779 final ViewGroup vgAncestor = (ViewGroup) ancestor; 8780 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS 8781 || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) { 8782 return true; 8783 } else { 8784 ancestor = vgAncestor.getParent(); 8785 } 8786 } 8787 return false; 8788 } 8789 8790 /** 8791 * Gets the mode for determining whether this View is important for accessibility 8792 * which is if it fires accessibility events and if it is reported to 8793 * accessibility services that query the screen. 8794 * 8795 * @return The mode for determining whether a View is important for accessibility. 8796 * 8797 * @attr ref android.R.styleable#View_importantForAccessibility 8798 * 8799 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 8800 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 8801 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 8802 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 8803 */ 8804 @ViewDebug.ExportedProperty(category = "accessibility", mapping = { 8805 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"), 8806 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"), 8807 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"), 8808 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS, 8809 to = "noHideDescendants") 8810 }) 8811 public int getImportantForAccessibility() { 8812 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 8813 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 8814 } 8815 8816 /** 8817 * Sets the live region mode for this view. This indicates to accessibility 8818 * services whether they should automatically notify the user about changes 8819 * to the view's content description or text, or to the content descriptions 8820 * or text of the view's children (where applicable). 8821 * <p> 8822 * For example, in a login screen with a TextView that displays an "incorrect 8823 * password" notification, that view should be marked as a live region with 8824 * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 8825 * <p> 8826 * To disable change notifications for this view, use 8827 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region 8828 * mode for most views. 8829 * <p> 8830 * To indicate that the user should be notified of changes, use 8831 * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}. 8832 * <p> 8833 * If the view's changes should interrupt ongoing speech and notify the user 8834 * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}. 8835 * 8836 * @param mode The live region mode for this view, one of: 8837 * <ul> 8838 * <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE} 8839 * <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE} 8840 * <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE} 8841 * </ul> 8842 * @attr ref android.R.styleable#View_accessibilityLiveRegion 8843 */ 8844 public void setAccessibilityLiveRegion(int mode) { 8845 if (mode != getAccessibilityLiveRegion()) { 8846 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 8847 mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) 8848 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; 8849 notifyViewAccessibilityStateChangedIfNeeded( 8850 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 8851 } 8852 } 8853 8854 /** 8855 * Gets the live region mode for this View. 8856 * 8857 * @return The live region mode for the view. 8858 * 8859 * @attr ref android.R.styleable#View_accessibilityLiveRegion 8860 * 8861 * @see #setAccessibilityLiveRegion(int) 8862 */ 8863 public int getAccessibilityLiveRegion() { 8864 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK) 8865 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT; 8866 } 8867 8868 /** 8869 * Sets how to determine whether this view is important for accessibility 8870 * which is if it fires accessibility events and if it is reported to 8871 * accessibility services that query the screen. 8872 * 8873 * @param mode How to determine whether this view is important for accessibility. 8874 * 8875 * @attr ref android.R.styleable#View_importantForAccessibility 8876 * 8877 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES 8878 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO 8879 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS 8880 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO 8881 */ 8882 public void setImportantForAccessibility(int mode) { 8883 final int oldMode = getImportantForAccessibility(); 8884 if (mode != oldMode) { 8885 final boolean hideDescendants = 8886 mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; 8887 8888 // If this node or its descendants are no longer important, try to 8889 // clear accessibility focus. 8890 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) { 8891 final View focusHost = findAccessibilityFocusHost(hideDescendants); 8892 if (focusHost != null) { 8893 focusHost.clearAccessibilityFocus(); 8894 } 8895 } 8896 8897 // If we're moving between AUTO and another state, we might not need 8898 // to send a subtree changed notification. We'll store the computed 8899 // importance, since we'll need to check it later to make sure. 8900 final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO 8901 || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO; 8902 final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility(); 8903 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 8904 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT) 8905 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK; 8906 if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { 8907 notifySubtreeAccessibilityStateChangedIfNeeded(); 8908 } else { 8909 notifyViewAccessibilityStateChangedIfNeeded( 8910 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 8911 } 8912 } 8913 } 8914 8915 /** 8916 * Returns the view within this view's hierarchy that is hosting 8917 * accessibility focus. 8918 * 8919 * @param searchDescendants whether to search for focus in descendant views 8920 * @return the view hosting accessibility focus, or {@code null} 8921 */ 8922 private View findAccessibilityFocusHost(boolean searchDescendants) { 8923 if (isAccessibilityFocusedViewOrHost()) { 8924 return this; 8925 } 8926 8927 if (searchDescendants) { 8928 final ViewRootImpl viewRoot = getViewRootImpl(); 8929 if (viewRoot != null) { 8930 final View focusHost = viewRoot.getAccessibilityFocusedHost(); 8931 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) { 8932 return focusHost; 8933 } 8934 } 8935 } 8936 8937 return null; 8938 } 8939 8940 /** 8941 * Computes whether this view should be exposed for accessibility. In 8942 * general, views that are interactive or provide information are exposed 8943 * while views that serve only as containers are hidden. 8944 * <p> 8945 * If an ancestor of this view has importance 8946 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method 8947 * returns <code>false</code>. 8948 * <p> 8949 * Otherwise, the value is computed according to the view's 8950 * {@link #getImportantForAccessibility()} value: 8951 * <ol> 8952 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or 8953 * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false 8954 * </code> 8955 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code> 8956 * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if 8957 * view satisfies any of the following: 8958 * <ul> 8959 * <li>Is actionable, e.g. {@link #isClickable()}, 8960 * {@link #isLongClickable()}, or {@link #isFocusable()} 8961 * <li>Has an {@link AccessibilityDelegate} 8962 * <li>Has an interaction listener, e.g. {@link OnTouchListener}, 8963 * {@link OnKeyListener}, etc. 8964 * <li>Is an accessibility live region, e.g. 8965 * {@link #getAccessibilityLiveRegion()} is not 8966 * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. 8967 * </ul> 8968 * </ol> 8969 * 8970 * @return Whether the view is exposed for accessibility. 8971 * @see #setImportantForAccessibility(int) 8972 * @see #getImportantForAccessibility() 8973 */ 8974 public boolean isImportantForAccessibility() { 8975 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK) 8976 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT; 8977 if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO 8978 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 8979 return false; 8980 } 8981 8982 // Check parent mode to ensure we're not hidden. 8983 ViewParent parent = mParent; 8984 while (parent instanceof View) { 8985 if (((View) parent).getImportantForAccessibility() 8986 == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) { 8987 return false; 8988 } 8989 parent = parent.getParent(); 8990 } 8991 8992 return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility() 8993 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null 8994 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE; 8995 } 8996 8997 /** 8998 * Gets the parent for accessibility purposes. Note that the parent for 8999 * accessibility is not necessary the immediate parent. It is the first 9000 * predecessor that is important for accessibility. 9001 * 9002 * @return The parent for accessibility purposes. 9003 */ 9004 public ViewParent getParentForAccessibility() { 9005 if (mParent instanceof View) { 9006 View parentView = (View) mParent; 9007 if (parentView.includeForAccessibility()) { 9008 return mParent; 9009 } else { 9010 return mParent.getParentForAccessibility(); 9011 } 9012 } 9013 return null; 9014 } 9015 9016 /** 9017 * Adds the children of this View relevant for accessibility to the given list 9018 * as output. Since some Views are not important for accessibility the added 9019 * child views are not necessarily direct children of this view, rather they are 9020 * the first level of descendants important for accessibility. 9021 * 9022 * @param outChildren The output list that will receive children for accessibility. 9023 */ 9024 public void addChildrenForAccessibility(ArrayList<View> outChildren) { 9025 9026 } 9027 9028 /** 9029 * Whether to regard this view for accessibility. A view is regarded for 9030 * accessibility if it is important for accessibility or the querying 9031 * accessibility service has explicitly requested that view not 9032 * important for accessibility are regarded. 9033 * 9034 * @return Whether to regard the view for accessibility. 9035 * 9036 * @hide 9037 */ 9038 public boolean includeForAccessibility() { 9039 if (mAttachInfo != null) { 9040 return (mAttachInfo.mAccessibilityFetchFlags 9041 & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0 9042 || isImportantForAccessibility(); 9043 } 9044 return false; 9045 } 9046 9047 /** 9048 * Returns whether the View is considered actionable from 9049 * accessibility perspective. Such view are important for 9050 * accessibility. 9051 * 9052 * @return True if the view is actionable for accessibility. 9053 * 9054 * @hide 9055 */ 9056 public boolean isActionableForAccessibility() { 9057 return (isClickable() || isLongClickable() || isFocusable()); 9058 } 9059 9060 /** 9061 * Returns whether the View has registered callbacks which makes it 9062 * important for accessibility. 9063 * 9064 * @return True if the view is actionable for accessibility. 9065 */ 9066 private boolean hasListenersForAccessibility() { 9067 ListenerInfo info = getListenerInfo(); 9068 return mTouchDelegate != null || info.mOnKeyListener != null 9069 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null 9070 || info.mOnHoverListener != null || info.mOnDragListener != null; 9071 } 9072 9073 /** 9074 * Notifies that the accessibility state of this view changed. The change 9075 * is local to this view and does not represent structural changes such 9076 * as children and parent. For example, the view became focusable. The 9077 * notification is at at most once every 9078 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9079 * to avoid unnecessary load to the system. Also once a view has a pending 9080 * notification this method is a NOP until the notification has been sent. 9081 * 9082 * @hide 9083 */ 9084 public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) { 9085 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9086 return; 9087 } 9088 if (mSendViewStateChangedAccessibilityEvent == null) { 9089 mSendViewStateChangedAccessibilityEvent = 9090 new SendViewStateChangedAccessibilityEvent(); 9091 } 9092 mSendViewStateChangedAccessibilityEvent.runOrPost(changeType); 9093 } 9094 9095 /** 9096 * Notifies that the accessibility state of this view changed. The change 9097 * is *not* local to this view and does represent structural changes such 9098 * as children and parent. For example, the view size changed. The 9099 * notification is at at most once every 9100 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()} 9101 * to avoid unnecessary load to the system. Also once a view has a pending 9102 * notification this method is a NOP until the notification has been sent. 9103 * 9104 * @hide 9105 */ 9106 public void notifySubtreeAccessibilityStateChangedIfNeeded() { 9107 if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) { 9108 return; 9109 } 9110 if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) { 9111 mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9112 if (mParent != null) { 9113 try { 9114 mParent.notifySubtreeAccessibilityStateChanged( 9115 this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); 9116 } catch (AbstractMethodError e) { 9117 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 9118 " does not fully implement ViewParent", e); 9119 } 9120 } 9121 } 9122 } 9123 9124 /** 9125 * Change the visibility of the View without triggering any other changes. This is 9126 * important for transitions, where visibility changes should not adjust focus or 9127 * trigger a new layout. This is only used when the visibility has already been changed 9128 * and we need a transient value during an animation. When the animation completes, 9129 * the original visibility value is always restored. 9130 * 9131 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}. 9132 * @hide 9133 */ 9134 public void setTransitionVisibility(@Visibility int visibility) { 9135 mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility; 9136 } 9137 9138 /** 9139 * Reset the flag indicating the accessibility state of the subtree rooted 9140 * at this view changed. 9141 */ 9142 void resetSubtreeAccessibilityStateChanged() { 9143 mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED; 9144 } 9145 9146 /** 9147 * Report an accessibility action to this view's parents for delegated processing. 9148 * 9149 * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally 9150 * call this method to delegate an accessibility action to a supporting parent. If the parent 9151 * returns true from its 9152 * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)} 9153 * method this method will return true to signify that the action was consumed.</p> 9154 * 9155 * <p>This method is useful for implementing nested scrolling child views. If 9156 * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action 9157 * a custom view implementation may invoke this method to allow a parent to consume the 9158 * scroll first. If this method returns true the custom view should skip its own scrolling 9159 * behavior.</p> 9160 * 9161 * @param action Accessibility action to delegate 9162 * @param arguments Optional action arguments 9163 * @return true if the action was consumed by a parent 9164 */ 9165 public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) { 9166 for (ViewParent p = getParent(); p != null; p = p.getParent()) { 9167 if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) { 9168 return true; 9169 } 9170 } 9171 return false; 9172 } 9173 9174 /** 9175 * Performs the specified accessibility action on the view. For 9176 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 9177 * <p> 9178 * If an {@link AccessibilityDelegate} has been specified via calling 9179 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its 9180 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)} 9181 * is responsible for handling this call. 9182 * </p> 9183 * 9184 * <p>The default implementation will delegate 9185 * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and 9186 * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if 9187 * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p> 9188 * 9189 * @param action The action to perform. 9190 * @param arguments Optional action arguments. 9191 * @return Whether the action was performed. 9192 */ 9193 public boolean performAccessibilityAction(int action, Bundle arguments) { 9194 if (mAccessibilityDelegate != null) { 9195 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments); 9196 } else { 9197 return performAccessibilityActionInternal(action, arguments); 9198 } 9199 } 9200 9201 /** 9202 * @see #performAccessibilityAction(int, Bundle) 9203 * 9204 * Note: Called from the default {@link AccessibilityDelegate}. 9205 * 9206 * @hide 9207 */ 9208 public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 9209 if (isNestedScrollingEnabled() 9210 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD 9211 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD 9212 || action == R.id.accessibilityActionScrollUp 9213 || action == R.id.accessibilityActionScrollLeft 9214 || action == R.id.accessibilityActionScrollDown 9215 || action == R.id.accessibilityActionScrollRight)) { 9216 if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) { 9217 return true; 9218 } 9219 } 9220 9221 switch (action) { 9222 case AccessibilityNodeInfo.ACTION_CLICK: { 9223 if (isClickable()) { 9224 performClick(); 9225 return true; 9226 } 9227 } break; 9228 case AccessibilityNodeInfo.ACTION_LONG_CLICK: { 9229 if (isLongClickable()) { 9230 performLongClick(); 9231 return true; 9232 } 9233 } break; 9234 case AccessibilityNodeInfo.ACTION_FOCUS: { 9235 if (!hasFocus()) { 9236 // Get out of touch mode since accessibility 9237 // wants to move focus around. 9238 getViewRootImpl().ensureTouchMode(false); 9239 return requestFocus(); 9240 } 9241 } break; 9242 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: { 9243 if (hasFocus()) { 9244 clearFocus(); 9245 return !isFocused(); 9246 } 9247 } break; 9248 case AccessibilityNodeInfo.ACTION_SELECT: { 9249 if (!isSelected()) { 9250 setSelected(true); 9251 return isSelected(); 9252 } 9253 } break; 9254 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: { 9255 if (isSelected()) { 9256 setSelected(false); 9257 return !isSelected(); 9258 } 9259 } break; 9260 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: { 9261 if (!isAccessibilityFocused()) { 9262 return requestAccessibilityFocus(); 9263 } 9264 } break; 9265 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: { 9266 if (isAccessibilityFocused()) { 9267 clearAccessibilityFocus(); 9268 return true; 9269 } 9270 } break; 9271 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: { 9272 if (arguments != null) { 9273 final int granularity = arguments.getInt( 9274 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9275 final boolean extendSelection = arguments.getBoolean( 9276 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9277 return traverseAtGranularity(granularity, true, extendSelection); 9278 } 9279 } break; 9280 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: { 9281 if (arguments != null) { 9282 final int granularity = arguments.getInt( 9283 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT); 9284 final boolean extendSelection = arguments.getBoolean( 9285 AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN); 9286 return traverseAtGranularity(granularity, false, extendSelection); 9287 } 9288 } break; 9289 case AccessibilityNodeInfo.ACTION_SET_SELECTION: { 9290 CharSequence text = getIterableTextForAccessibility(); 9291 if (text == null) { 9292 return false; 9293 } 9294 final int start = (arguments != null) ? arguments.getInt( 9295 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; 9296 final int end = (arguments != null) ? arguments.getInt( 9297 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; 9298 // Only cursor position can be specified (selection length == 0) 9299 if ((getAccessibilitySelectionStart() != start 9300 || getAccessibilitySelectionEnd() != end) 9301 && (start == end)) { 9302 setAccessibilitySelection(start, end); 9303 notifyViewAccessibilityStateChangedIfNeeded( 9304 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 9305 return true; 9306 } 9307 } break; 9308 case R.id.accessibilityActionShowOnScreen: { 9309 if (mAttachInfo != null) { 9310 final Rect r = mAttachInfo.mTmpInvalRect; 9311 getDrawingRect(r); 9312 return requestRectangleOnScreen(r, true); 9313 } 9314 } break; 9315 case R.id.accessibilityActionContextClick: { 9316 if (isContextClickable()) { 9317 performContextClick(); 9318 return true; 9319 } 9320 } break; 9321 } 9322 return false; 9323 } 9324 9325 private boolean traverseAtGranularity(int granularity, boolean forward, 9326 boolean extendSelection) { 9327 CharSequence text = getIterableTextForAccessibility(); 9328 if (text == null || text.length() == 0) { 9329 return false; 9330 } 9331 TextSegmentIterator iterator = getIteratorForGranularity(granularity); 9332 if (iterator == null) { 9333 return false; 9334 } 9335 int current = getAccessibilitySelectionEnd(); 9336 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9337 current = forward ? 0 : text.length(); 9338 } 9339 final int[] range = forward ? iterator.following(current) : iterator.preceding(current); 9340 if (range == null) { 9341 return false; 9342 } 9343 final int segmentStart = range[0]; 9344 final int segmentEnd = range[1]; 9345 int selectionStart; 9346 int selectionEnd; 9347 if (extendSelection && isAccessibilitySelectionExtendable()) { 9348 selectionStart = getAccessibilitySelectionStart(); 9349 if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) { 9350 selectionStart = forward ? segmentStart : segmentEnd; 9351 } 9352 selectionEnd = forward ? segmentEnd : segmentStart; 9353 } else { 9354 selectionStart = selectionEnd= forward ? segmentEnd : segmentStart; 9355 } 9356 setAccessibilitySelection(selectionStart, selectionEnd); 9357 final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY 9358 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY; 9359 sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd); 9360 return true; 9361 } 9362 9363 /** 9364 * Gets the text reported for accessibility purposes. 9365 * 9366 * @return The accessibility text. 9367 * 9368 * @hide 9369 */ 9370 public CharSequence getIterableTextForAccessibility() { 9371 return getContentDescription(); 9372 } 9373 9374 /** 9375 * Gets whether accessibility selection can be extended. 9376 * 9377 * @return If selection is extensible. 9378 * 9379 * @hide 9380 */ 9381 public boolean isAccessibilitySelectionExtendable() { 9382 return false; 9383 } 9384 9385 /** 9386 * @hide 9387 */ 9388 public int getAccessibilitySelectionStart() { 9389 return mAccessibilityCursorPosition; 9390 } 9391 9392 /** 9393 * @hide 9394 */ 9395 public int getAccessibilitySelectionEnd() { 9396 return getAccessibilitySelectionStart(); 9397 } 9398 9399 /** 9400 * @hide 9401 */ 9402 public void setAccessibilitySelection(int start, int end) { 9403 if (start == end && end == mAccessibilityCursorPosition) { 9404 return; 9405 } 9406 if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) { 9407 mAccessibilityCursorPosition = start; 9408 } else { 9409 mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED; 9410 } 9411 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); 9412 } 9413 9414 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity, 9415 int fromIndex, int toIndex) { 9416 if (mParent == null) { 9417 return; 9418 } 9419 AccessibilityEvent event = AccessibilityEvent.obtain( 9420 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); 9421 onInitializeAccessibilityEvent(event); 9422 onPopulateAccessibilityEvent(event); 9423 event.setFromIndex(fromIndex); 9424 event.setToIndex(toIndex); 9425 event.setAction(action); 9426 event.setMovementGranularity(granularity); 9427 mParent.requestSendAccessibilityEvent(this, event); 9428 } 9429 9430 /** 9431 * @hide 9432 */ 9433 public TextSegmentIterator getIteratorForGranularity(int granularity) { 9434 switch (granularity) { 9435 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: { 9436 CharSequence text = getIterableTextForAccessibility(); 9437 if (text != null && text.length() > 0) { 9438 CharacterTextSegmentIterator iterator = 9439 CharacterTextSegmentIterator.getInstance( 9440 mContext.getResources().getConfiguration().locale); 9441 iterator.initialize(text.toString()); 9442 return iterator; 9443 } 9444 } break; 9445 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: { 9446 CharSequence text = getIterableTextForAccessibility(); 9447 if (text != null && text.length() > 0) { 9448 WordTextSegmentIterator iterator = 9449 WordTextSegmentIterator.getInstance( 9450 mContext.getResources().getConfiguration().locale); 9451 iterator.initialize(text.toString()); 9452 return iterator; 9453 } 9454 } break; 9455 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: { 9456 CharSequence text = getIterableTextForAccessibility(); 9457 if (text != null && text.length() > 0) { 9458 ParagraphTextSegmentIterator iterator = 9459 ParagraphTextSegmentIterator.getInstance(); 9460 iterator.initialize(text.toString()); 9461 return iterator; 9462 } 9463 } break; 9464 } 9465 return null; 9466 } 9467 9468 /** 9469 * @hide 9470 */ 9471 public void dispatchStartTemporaryDetach() { 9472 onStartTemporaryDetach(); 9473 } 9474 9475 /** 9476 * This is called when a container is going to temporarily detach a child, with 9477 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}. 9478 * It will either be followed by {@link #onFinishTemporaryDetach()} or 9479 * {@link #onDetachedFromWindow()} when the container is done. 9480 */ 9481 public void onStartTemporaryDetach() { 9482 removeUnsetPressCallback(); 9483 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT; 9484 } 9485 9486 /** 9487 * @hide 9488 */ 9489 public void dispatchFinishTemporaryDetach() { 9490 onFinishTemporaryDetach(); 9491 } 9492 9493 /** 9494 * Called after {@link #onStartTemporaryDetach} when the container is done 9495 * changing the view. 9496 */ 9497 public void onFinishTemporaryDetach() { 9498 } 9499 9500 /** 9501 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} 9502 * for this view's window. Returns null if the view is not currently attached 9503 * to the window. Normally you will not need to use this directly, but 9504 * just use the standard high-level event callbacks like 9505 * {@link #onKeyDown(int, KeyEvent)}. 9506 */ 9507 public KeyEvent.DispatcherState getKeyDispatcherState() { 9508 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; 9509 } 9510 9511 /** 9512 * Dispatch a key event before it is processed by any input method 9513 * associated with the view hierarchy. This can be used to intercept 9514 * key events in special situations before the IME consumes them; a 9515 * typical example would be handling the BACK key to update the application's 9516 * UI instead of allowing the IME to see it and close itself. 9517 * 9518 * @param event The key event to be dispatched. 9519 * @return True if the event was handled, false otherwise. 9520 */ 9521 public boolean dispatchKeyEventPreIme(KeyEvent event) { 9522 return onKeyPreIme(event.getKeyCode(), event); 9523 } 9524 9525 /** 9526 * Dispatch a key event to the next view on the focus path. This path runs 9527 * from the top of the view tree down to the currently focused view. If this 9528 * view has focus, it will dispatch to itself. Otherwise it will dispatch 9529 * the next node down the focus path. This method also fires any key 9530 * listeners. 9531 * 9532 * @param event The key event to be dispatched. 9533 * @return True if the event was handled, false otherwise. 9534 */ 9535 public boolean dispatchKeyEvent(KeyEvent event) { 9536 if (mInputEventConsistencyVerifier != null) { 9537 mInputEventConsistencyVerifier.onKeyEvent(event, 0); 9538 } 9539 9540 // Give any attached key listener a first crack at the event. 9541 //noinspection SimplifiableIfStatement 9542 ListenerInfo li = mListenerInfo; 9543 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 9544 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) { 9545 return true; 9546 } 9547 9548 if (event.dispatch(this, mAttachInfo != null 9549 ? mAttachInfo.mKeyDispatchState : null, this)) { 9550 return true; 9551 } 9552 9553 if (mInputEventConsistencyVerifier != null) { 9554 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9555 } 9556 return false; 9557 } 9558 9559 /** 9560 * Dispatches a key shortcut event. 9561 * 9562 * @param event The key event to be dispatched. 9563 * @return True if the event was handled by the view, false otherwise. 9564 */ 9565 public boolean dispatchKeyShortcutEvent(KeyEvent event) { 9566 return onKeyShortcut(event.getKeyCode(), event); 9567 } 9568 9569 /** 9570 * Pass the touch screen motion event down to the target view, or this 9571 * view if it is the target. 9572 * 9573 * @param event The motion event to be dispatched. 9574 * @return True if the event was handled by the view, false otherwise. 9575 */ 9576 public boolean dispatchTouchEvent(MotionEvent event) { 9577 // If the event should be handled by accessibility focus first. 9578 if (event.isTargetAccessibilityFocus()) { 9579 // We don't have focus or no virtual descendant has it, do not handle the event. 9580 if (!isAccessibilityFocusedViewOrHost()) { 9581 return false; 9582 } 9583 // We have focus and got the event, then use normal event dispatch. 9584 event.setTargetAccessibilityFocus(false); 9585 } 9586 9587 boolean result = false; 9588 9589 if (mInputEventConsistencyVerifier != null) { 9590 mInputEventConsistencyVerifier.onTouchEvent(event, 0); 9591 } 9592 9593 final int actionMasked = event.getActionMasked(); 9594 if (actionMasked == MotionEvent.ACTION_DOWN) { 9595 // Defensive cleanup for new gesture 9596 stopNestedScroll(); 9597 } 9598 9599 if (onFilterTouchEventForSecurity(event)) { 9600 //noinspection SimplifiableIfStatement 9601 ListenerInfo li = mListenerInfo; 9602 if (li != null && li.mOnTouchListener != null 9603 && (mViewFlags & ENABLED_MASK) == ENABLED 9604 && li.mOnTouchListener.onTouch(this, event)) { 9605 result = true; 9606 } 9607 9608 if (!result && onTouchEvent(event)) { 9609 result = true; 9610 } 9611 } 9612 9613 if (!result && mInputEventConsistencyVerifier != null) { 9614 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9615 } 9616 9617 // Clean up after nested scrolls if this is the end of a gesture; 9618 // also cancel it if we tried an ACTION_DOWN but we didn't want the rest 9619 // of the gesture. 9620 if (actionMasked == MotionEvent.ACTION_UP || 9621 actionMasked == MotionEvent.ACTION_CANCEL || 9622 (actionMasked == MotionEvent.ACTION_DOWN && !result)) { 9623 stopNestedScroll(); 9624 } 9625 9626 return result; 9627 } 9628 9629 boolean isAccessibilityFocusedViewOrHost() { 9630 return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl() 9631 .getAccessibilityFocusedHost() == this); 9632 } 9633 9634 /** 9635 * Filter the touch event to apply security policies. 9636 * 9637 * @param event The motion event to be filtered. 9638 * @return True if the event should be dispatched, false if the event should be dropped. 9639 * 9640 * @see #getFilterTouchesWhenObscured 9641 */ 9642 public boolean onFilterTouchEventForSecurity(MotionEvent event) { 9643 //noinspection RedundantIfStatement 9644 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0 9645 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) { 9646 // Window is obscured, drop this touch. 9647 return false; 9648 } 9649 return true; 9650 } 9651 9652 /** 9653 * Pass a trackball motion event down to the focused view. 9654 * 9655 * @param event The motion event to be dispatched. 9656 * @return True if the event was handled by the view, false otherwise. 9657 */ 9658 public boolean dispatchTrackballEvent(MotionEvent event) { 9659 if (mInputEventConsistencyVerifier != null) { 9660 mInputEventConsistencyVerifier.onTrackballEvent(event, 0); 9661 } 9662 9663 return onTrackballEvent(event); 9664 } 9665 9666 /** 9667 * Dispatch a generic motion event. 9668 * <p> 9669 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 9670 * are delivered to the view under the pointer. All other generic motion events are 9671 * delivered to the focused view. Hover events are handled specially and are delivered 9672 * to {@link #onHoverEvent(MotionEvent)}. 9673 * </p> 9674 * 9675 * @param event The motion event to be dispatched. 9676 * @return True if the event was handled by the view, false otherwise. 9677 */ 9678 public boolean dispatchGenericMotionEvent(MotionEvent event) { 9679 if (mInputEventConsistencyVerifier != null) { 9680 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0); 9681 } 9682 9683 final int source = event.getSource(); 9684 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 9685 final int action = event.getAction(); 9686 if (action == MotionEvent.ACTION_HOVER_ENTER 9687 || action == MotionEvent.ACTION_HOVER_MOVE 9688 || action == MotionEvent.ACTION_HOVER_EXIT) { 9689 if (dispatchHoverEvent(event)) { 9690 return true; 9691 } 9692 } else if (dispatchGenericPointerEvent(event)) { 9693 return true; 9694 } 9695 } else if (dispatchGenericFocusedEvent(event)) { 9696 return true; 9697 } 9698 9699 if (dispatchGenericMotionEventInternal(event)) { 9700 return true; 9701 } 9702 9703 if (mInputEventConsistencyVerifier != null) { 9704 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9705 } 9706 return false; 9707 } 9708 9709 private boolean dispatchGenericMotionEventInternal(MotionEvent event) { 9710 //noinspection SimplifiableIfStatement 9711 ListenerInfo li = mListenerInfo; 9712 if (li != null && li.mOnGenericMotionListener != null 9713 && (mViewFlags & ENABLED_MASK) == ENABLED 9714 && li.mOnGenericMotionListener.onGenericMotion(this, event)) { 9715 return true; 9716 } 9717 9718 if (onGenericMotionEvent(event)) { 9719 return true; 9720 } 9721 9722 final int actionButton = event.getActionButton(); 9723 switch (event.getActionMasked()) { 9724 case MotionEvent.ACTION_BUTTON_PRESS: 9725 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress 9726 && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 9727 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 9728 if (performContextClick()) { 9729 mInContextButtonPress = true; 9730 setPressed(true, event.getX(), event.getY()); 9731 removeTapCallback(); 9732 removeLongPressCallback(); 9733 return true; 9734 } 9735 } 9736 break; 9737 9738 case MotionEvent.ACTION_BUTTON_RELEASE: 9739 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY 9740 || actionButton == MotionEvent.BUTTON_SECONDARY)) { 9741 mInContextButtonPress = false; 9742 mIgnoreNextUpEvent = true; 9743 } 9744 break; 9745 } 9746 9747 if (mInputEventConsistencyVerifier != null) { 9748 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); 9749 } 9750 return false; 9751 } 9752 9753 /** 9754 * Dispatch a hover event. 9755 * <p> 9756 * Do not call this method directly. 9757 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 9758 * </p> 9759 * 9760 * @param event The motion event to be dispatched. 9761 * @return True if the event was handled by the view, false otherwise. 9762 */ 9763 protected boolean dispatchHoverEvent(MotionEvent event) { 9764 ListenerInfo li = mListenerInfo; 9765 //noinspection SimplifiableIfStatement 9766 if (li != null && li.mOnHoverListener != null 9767 && (mViewFlags & ENABLED_MASK) == ENABLED 9768 && li.mOnHoverListener.onHover(this, event)) { 9769 return true; 9770 } 9771 9772 return onHoverEvent(event); 9773 } 9774 9775 /** 9776 * Returns true if the view has a child to which it has recently sent 9777 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and 9778 * it does not have a hovered child, then it must be the innermost hovered view. 9779 * @hide 9780 */ 9781 protected boolean hasHoveredChild() { 9782 return false; 9783 } 9784 9785 /** 9786 * Dispatch a generic motion event to the view under the first pointer. 9787 * <p> 9788 * Do not call this method directly. 9789 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 9790 * </p> 9791 * 9792 * @param event The motion event to be dispatched. 9793 * @return True if the event was handled by the view, false otherwise. 9794 */ 9795 protected boolean dispatchGenericPointerEvent(MotionEvent event) { 9796 return false; 9797 } 9798 9799 /** 9800 * Dispatch a generic motion event to the currently focused view. 9801 * <p> 9802 * Do not call this method directly. 9803 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead. 9804 * </p> 9805 * 9806 * @param event The motion event to be dispatched. 9807 * @return True if the event was handled by the view, false otherwise. 9808 */ 9809 protected boolean dispatchGenericFocusedEvent(MotionEvent event) { 9810 return false; 9811 } 9812 9813 /** 9814 * Dispatch a pointer event. 9815 * <p> 9816 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all 9817 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns 9818 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches 9819 * and should not be expected to handle other pointing device features. 9820 * </p> 9821 * 9822 * @param event The motion event to be dispatched. 9823 * @return True if the event was handled by the view, false otherwise. 9824 * @hide 9825 */ 9826 public final boolean dispatchPointerEvent(MotionEvent event) { 9827 if (event.isTouchEvent()) { 9828 return dispatchTouchEvent(event); 9829 } else { 9830 return dispatchGenericMotionEvent(event); 9831 } 9832 } 9833 9834 /** 9835 * Called when the window containing this view gains or loses window focus. 9836 * ViewGroups should override to route to their children. 9837 * 9838 * @param hasFocus True if the window containing this view now has focus, 9839 * false otherwise. 9840 */ 9841 public void dispatchWindowFocusChanged(boolean hasFocus) { 9842 onWindowFocusChanged(hasFocus); 9843 } 9844 9845 /** 9846 * Called when the window containing this view gains or loses focus. Note 9847 * that this is separate from view focus: to receive key events, both 9848 * your view and its window must have focus. If a window is displayed 9849 * on top of yours that takes input focus, then your own window will lose 9850 * focus but the view focus will remain unchanged. 9851 * 9852 * @param hasWindowFocus True if the window containing this view now has 9853 * focus, false otherwise. 9854 */ 9855 public void onWindowFocusChanged(boolean hasWindowFocus) { 9856 InputMethodManager imm = InputMethodManager.peekInstance(); 9857 if (!hasWindowFocus) { 9858 if (isPressed()) { 9859 setPressed(false); 9860 } 9861 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 9862 imm.focusOut(this); 9863 } 9864 removeLongPressCallback(); 9865 removeTapCallback(); 9866 onFocusLost(); 9867 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) { 9868 imm.focusIn(this); 9869 } 9870 refreshDrawableState(); 9871 } 9872 9873 /** 9874 * Returns true if this view is in a window that currently has window focus. 9875 * Note that this is not the same as the view itself having focus. 9876 * 9877 * @return True if this view is in a window that currently has window focus. 9878 */ 9879 public boolean hasWindowFocus() { 9880 return mAttachInfo != null && mAttachInfo.mHasWindowFocus; 9881 } 9882 9883 /** 9884 * Dispatch a view visibility change down the view hierarchy. 9885 * ViewGroups should override to route to their children. 9886 * @param changedView The view whose visibility changed. Could be 'this' or 9887 * an ancestor view. 9888 * @param visibility The new visibility of changedView: {@link #VISIBLE}, 9889 * {@link #INVISIBLE} or {@link #GONE}. 9890 */ 9891 protected void dispatchVisibilityChanged(@NonNull View changedView, 9892 @Visibility int visibility) { 9893 onVisibilityChanged(changedView, visibility); 9894 } 9895 9896 /** 9897 * Called when the visibility of the view or an ancestor of the view has 9898 * changed. 9899 * 9900 * @param changedView The view whose visibility changed. May be 9901 * {@code this} or an ancestor view. 9902 * @param visibility The new visibility, one of {@link #VISIBLE}, 9903 * {@link #INVISIBLE} or {@link #GONE}. 9904 */ 9905 protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { 9906 final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE; 9907 if (visible && mAttachInfo != null) { 9908 initialAwakenScrollBars(); 9909 } 9910 9911 final Drawable dr = mBackground; 9912 if (dr != null && visible != dr.isVisible()) { 9913 dr.setVisible(visible, false); 9914 } 9915 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 9916 if (fg != null && visible != fg.isVisible()) { 9917 fg.setVisible(visible, false); 9918 } 9919 } 9920 9921 /** 9922 * Dispatch a hint about whether this view is displayed. For instance, when 9923 * a View moves out of the screen, it might receives a display hint indicating 9924 * the view is not displayed. Applications should not <em>rely</em> on this hint 9925 * as there is no guarantee that they will receive one. 9926 * 9927 * @param hint A hint about whether or not this view is displayed: 9928 * {@link #VISIBLE} or {@link #INVISIBLE}. 9929 */ 9930 public void dispatchDisplayHint(@Visibility int hint) { 9931 onDisplayHint(hint); 9932 } 9933 9934 /** 9935 * Gives this view a hint about whether is displayed or not. For instance, when 9936 * a View moves out of the screen, it might receives a display hint indicating 9937 * the view is not displayed. Applications should not <em>rely</em> on this hint 9938 * as there is no guarantee that they will receive one. 9939 * 9940 * @param hint A hint about whether or not this view is displayed: 9941 * {@link #VISIBLE} or {@link #INVISIBLE}. 9942 */ 9943 protected void onDisplayHint(@Visibility int hint) { 9944 } 9945 9946 /** 9947 * Dispatch a window visibility change down the view hierarchy. 9948 * ViewGroups should override to route to their children. 9949 * 9950 * @param visibility The new visibility of the window. 9951 * 9952 * @see #onWindowVisibilityChanged(int) 9953 */ 9954 public void dispatchWindowVisibilityChanged(@Visibility int visibility) { 9955 onWindowVisibilityChanged(visibility); 9956 } 9957 9958 /** 9959 * Called when the window containing has change its visibility 9960 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note 9961 * that this tells you whether or not your window is being made visible 9962 * to the window manager; this does <em>not</em> tell you whether or not 9963 * your window is obscured by other windows on the screen, even if it 9964 * is itself visible. 9965 * 9966 * @param visibility The new visibility of the window. 9967 */ 9968 protected void onWindowVisibilityChanged(@Visibility int visibility) { 9969 if (visibility == VISIBLE) { 9970 initialAwakenScrollBars(); 9971 } 9972 } 9973 9974 /** 9975 * Returns the current visibility of the window this view is attached to 9976 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). 9977 * 9978 * @return Returns the current visibility of the view's window. 9979 */ 9980 @Visibility 9981 public int getWindowVisibility() { 9982 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE; 9983 } 9984 9985 /** 9986 * Retrieve the overall visible display size in which the window this view is 9987 * attached to has been positioned in. This takes into account screen 9988 * decorations above the window, for both cases where the window itself 9989 * is being position inside of them or the window is being placed under 9990 * then and covered insets are used for the window to position its content 9991 * inside. In effect, this tells you the available area where content can 9992 * be placed and remain visible to users. 9993 * 9994 * <p>This function requires an IPC back to the window manager to retrieve 9995 * the requested information, so should not be used in performance critical 9996 * code like drawing. 9997 * 9998 * @param outRect Filled in with the visible display frame. If the view 9999 * is not attached to a window, this is simply the raw display size. 10000 */ 10001 public void getWindowVisibleDisplayFrame(Rect outRect) { 10002 if (mAttachInfo != null) { 10003 try { 10004 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); 10005 } catch (RemoteException e) { 10006 return; 10007 } 10008 // XXX This is really broken, and probably all needs to be done 10009 // in the window manager, and we need to know more about whether 10010 // we want the area behind or in front of the IME. 10011 final Rect insets = mAttachInfo.mVisibleInsets; 10012 outRect.left += insets.left; 10013 outRect.top += insets.top; 10014 outRect.right -= insets.right; 10015 outRect.bottom -= insets.bottom; 10016 return; 10017 } 10018 // The view is not attached to a display so we don't have a context. 10019 // Make a best guess about the display size. 10020 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY); 10021 d.getRectSize(outRect); 10022 } 10023 10024 /** 10025 * Dispatch a notification about a resource configuration change down 10026 * the view hierarchy. 10027 * ViewGroups should override to route to their children. 10028 * 10029 * @param newConfig The new resource configuration. 10030 * 10031 * @see #onConfigurationChanged(android.content.res.Configuration) 10032 */ 10033 public void dispatchConfigurationChanged(Configuration newConfig) { 10034 onConfigurationChanged(newConfig); 10035 } 10036 10037 /** 10038 * Called when the current configuration of the resources being used 10039 * by the application have changed. You can use this to decide when 10040 * to reload resources that can changed based on orientation and other 10041 * configuration characteristics. You only need to use this if you are 10042 * not relying on the normal {@link android.app.Activity} mechanism of 10043 * recreating the activity instance upon a configuration change. 10044 * 10045 * @param newConfig The new resource configuration. 10046 */ 10047 protected void onConfigurationChanged(Configuration newConfig) { 10048 } 10049 10050 /** 10051 * Private function to aggregate all per-view attributes in to the view 10052 * root. 10053 */ 10054 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10055 performCollectViewAttributes(attachInfo, visibility); 10056 } 10057 10058 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) { 10059 if ((visibility & VISIBILITY_MASK) == VISIBLE) { 10060 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) { 10061 attachInfo.mKeepScreenOn = true; 10062 } 10063 attachInfo.mSystemUiVisibility |= mSystemUiVisibility; 10064 ListenerInfo li = mListenerInfo; 10065 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 10066 attachInfo.mHasSystemUiListeners = true; 10067 } 10068 } 10069 } 10070 10071 void needGlobalAttributesUpdate(boolean force) { 10072 final AttachInfo ai = mAttachInfo; 10073 if (ai != null && !ai.mRecomputeGlobalAttributes) { 10074 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0) 10075 || ai.mHasSystemUiListeners) { 10076 ai.mRecomputeGlobalAttributes = true; 10077 } 10078 } 10079 } 10080 10081 /** 10082 * Returns whether the device is currently in touch mode. Touch mode is entered 10083 * once the user begins interacting with the device by touch, and affects various 10084 * things like whether focus is always visible to the user. 10085 * 10086 * @return Whether the device is in touch mode. 10087 */ 10088 @ViewDebug.ExportedProperty 10089 public boolean isInTouchMode() { 10090 if (mAttachInfo != null) { 10091 return mAttachInfo.mInTouchMode; 10092 } else { 10093 return ViewRootImpl.isInTouchMode(); 10094 } 10095 } 10096 10097 /** 10098 * Returns the context the view is running in, through which it can 10099 * access the current theme, resources, etc. 10100 * 10101 * @return The view's Context. 10102 */ 10103 @ViewDebug.CapturedViewProperty 10104 public final Context getContext() { 10105 return mContext; 10106 } 10107 10108 /** 10109 * Handle a key event before it is processed by any input method 10110 * associated with the view hierarchy. This can be used to intercept 10111 * key events in special situations before the IME consumes them; a 10112 * typical example would be handling the BACK key to update the application's 10113 * UI instead of allowing the IME to see it and close itself. 10114 * 10115 * @param keyCode The value in event.getKeyCode(). 10116 * @param event Description of the key event. 10117 * @return If you handled the event, return true. If you want to allow the 10118 * event to be handled by the next receiver, return false. 10119 */ 10120 public boolean onKeyPreIme(int keyCode, KeyEvent event) { 10121 return false; 10122 } 10123 10124 /** 10125 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent) 10126 * KeyEvent.Callback.onKeyDown()}: perform press of the view 10127 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER} 10128 * is released, if the view is enabled and clickable. 10129 * <p> 10130 * Key presses in software keyboards will generally NOT trigger this 10131 * listener, although some may elect to do so in some situations. Do not 10132 * rely on this to catch software key presses. 10133 * 10134 * @param keyCode a key code that represents the button pressed, from 10135 * {@link android.view.KeyEvent} 10136 * @param event the KeyEvent object that defines the button action 10137 */ 10138 public boolean onKeyDown(int keyCode, KeyEvent event) { 10139 if (KeyEvent.isConfirmKey(keyCode)) { 10140 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10141 return true; 10142 } 10143 10144 // Long clickable items don't necessarily have to be clickable. 10145 if (((mViewFlags & CLICKABLE) == CLICKABLE 10146 || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 10147 && (event.getRepeatCount() == 0)) { 10148 // For the purposes of menu anchoring and drawable hotspots, 10149 // key events are considered to be at the center of the view. 10150 final float x = getWidth() / 2f; 10151 final float y = getHeight() / 2f; 10152 setPressed(true, x, y); 10153 checkForLongClick(0, x, y); 10154 return true; 10155 } 10156 } 10157 10158 return false; 10159 } 10160 10161 /** 10162 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) 10163 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle 10164 * the event). 10165 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10166 * although some may elect to do so in some situations. Do not rely on this to 10167 * catch software key presses. 10168 */ 10169 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 10170 return false; 10171 } 10172 10173 /** 10174 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent) 10175 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view 10176 * when {@link KeyEvent#KEYCODE_DPAD_CENTER}, {@link KeyEvent#KEYCODE_ENTER} 10177 * or {@link KeyEvent#KEYCODE_SPACE} is released. 10178 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10179 * although some may elect to do so in some situations. Do not rely on this to 10180 * catch software key presses. 10181 * 10182 * @param keyCode A key code that represents the button pressed, from 10183 * {@link android.view.KeyEvent}. 10184 * @param event The KeyEvent object that defines the button action. 10185 */ 10186 public boolean onKeyUp(int keyCode, KeyEvent event) { 10187 if (KeyEvent.isConfirmKey(keyCode)) { 10188 if ((mViewFlags & ENABLED_MASK) == DISABLED) { 10189 return true; 10190 } 10191 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) { 10192 setPressed(false); 10193 10194 if (!mHasPerformedLongPress) { 10195 // This is a tap, so remove the longpress check 10196 removeLongPressCallback(); 10197 return performClick(); 10198 } 10199 } 10200 } 10201 return false; 10202 } 10203 10204 /** 10205 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) 10206 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle 10207 * the event). 10208 * <p>Key presses in software keyboards will generally NOT trigger this listener, 10209 * although some may elect to do so in some situations. Do not rely on this to 10210 * catch software key presses. 10211 * 10212 * @param keyCode A key code that represents the button pressed, from 10213 * {@link android.view.KeyEvent}. 10214 * @param repeatCount The number of times the action was made. 10215 * @param event The KeyEvent object that defines the button action. 10216 */ 10217 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 10218 return false; 10219 } 10220 10221 /** 10222 * Called on the focused view when a key shortcut event is not handled. 10223 * Override this method to implement local key shortcuts for the View. 10224 * Key shortcuts can also be implemented by setting the 10225 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items. 10226 * 10227 * @param keyCode The value in event.getKeyCode(). 10228 * @param event Description of the key event. 10229 * @return If you handled the event, return true. If you want to allow the 10230 * event to be handled by the next receiver, return false. 10231 */ 10232 public boolean onKeyShortcut(int keyCode, KeyEvent event) { 10233 return false; 10234 } 10235 10236 /** 10237 * Check whether the called view is a text editor, in which case it 10238 * would make sense to automatically display a soft input window for 10239 * it. Subclasses should override this if they implement 10240 * {@link #onCreateInputConnection(EditorInfo)} to return true if 10241 * a call on that method would return a non-null InputConnection, and 10242 * they are really a first-class editor that the user would normally 10243 * start typing on when the go into a window containing your view. 10244 * 10245 * <p>The default implementation always returns false. This does 10246 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)} 10247 * will not be called or the user can not otherwise perform edits on your 10248 * view; it is just a hint to the system that this is not the primary 10249 * purpose of this view. 10250 * 10251 * @return Returns true if this view is a text editor, else false. 10252 */ 10253 public boolean onCheckIsTextEditor() { 10254 return false; 10255 } 10256 10257 /** 10258 * Create a new InputConnection for an InputMethod to interact 10259 * with the view. The default implementation returns null, since it doesn't 10260 * support input methods. You can override this to implement such support. 10261 * This is only needed for views that take focus and text input. 10262 * 10263 * <p>When implementing this, you probably also want to implement 10264 * {@link #onCheckIsTextEditor()} to indicate you will return a 10265 * non-null InputConnection.</p> 10266 * 10267 * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo} 10268 * object correctly and in its entirety, so that the connected IME can rely 10269 * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart} 10270 * and {@link android.view.inputmethod.EditorInfo#initialSelEnd} members 10271 * must be filled in with the correct cursor position for IMEs to work correctly 10272 * with your application.</p> 10273 * 10274 * @param outAttrs Fill in with attribute information about the connection. 10275 */ 10276 public InputConnection onCreateInputConnection(EditorInfo outAttrs) { 10277 return null; 10278 } 10279 10280 /** 10281 * Called by the {@link android.view.inputmethod.InputMethodManager} 10282 * when a view who is not the current 10283 * input connection target is trying to make a call on the manager. The 10284 * default implementation returns false; you can override this to return 10285 * true for certain views if you are performing InputConnection proxying 10286 * to them. 10287 * @param view The View that is making the InputMethodManager call. 10288 * @return Return true to allow the call, false to reject. 10289 */ 10290 public boolean checkInputConnectionProxy(View view) { 10291 return false; 10292 } 10293 10294 /** 10295 * Show the context menu for this view. It is not safe to hold on to the 10296 * menu after returning from this method. 10297 * 10298 * You should normally not overload this method. Overload 10299 * {@link #onCreateContextMenu(ContextMenu)} or define an 10300 * {@link OnCreateContextMenuListener} to add items to the context menu. 10301 * 10302 * @param menu The context menu to populate 10303 */ 10304 public void createContextMenu(ContextMenu menu) { 10305 ContextMenuInfo menuInfo = getContextMenuInfo(); 10306 10307 // Sets the current menu info so all items added to menu will have 10308 // my extra info set. 10309 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo); 10310 10311 onCreateContextMenu(menu); 10312 ListenerInfo li = mListenerInfo; 10313 if (li != null && li.mOnCreateContextMenuListener != null) { 10314 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo); 10315 } 10316 10317 // Clear the extra information so subsequent items that aren't mine don't 10318 // have my extra info. 10319 ((MenuBuilder)menu).setCurrentMenuInfo(null); 10320 10321 if (mParent != null) { 10322 mParent.createContextMenu(menu); 10323 } 10324 } 10325 10326 /** 10327 * Views should implement this if they have extra information to associate 10328 * with the context menu. The return result is supplied as a parameter to 10329 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} 10330 * callback. 10331 * 10332 * @return Extra information about the item for which the context menu 10333 * should be shown. This information will vary across different 10334 * subclasses of View. 10335 */ 10336 protected ContextMenuInfo getContextMenuInfo() { 10337 return null; 10338 } 10339 10340 /** 10341 * Views should implement this if the view itself is going to add items to 10342 * the context menu. 10343 * 10344 * @param menu the context menu to populate 10345 */ 10346 protected void onCreateContextMenu(ContextMenu menu) { 10347 } 10348 10349 /** 10350 * Implement this method to handle trackball motion events. The 10351 * <em>relative</em> movement of the trackball since the last event 10352 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and 10353 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so 10354 * that a movement of 1 corresponds to the user pressing one DPAD key (so 10355 * they will often be fractional values, representing the more fine-grained 10356 * movement information available from a trackball). 10357 * 10358 * @param event The motion event. 10359 * @return True if the event was handled, false otherwise. 10360 */ 10361 public boolean onTrackballEvent(MotionEvent event) { 10362 return false; 10363 } 10364 10365 /** 10366 * Implement this method to handle generic motion events. 10367 * <p> 10368 * Generic motion events describe joystick movements, mouse hovers, track pad 10369 * touches, scroll wheel movements and other input events. The 10370 * {@link MotionEvent#getSource() source} of the motion event specifies 10371 * the class of input that was received. Implementations of this method 10372 * must examine the bits in the source before processing the event. 10373 * The following code example shows how this is done. 10374 * </p><p> 10375 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER} 10376 * are delivered to the view under the pointer. All other generic motion events are 10377 * delivered to the focused view. 10378 * </p> 10379 * <pre> public boolean onGenericMotionEvent(MotionEvent event) { 10380 * if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) { 10381 * if (event.getAction() == MotionEvent.ACTION_MOVE) { 10382 * // process the joystick movement... 10383 * return true; 10384 * } 10385 * } 10386 * if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { 10387 * switch (event.getAction()) { 10388 * case MotionEvent.ACTION_HOVER_MOVE: 10389 * // process the mouse hover movement... 10390 * return true; 10391 * case MotionEvent.ACTION_SCROLL: 10392 * // process the scroll wheel movement... 10393 * return true; 10394 * } 10395 * } 10396 * return super.onGenericMotionEvent(event); 10397 * }</pre> 10398 * 10399 * @param event The generic motion event being processed. 10400 * @return True if the event was handled, false otherwise. 10401 */ 10402 public boolean onGenericMotionEvent(MotionEvent event) { 10403 return false; 10404 } 10405 10406 /** 10407 * Implement this method to handle hover events. 10408 * <p> 10409 * This method is called whenever a pointer is hovering into, over, or out of the 10410 * bounds of a view and the view is not currently being touched. 10411 * Hover events are represented as pointer events with action 10412 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE}, 10413 * or {@link MotionEvent#ACTION_HOVER_EXIT}. 10414 * </p> 10415 * <ul> 10416 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER} 10417 * when the pointer enters the bounds of the view.</li> 10418 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE} 10419 * when the pointer has already entered the bounds of the view and has moved.</li> 10420 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT} 10421 * when the pointer has exited the bounds of the view or when the pointer is 10422 * about to go down due to a button click, tap, or similar user action that 10423 * causes the view to be touched.</li> 10424 * </ul> 10425 * <p> 10426 * The view should implement this method to return true to indicate that it is 10427 * handling the hover event, such as by changing its drawable state. 10428 * </p><p> 10429 * The default implementation calls {@link #setHovered} to update the hovered state 10430 * of the view when a hover enter or hover exit event is received, if the view 10431 * is enabled and is clickable. The default implementation also sends hover 10432 * accessibility events. 10433 * </p> 10434 * 10435 * @param event The motion event that describes the hover. 10436 * @return True if the view handled the hover event. 10437 * 10438 * @see #isHovered 10439 * @see #setHovered 10440 * @see #onHoverChanged 10441 */ 10442 public boolean onHoverEvent(MotionEvent event) { 10443 // The root view may receive hover (or touch) events that are outside the bounds of 10444 // the window. This code ensures that we only send accessibility events for 10445 // hovers that are actually within the bounds of the root view. 10446 final int action = event.getActionMasked(); 10447 if (!mSendingHoverAccessibilityEvents) { 10448 if ((action == MotionEvent.ACTION_HOVER_ENTER 10449 || action == MotionEvent.ACTION_HOVER_MOVE) 10450 && !hasHoveredChild() 10451 && pointInView(event.getX(), event.getY())) { 10452 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); 10453 mSendingHoverAccessibilityEvents = true; 10454 } 10455 } else { 10456 if (action == MotionEvent.ACTION_HOVER_EXIT 10457 || (action == MotionEvent.ACTION_MOVE 10458 && !pointInView(event.getX(), event.getY()))) { 10459 mSendingHoverAccessibilityEvents = false; 10460 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); 10461 } 10462 } 10463 10464 if (isHoverable()) { 10465 switch (action) { 10466 case MotionEvent.ACTION_HOVER_ENTER: 10467 setHovered(true); 10468 break; 10469 case MotionEvent.ACTION_HOVER_EXIT: 10470 setHovered(false); 10471 break; 10472 } 10473 10474 // Dispatch the event to onGenericMotionEvent before returning true. 10475 // This is to provide compatibility with existing applications that 10476 // handled HOVER_MOVE events in onGenericMotionEvent and that would 10477 // break because of the new default handling for hoverable views 10478 // in onHoverEvent. 10479 // Note that onGenericMotionEvent will be called by default when 10480 // onHoverEvent returns false (refer to dispatchGenericMotionEvent). 10481 dispatchGenericMotionEventInternal(event); 10482 // The event was already handled by calling setHovered(), so always 10483 // return true. 10484 return true; 10485 } 10486 10487 return false; 10488 } 10489 10490 /** 10491 * Returns true if the view should handle {@link #onHoverEvent} 10492 * by calling {@link #setHovered} to change its hovered state. 10493 * 10494 * @return True if the view is hoverable. 10495 */ 10496 private boolean isHoverable() { 10497 final int viewFlags = mViewFlags; 10498 if ((viewFlags & ENABLED_MASK) == DISABLED) { 10499 return false; 10500 } 10501 10502 return (viewFlags & CLICKABLE) == CLICKABLE 10503 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE 10504 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE; 10505 } 10506 10507 /** 10508 * Returns true if the view is currently hovered. 10509 * 10510 * @return True if the view is currently hovered. 10511 * 10512 * @see #setHovered 10513 * @see #onHoverChanged 10514 */ 10515 @ViewDebug.ExportedProperty 10516 public boolean isHovered() { 10517 return (mPrivateFlags & PFLAG_HOVERED) != 0; 10518 } 10519 10520 /** 10521 * Sets whether the view is currently hovered. 10522 * <p> 10523 * Calling this method also changes the drawable state of the view. This 10524 * enables the view to react to hover by using different drawable resources 10525 * to change its appearance. 10526 * </p><p> 10527 * The {@link #onHoverChanged} method is called when the hovered state changes. 10528 * </p> 10529 * 10530 * @param hovered True if the view is hovered. 10531 * 10532 * @see #isHovered 10533 * @see #onHoverChanged 10534 */ 10535 public void setHovered(boolean hovered) { 10536 if (hovered) { 10537 if ((mPrivateFlags & PFLAG_HOVERED) == 0) { 10538 mPrivateFlags |= PFLAG_HOVERED; 10539 refreshDrawableState(); 10540 onHoverChanged(true); 10541 } 10542 } else { 10543 if ((mPrivateFlags & PFLAG_HOVERED) != 0) { 10544 mPrivateFlags &= ~PFLAG_HOVERED; 10545 refreshDrawableState(); 10546 onHoverChanged(false); 10547 } 10548 } 10549 } 10550 10551 /** 10552 * Implement this method to handle hover state changes. 10553 * <p> 10554 * This method is called whenever the hover state changes as a result of a 10555 * call to {@link #setHovered}. 10556 * </p> 10557 * 10558 * @param hovered The current hover state, as returned by {@link #isHovered}. 10559 * 10560 * @see #isHovered 10561 * @see #setHovered 10562 */ 10563 public void onHoverChanged(boolean hovered) { 10564 } 10565 10566 /** 10567 * Implement this method to handle touch screen motion events. 10568 * <p> 10569 * If this method is used to detect click actions, it is recommended that 10570 * the actions be performed by implementing and calling 10571 * {@link #performClick()}. This will ensure consistent system behavior, 10572 * including: 10573 * <ul> 10574 * <li>obeying click sound preferences 10575 * <li>dispatching OnClickListener calls 10576 * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when 10577 * accessibility features are enabled 10578 * </ul> 10579 * 10580 * @param event The motion event. 10581 * @return True if the event was handled, false otherwise. 10582 */ 10583 public boolean onTouchEvent(MotionEvent event) { 10584 final float x = event.getX(); 10585 final float y = event.getY(); 10586 final int viewFlags = mViewFlags; 10587 final int action = event.getAction(); 10588 10589 if ((viewFlags & ENABLED_MASK) == DISABLED) { 10590 if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) { 10591 setPressed(false); 10592 } 10593 // A disabled view that is clickable still consumes the touch 10594 // events, it just doesn't respond to them. 10595 return (((viewFlags & CLICKABLE) == CLICKABLE 10596 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) 10597 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE); 10598 } 10599 10600 if (mTouchDelegate != null) { 10601 if (mTouchDelegate.onTouchEvent(event)) { 10602 return true; 10603 } 10604 } 10605 10606 if (((viewFlags & CLICKABLE) == CLICKABLE || 10607 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || 10608 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) { 10609 switch (action) { 10610 case MotionEvent.ACTION_UP: 10611 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 10612 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 10613 // take focus if we don't have it already and we should in 10614 // touch mode. 10615 boolean focusTaken = false; 10616 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 10617 focusTaken = requestFocus(); 10618 } 10619 10620 if (prepressed) { 10621 // The button is being released before we actually 10622 // showed it as pressed. Make it show the pressed 10623 // state now (before scheduling the click) to ensure 10624 // the user sees it. 10625 setPressed(true, x, y); 10626 } 10627 10628 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { 10629 // This is a tap, so remove the longpress check 10630 removeLongPressCallback(); 10631 10632 // Only perform take click actions if we were in the pressed state 10633 if (!focusTaken) { 10634 // Use a Runnable and post this rather than calling 10635 // performClick directly. This lets other visual state 10636 // of the view update before click actions start. 10637 if (mPerformClick == null) { 10638 mPerformClick = new PerformClick(); 10639 } 10640 if (!post(mPerformClick)) { 10641 performClick(); 10642 } 10643 } 10644 } 10645 10646 if (mUnsetPressedState == null) { 10647 mUnsetPressedState = new UnsetPressedState(); 10648 } 10649 10650 if (prepressed) { 10651 postDelayed(mUnsetPressedState, 10652 ViewConfiguration.getPressedStateDuration()); 10653 } else if (!post(mUnsetPressedState)) { 10654 // If the post failed, unpress right now 10655 mUnsetPressedState.run(); 10656 } 10657 10658 removeTapCallback(); 10659 } 10660 mIgnoreNextUpEvent = false; 10661 break; 10662 10663 case MotionEvent.ACTION_DOWN: 10664 mHasPerformedLongPress = false; 10665 10666 if (performButtonActionOnTouchDown(event)) { 10667 break; 10668 } 10669 10670 // Walk up the hierarchy to determine if we're inside a scrolling container. 10671 boolean isInScrollingContainer = isInScrollingContainer(); 10672 10673 // For views inside a scrolling container, delay the pressed feedback for 10674 // a short period in case this is a scroll. 10675 if (isInScrollingContainer) { 10676 mPrivateFlags |= PFLAG_PREPRESSED; 10677 if (mPendingCheckForTap == null) { 10678 mPendingCheckForTap = new CheckForTap(); 10679 } 10680 mPendingCheckForTap.x = event.getX(); 10681 mPendingCheckForTap.y = event.getY(); 10682 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 10683 } else { 10684 // Not inside a scrolling container, so show the feedback right away 10685 setPressed(true, x, y); 10686 checkForLongClick(0, x, y); 10687 } 10688 break; 10689 10690 case MotionEvent.ACTION_CANCEL: 10691 setPressed(false); 10692 removeTapCallback(); 10693 removeLongPressCallback(); 10694 mInContextButtonPress = false; 10695 mHasPerformedLongPress = false; 10696 mIgnoreNextUpEvent = false; 10697 break; 10698 10699 case MotionEvent.ACTION_MOVE: 10700 drawableHotspotChanged(x, y); 10701 10702 // Be lenient about moving outside of buttons 10703 if (!pointInView(x, y, mTouchSlop)) { 10704 // Outside button 10705 removeTapCallback(); 10706 if ((mPrivateFlags & PFLAG_PRESSED) != 0) { 10707 // Remove any future long press/tap checks 10708 removeLongPressCallback(); 10709 10710 setPressed(false); 10711 } 10712 } 10713 break; 10714 } 10715 10716 return true; 10717 } 10718 10719 return false; 10720 } 10721 10722 /** 10723 * @hide 10724 */ 10725 public boolean isInScrollingContainer() { 10726 ViewParent p = getParent(); 10727 while (p != null && p instanceof ViewGroup) { 10728 if (((ViewGroup) p).shouldDelayChildPressedState()) { 10729 return true; 10730 } 10731 p = p.getParent(); 10732 } 10733 return false; 10734 } 10735 10736 /** 10737 * Remove the longpress detection timer. 10738 */ 10739 private void removeLongPressCallback() { 10740 if (mPendingCheckForLongPress != null) { 10741 removeCallbacks(mPendingCheckForLongPress); 10742 } 10743 } 10744 10745 /** 10746 * Remove the pending click action 10747 */ 10748 private void removePerformClickCallback() { 10749 if (mPerformClick != null) { 10750 removeCallbacks(mPerformClick); 10751 } 10752 } 10753 10754 /** 10755 * Remove the prepress detection timer. 10756 */ 10757 private void removeUnsetPressCallback() { 10758 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) { 10759 setPressed(false); 10760 removeCallbacks(mUnsetPressedState); 10761 } 10762 } 10763 10764 /** 10765 * Remove the tap detection timer. 10766 */ 10767 private void removeTapCallback() { 10768 if (mPendingCheckForTap != null) { 10769 mPrivateFlags &= ~PFLAG_PREPRESSED; 10770 removeCallbacks(mPendingCheckForTap); 10771 } 10772 } 10773 10774 /** 10775 * Cancels a pending long press. Your subclass can use this if you 10776 * want the context menu to come up if the user presses and holds 10777 * at the same place, but you don't want it to come up if they press 10778 * and then move around enough to cause scrolling. 10779 */ 10780 public void cancelLongPress() { 10781 removeLongPressCallback(); 10782 10783 /* 10784 * The prepressed state handled by the tap callback is a display 10785 * construct, but the tap callback will post a long press callback 10786 * less its own timeout. Remove it here. 10787 */ 10788 removeTapCallback(); 10789 } 10790 10791 /** 10792 * Remove the pending callback for sending a 10793 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 10794 */ 10795 private void removeSendViewScrolledAccessibilityEventCallback() { 10796 if (mSendViewScrolledAccessibilityEvent != null) { 10797 removeCallbacks(mSendViewScrolledAccessibilityEvent); 10798 mSendViewScrolledAccessibilityEvent.mIsPending = false; 10799 } 10800 } 10801 10802 /** 10803 * Sets the TouchDelegate for this View. 10804 */ 10805 public void setTouchDelegate(TouchDelegate delegate) { 10806 mTouchDelegate = delegate; 10807 } 10808 10809 /** 10810 * Gets the TouchDelegate for this View. 10811 */ 10812 public TouchDelegate getTouchDelegate() { 10813 return mTouchDelegate; 10814 } 10815 10816 /** 10817 * Request unbuffered dispatch of the given stream of MotionEvents to this View. 10818 * 10819 * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input 10820 * system not batch {@link MotionEvent}s but instead deliver them as soon as they're 10821 * available. This method should only be called for touch events. 10822 * 10823 * <p class="note">This api is not intended for most applications. Buffered dispatch 10824 * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent 10825 * streams will not improve your input latency. Side effects include: increased latency, 10826 * jittery scrolls and inability to take advantage of system resampling. Talk to your input 10827 * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for 10828 * you.</p> 10829 */ 10830 public final void requestUnbufferedDispatch(MotionEvent event) { 10831 final int action = event.getAction(); 10832 if (mAttachInfo == null 10833 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE 10834 || !event.isTouchEvent()) { 10835 return; 10836 } 10837 mAttachInfo.mUnbufferedDispatchRequested = true; 10838 } 10839 10840 /** 10841 * Set flags controlling behavior of this view. 10842 * 10843 * @param flags Constant indicating the value which should be set 10844 * @param mask Constant indicating the bit range that should be changed 10845 */ 10846 void setFlags(int flags, int mask) { 10847 final boolean accessibilityEnabled = 10848 AccessibilityManager.getInstance(mContext).isEnabled(); 10849 final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility(); 10850 10851 int old = mViewFlags; 10852 mViewFlags = (mViewFlags & ~mask) | (flags & mask); 10853 10854 int changed = mViewFlags ^ old; 10855 if (changed == 0) { 10856 return; 10857 } 10858 int privateFlags = mPrivateFlags; 10859 10860 /* Check if the FOCUSABLE bit has changed */ 10861 if (((changed & FOCUSABLE_MASK) != 0) && 10862 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) { 10863 if (((old & FOCUSABLE_MASK) == FOCUSABLE) 10864 && ((privateFlags & PFLAG_FOCUSED) != 0)) { 10865 /* Give up focus if we are no longer focusable */ 10866 clearFocus(); 10867 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE) 10868 && ((privateFlags & PFLAG_FOCUSED) == 0)) { 10869 /* 10870 * Tell the view system that we are now available to take focus 10871 * if no one else already has it. 10872 */ 10873 if (mParent != null) mParent.focusableViewAvailable(this); 10874 } 10875 } 10876 10877 final int newVisibility = flags & VISIBILITY_MASK; 10878 if (newVisibility == VISIBLE) { 10879 if ((changed & VISIBILITY_MASK) != 0) { 10880 /* 10881 * If this view is becoming visible, invalidate it in case it changed while 10882 * it was not visible. Marking it drawn ensures that the invalidation will 10883 * go through. 10884 */ 10885 mPrivateFlags |= PFLAG_DRAWN; 10886 invalidate(true); 10887 10888 needGlobalAttributesUpdate(true); 10889 10890 // a view becoming visible is worth notifying the parent 10891 // about in case nothing has focus. even if this specific view 10892 // isn't focusable, it may contain something that is, so let 10893 // the root view try to give this focus if nothing else does. 10894 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) { 10895 mParent.focusableViewAvailable(this); 10896 } 10897 } 10898 } 10899 10900 /* Check if the GONE bit has changed */ 10901 if ((changed & GONE) != 0) { 10902 needGlobalAttributesUpdate(false); 10903 requestLayout(); 10904 10905 if (((mViewFlags & VISIBILITY_MASK) == GONE)) { 10906 if (hasFocus()) clearFocus(); 10907 clearAccessibilityFocus(); 10908 destroyDrawingCache(); 10909 if (mParent instanceof View) { 10910 // GONE views noop invalidation, so invalidate the parent 10911 ((View) mParent).invalidate(true); 10912 } 10913 // Mark the view drawn to ensure that it gets invalidated properly the next 10914 // time it is visible and gets invalidated 10915 mPrivateFlags |= PFLAG_DRAWN; 10916 } 10917 if (mAttachInfo != null) { 10918 mAttachInfo.mViewVisibilityChanged = true; 10919 } 10920 } 10921 10922 /* Check if the VISIBLE bit has changed */ 10923 if ((changed & INVISIBLE) != 0) { 10924 needGlobalAttributesUpdate(false); 10925 /* 10926 * If this view is becoming invisible, set the DRAWN flag so that 10927 * the next invalidate() will not be skipped. 10928 */ 10929 mPrivateFlags |= PFLAG_DRAWN; 10930 10931 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) { 10932 // root view becoming invisible shouldn't clear focus and accessibility focus 10933 if (getRootView() != this) { 10934 if (hasFocus()) clearFocus(); 10935 clearAccessibilityFocus(); 10936 } 10937 } 10938 if (mAttachInfo != null) { 10939 mAttachInfo.mViewVisibilityChanged = true; 10940 } 10941 } 10942 10943 if ((changed & VISIBILITY_MASK) != 0) { 10944 // If the view is invisible, cleanup its display list to free up resources 10945 if (newVisibility != VISIBLE && mAttachInfo != null) { 10946 cleanupDraw(); 10947 } 10948 10949 if (mParent instanceof ViewGroup) { 10950 ((ViewGroup) mParent).onChildVisibilityChanged(this, 10951 (changed & VISIBILITY_MASK), newVisibility); 10952 ((View) mParent).invalidate(true); 10953 } else if (mParent != null) { 10954 mParent.invalidateChild(this, null); 10955 } 10956 10957 if (mAttachInfo != null) { 10958 dispatchVisibilityChanged(this, newVisibility); 10959 notifySubtreeAccessibilityStateChangedIfNeeded(); 10960 } 10961 } 10962 10963 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) { 10964 destroyDrawingCache(); 10965 } 10966 10967 if ((changed & DRAWING_CACHE_ENABLED) != 0) { 10968 destroyDrawingCache(); 10969 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 10970 invalidateParentCaches(); 10971 } 10972 10973 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) { 10974 destroyDrawingCache(); 10975 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 10976 } 10977 10978 if ((changed & DRAW_MASK) != 0) { 10979 if ((mViewFlags & WILL_NOT_DRAW) != 0) { 10980 if (mBackground != null 10981 || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) { 10982 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 10983 } else { 10984 mPrivateFlags |= PFLAG_SKIP_DRAW; 10985 } 10986 } else { 10987 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 10988 } 10989 requestLayout(); 10990 invalidate(true); 10991 } 10992 10993 if ((changed & KEEP_SCREEN_ON) != 0) { 10994 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 10995 mParent.recomputeViewAttributes(this); 10996 } 10997 } 10998 10999 if (accessibilityEnabled) { 11000 if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0 11001 || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0 11002 || (changed & CONTEXT_CLICKABLE) != 0) { 11003 if (oldIncludeForAccessibility != includeForAccessibility()) { 11004 notifySubtreeAccessibilityStateChangedIfNeeded(); 11005 } else { 11006 notifyViewAccessibilityStateChangedIfNeeded( 11007 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11008 } 11009 } else if ((changed & ENABLED_MASK) != 0) { 11010 notifyViewAccessibilityStateChangedIfNeeded( 11011 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11012 } 11013 } 11014 } 11015 11016 /** 11017 * Change the view's z order in the tree, so it's on top of other sibling 11018 * views. This ordering change may affect layout, if the parent container 11019 * uses an order-dependent layout scheme (e.g., LinearLayout). Prior 11020 * to {@link android.os.Build.VERSION_CODES#KITKAT} this 11021 * method should be followed by calls to {@link #requestLayout()} and 11022 * {@link View#invalidate()} on the view's parent to force the parent to redraw 11023 * with the new child ordering. 11024 * 11025 * @see ViewGroup#bringChildToFront(View) 11026 */ 11027 public void bringToFront() { 11028 if (mParent != null) { 11029 mParent.bringChildToFront(this); 11030 } 11031 } 11032 11033 /** 11034 * This is called in response to an internal scroll in this view (i.e., the 11035 * view scrolled its own contents). This is typically as a result of 11036 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been 11037 * called. 11038 * 11039 * @param l Current horizontal scroll origin. 11040 * @param t Current vertical scroll origin. 11041 * @param oldl Previous horizontal scroll origin. 11042 * @param oldt Previous vertical scroll origin. 11043 */ 11044 protected void onScrollChanged(int l, int t, int oldl, int oldt) { 11045 notifySubtreeAccessibilityStateChangedIfNeeded(); 11046 11047 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 11048 postSendViewScrolledAccessibilityEventCallback(); 11049 } 11050 11051 mBackgroundSizeChanged = true; 11052 if (mForegroundInfo != null) { 11053 mForegroundInfo.mBoundsChanged = true; 11054 } 11055 11056 final AttachInfo ai = mAttachInfo; 11057 if (ai != null) { 11058 ai.mViewScrollChanged = true; 11059 } 11060 11061 if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) { 11062 mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt); 11063 } 11064 } 11065 11066 /** 11067 * Interface definition for a callback to be invoked when the scroll 11068 * X or Y positions of a view change. 11069 * <p> 11070 * <b>Note:</b> Some views handle scrolling independently from View and may 11071 * have their own separate listeners for scroll-type events. For example, 11072 * {@link android.widget.ListView ListView} allows clients to register an 11073 * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener} 11074 * to listen for changes in list scroll position. 11075 * 11076 * @see #setOnScrollChangeListener(View.OnScrollChangeListener) 11077 */ 11078 public interface OnScrollChangeListener { 11079 /** 11080 * Called when the scroll position of a view changes. 11081 * 11082 * @param v The view whose scroll position has changed. 11083 * @param scrollX Current horizontal scroll origin. 11084 * @param scrollY Current vertical scroll origin. 11085 * @param oldScrollX Previous horizontal scroll origin. 11086 * @param oldScrollY Previous vertical scroll origin. 11087 */ 11088 void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY); 11089 } 11090 11091 /** 11092 * Interface definition for a callback to be invoked when the layout bounds of a view 11093 * changes due to layout processing. 11094 */ 11095 public interface OnLayoutChangeListener { 11096 /** 11097 * Called when the layout bounds of a view changes due to layout processing. 11098 * 11099 * @param v The view whose bounds have changed. 11100 * @param left The new value of the view's left property. 11101 * @param top The new value of the view's top property. 11102 * @param right The new value of the view's right property. 11103 * @param bottom The new value of the view's bottom property. 11104 * @param oldLeft The previous value of the view's left property. 11105 * @param oldTop The previous value of the view's top property. 11106 * @param oldRight The previous value of the view's right property. 11107 * @param oldBottom The previous value of the view's bottom property. 11108 */ 11109 void onLayoutChange(View v, int left, int top, int right, int bottom, 11110 int oldLeft, int oldTop, int oldRight, int oldBottom); 11111 } 11112 11113 /** 11114 * This is called during layout when the size of this view has changed. If 11115 * you were just added to the view hierarchy, you're called with the old 11116 * values of 0. 11117 * 11118 * @param w Current width of this view. 11119 * @param h Current height of this view. 11120 * @param oldw Old width of this view. 11121 * @param oldh Old height of this view. 11122 */ 11123 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 11124 } 11125 11126 /** 11127 * Called by draw to draw the child views. This may be overridden 11128 * by derived classes to gain control just before its children are drawn 11129 * (but after its own view has been drawn). 11130 * @param canvas the canvas on which to draw the view 11131 */ 11132 protected void dispatchDraw(Canvas canvas) { 11133 11134 } 11135 11136 /** 11137 * Gets the parent of this view. Note that the parent is a 11138 * ViewParent and not necessarily a View. 11139 * 11140 * @return Parent of this view. 11141 */ 11142 public final ViewParent getParent() { 11143 return mParent; 11144 } 11145 11146 /** 11147 * Set the horizontal scrolled position of your view. This will cause a call to 11148 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11149 * invalidated. 11150 * @param value the x position to scroll to 11151 */ 11152 public void setScrollX(int value) { 11153 scrollTo(value, mScrollY); 11154 } 11155 11156 /** 11157 * Set the vertical scrolled position of your view. This will cause a call to 11158 * {@link #onScrollChanged(int, int, int, int)} and the view will be 11159 * invalidated. 11160 * @param value the y position to scroll to 11161 */ 11162 public void setScrollY(int value) { 11163 scrollTo(mScrollX, value); 11164 } 11165 11166 /** 11167 * Return the scrolled left position of this view. This is the left edge of 11168 * the displayed part of your view. You do not need to draw any pixels 11169 * farther left, since those are outside of the frame of your view on 11170 * screen. 11171 * 11172 * @return The left edge of the displayed part of your view, in pixels. 11173 */ 11174 public final int getScrollX() { 11175 return mScrollX; 11176 } 11177 11178 /** 11179 * Return the scrolled top position of this view. This is the top edge of 11180 * the displayed part of your view. You do not need to draw any pixels above 11181 * it, since those are outside of the frame of your view on screen. 11182 * 11183 * @return The top edge of the displayed part of your view, in pixels. 11184 */ 11185 public final int getScrollY() { 11186 return mScrollY; 11187 } 11188 11189 /** 11190 * Return the width of the your view. 11191 * 11192 * @return The width of your view, in pixels. 11193 */ 11194 @ViewDebug.ExportedProperty(category = "layout") 11195 public final int getWidth() { 11196 return mRight - mLeft; 11197 } 11198 11199 /** 11200 * Return the height of your view. 11201 * 11202 * @return The height of your view, in pixels. 11203 */ 11204 @ViewDebug.ExportedProperty(category = "layout") 11205 public final int getHeight() { 11206 return mBottom - mTop; 11207 } 11208 11209 /** 11210 * Return the visible drawing bounds of your view. Fills in the output 11211 * rectangle with the values from getScrollX(), getScrollY(), 11212 * getWidth(), and getHeight(). These bounds do not account for any 11213 * transformation properties currently set on the view, such as 11214 * {@link #setScaleX(float)} or {@link #setRotation(float)}. 11215 * 11216 * @param outRect The (scrolled) drawing bounds of the view. 11217 */ 11218 public void getDrawingRect(Rect outRect) { 11219 outRect.left = mScrollX; 11220 outRect.top = mScrollY; 11221 outRect.right = mScrollX + (mRight - mLeft); 11222 outRect.bottom = mScrollY + (mBottom - mTop); 11223 } 11224 11225 /** 11226 * Like {@link #getMeasuredWidthAndState()}, but only returns the 11227 * raw width component (that is the result is masked by 11228 * {@link #MEASURED_SIZE_MASK}). 11229 * 11230 * @return The raw measured width of this view. 11231 */ 11232 public final int getMeasuredWidth() { 11233 return mMeasuredWidth & MEASURED_SIZE_MASK; 11234 } 11235 11236 /** 11237 * Return the full width measurement information for this view as computed 11238 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11239 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11240 * This should be used during measurement and layout calculations only. Use 11241 * {@link #getWidth()} to see how wide a view is after layout. 11242 * 11243 * @return The measured width of this view as a bit mask. 11244 */ 11245 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11246 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11247 name = "MEASURED_STATE_TOO_SMALL"), 11248 }) 11249 public final int getMeasuredWidthAndState() { 11250 return mMeasuredWidth; 11251 } 11252 11253 /** 11254 * Like {@link #getMeasuredHeightAndState()}, but only returns the 11255 * raw width component (that is the result is masked by 11256 * {@link #MEASURED_SIZE_MASK}). 11257 * 11258 * @return The raw measured height of this view. 11259 */ 11260 public final int getMeasuredHeight() { 11261 return mMeasuredHeight & MEASURED_SIZE_MASK; 11262 } 11263 11264 /** 11265 * Return the full height measurement information for this view as computed 11266 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask 11267 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. 11268 * This should be used during measurement and layout calculations only. Use 11269 * {@link #getHeight()} to see how wide a view is after layout. 11270 * 11271 * @return The measured width of this view as a bit mask. 11272 */ 11273 @ViewDebug.ExportedProperty(category = "measurement", flagMapping = { 11274 @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL, 11275 name = "MEASURED_STATE_TOO_SMALL"), 11276 }) 11277 public final int getMeasuredHeightAndState() { 11278 return mMeasuredHeight; 11279 } 11280 11281 /** 11282 * Return only the state bits of {@link #getMeasuredWidthAndState()} 11283 * and {@link #getMeasuredHeightAndState()}, combined into one integer. 11284 * The width component is in the regular bits {@link #MEASURED_STATE_MASK} 11285 * and the height component is at the shifted bits 11286 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. 11287 */ 11288 public final int getMeasuredState() { 11289 return (mMeasuredWidth&MEASURED_STATE_MASK) 11290 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT) 11291 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT)); 11292 } 11293 11294 /** 11295 * The transform matrix of this view, which is calculated based on the current 11296 * rotation, scale, and pivot properties. 11297 * 11298 * @see #getRotation() 11299 * @see #getScaleX() 11300 * @see #getScaleY() 11301 * @see #getPivotX() 11302 * @see #getPivotY() 11303 * @return The current transform matrix for the view 11304 */ 11305 public Matrix getMatrix() { 11306 ensureTransformationInfo(); 11307 final Matrix matrix = mTransformationInfo.mMatrix; 11308 mRenderNode.getMatrix(matrix); 11309 return matrix; 11310 } 11311 11312 /** 11313 * Returns true if the transform matrix is the identity matrix. 11314 * Recomputes the matrix if necessary. 11315 * 11316 * @return True if the transform matrix is the identity matrix, false otherwise. 11317 */ 11318 final boolean hasIdentityMatrix() { 11319 return mRenderNode.hasIdentityMatrix(); 11320 } 11321 11322 void ensureTransformationInfo() { 11323 if (mTransformationInfo == null) { 11324 mTransformationInfo = new TransformationInfo(); 11325 } 11326 } 11327 11328 /** 11329 * Utility method to retrieve the inverse of the current mMatrix property. 11330 * We cache the matrix to avoid recalculating it when transform properties 11331 * have not changed. 11332 * 11333 * @return The inverse of the current matrix of this view. 11334 * @hide 11335 */ 11336 public final Matrix getInverseMatrix() { 11337 ensureTransformationInfo(); 11338 if (mTransformationInfo.mInverseMatrix == null) { 11339 mTransformationInfo.mInverseMatrix = new Matrix(); 11340 } 11341 final Matrix matrix = mTransformationInfo.mInverseMatrix; 11342 mRenderNode.getInverseMatrix(matrix); 11343 return matrix; 11344 } 11345 11346 /** 11347 * Gets the distance along the Z axis from the camera to this view. 11348 * 11349 * @see #setCameraDistance(float) 11350 * 11351 * @return The distance along the Z axis. 11352 */ 11353 public float getCameraDistance() { 11354 final float dpi = mResources.getDisplayMetrics().densityDpi; 11355 return -(mRenderNode.getCameraDistance() * dpi); 11356 } 11357 11358 /** 11359 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which 11360 * views are drawn) from the camera to this view. The camera's distance 11361 * affects 3D transformations, for instance rotations around the X and Y 11362 * axis. If the rotationX or rotationY properties are changed and this view is 11363 * large (more than half the size of the screen), it is recommended to always 11364 * use a camera distance that's greater than the height (X axis rotation) or 11365 * the width (Y axis rotation) of this view.</p> 11366 * 11367 * <p>The distance of the camera from the view plane can have an affect on the 11368 * perspective distortion of the view when it is rotated around the x or y axis. 11369 * For example, a large distance will result in a large viewing angle, and there 11370 * will not be much perspective distortion of the view as it rotates. A short 11371 * distance may cause much more perspective distortion upon rotation, and can 11372 * also result in some drawing artifacts if the rotated view ends up partially 11373 * behind the camera (which is why the recommendation is to use a distance at 11374 * least as far as the size of the view, if the view is to be rotated.)</p> 11375 * 11376 * <p>The distance is expressed in "depth pixels." The default distance depends 11377 * on the screen density. For instance, on a medium density display, the 11378 * default distance is 1280. On a high density display, the default distance 11379 * is 1920.</p> 11380 * 11381 * <p>If you want to specify a distance that leads to visually consistent 11382 * results across various densities, use the following formula:</p> 11383 * <pre> 11384 * float scale = context.getResources().getDisplayMetrics().density; 11385 * view.setCameraDistance(distance * scale); 11386 * </pre> 11387 * 11388 * <p>The density scale factor of a high density display is 1.5, 11389 * and 1920 = 1280 * 1.5.</p> 11390 * 11391 * @param distance The distance in "depth pixels", if negative the opposite 11392 * value is used 11393 * 11394 * @see #setRotationX(float) 11395 * @see #setRotationY(float) 11396 */ 11397 public void setCameraDistance(float distance) { 11398 final float dpi = mResources.getDisplayMetrics().densityDpi; 11399 11400 invalidateViewProperty(true, false); 11401 mRenderNode.setCameraDistance(-Math.abs(distance) / dpi); 11402 invalidateViewProperty(false, false); 11403 11404 invalidateParentIfNeededAndWasQuickRejected(); 11405 } 11406 11407 /** 11408 * The degrees that the view is rotated around the pivot point. 11409 * 11410 * @see #setRotation(float) 11411 * @see #getPivotX() 11412 * @see #getPivotY() 11413 * 11414 * @return The degrees of rotation. 11415 */ 11416 @ViewDebug.ExportedProperty(category = "drawing") 11417 public float getRotation() { 11418 return mRenderNode.getRotation(); 11419 } 11420 11421 /** 11422 * Sets the degrees that the view is rotated around the pivot point. Increasing values 11423 * result in clockwise rotation. 11424 * 11425 * @param rotation The degrees of rotation. 11426 * 11427 * @see #getRotation() 11428 * @see #getPivotX() 11429 * @see #getPivotY() 11430 * @see #setRotationX(float) 11431 * @see #setRotationY(float) 11432 * 11433 * @attr ref android.R.styleable#View_rotation 11434 */ 11435 public void setRotation(float rotation) { 11436 if (rotation != getRotation()) { 11437 // Double-invalidation is necessary to capture view's old and new areas 11438 invalidateViewProperty(true, false); 11439 mRenderNode.setRotation(rotation); 11440 invalidateViewProperty(false, true); 11441 11442 invalidateParentIfNeededAndWasQuickRejected(); 11443 notifySubtreeAccessibilityStateChangedIfNeeded(); 11444 } 11445 } 11446 11447 /** 11448 * The degrees that the view is rotated around the vertical axis through the pivot point. 11449 * 11450 * @see #getPivotX() 11451 * @see #getPivotY() 11452 * @see #setRotationY(float) 11453 * 11454 * @return The degrees of Y rotation. 11455 */ 11456 @ViewDebug.ExportedProperty(category = "drawing") 11457 public float getRotationY() { 11458 return mRenderNode.getRotationY(); 11459 } 11460 11461 /** 11462 * Sets the degrees that the view is rotated around the vertical axis through the pivot point. 11463 * Increasing values result in counter-clockwise rotation from the viewpoint of looking 11464 * down the y axis. 11465 * 11466 * When rotating large views, it is recommended to adjust the camera distance 11467 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 11468 * 11469 * @param rotationY The degrees of Y rotation. 11470 * 11471 * @see #getRotationY() 11472 * @see #getPivotX() 11473 * @see #getPivotY() 11474 * @see #setRotation(float) 11475 * @see #setRotationX(float) 11476 * @see #setCameraDistance(float) 11477 * 11478 * @attr ref android.R.styleable#View_rotationY 11479 */ 11480 public void setRotationY(float rotationY) { 11481 if (rotationY != getRotationY()) { 11482 invalidateViewProperty(true, false); 11483 mRenderNode.setRotationY(rotationY); 11484 invalidateViewProperty(false, true); 11485 11486 invalidateParentIfNeededAndWasQuickRejected(); 11487 notifySubtreeAccessibilityStateChangedIfNeeded(); 11488 } 11489 } 11490 11491 /** 11492 * The degrees that the view is rotated around the horizontal axis through the pivot point. 11493 * 11494 * @see #getPivotX() 11495 * @see #getPivotY() 11496 * @see #setRotationX(float) 11497 * 11498 * @return The degrees of X rotation. 11499 */ 11500 @ViewDebug.ExportedProperty(category = "drawing") 11501 public float getRotationX() { 11502 return mRenderNode.getRotationX(); 11503 } 11504 11505 /** 11506 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point. 11507 * Increasing values result in clockwise rotation from the viewpoint of looking down the 11508 * x axis. 11509 * 11510 * When rotating large views, it is recommended to adjust the camera distance 11511 * accordingly. Refer to {@link #setCameraDistance(float)} for more information. 11512 * 11513 * @param rotationX The degrees of X rotation. 11514 * 11515 * @see #getRotationX() 11516 * @see #getPivotX() 11517 * @see #getPivotY() 11518 * @see #setRotation(float) 11519 * @see #setRotationY(float) 11520 * @see #setCameraDistance(float) 11521 * 11522 * @attr ref android.R.styleable#View_rotationX 11523 */ 11524 public void setRotationX(float rotationX) { 11525 if (rotationX != getRotationX()) { 11526 invalidateViewProperty(true, false); 11527 mRenderNode.setRotationX(rotationX); 11528 invalidateViewProperty(false, true); 11529 11530 invalidateParentIfNeededAndWasQuickRejected(); 11531 notifySubtreeAccessibilityStateChangedIfNeeded(); 11532 } 11533 } 11534 11535 /** 11536 * The amount that the view is scaled in x around the pivot point, as a proportion of 11537 * the view's unscaled width. A value of 1, the default, means that no scaling is applied. 11538 * 11539 * <p>By default, this is 1.0f. 11540 * 11541 * @see #getPivotX() 11542 * @see #getPivotY() 11543 * @return The scaling factor. 11544 */ 11545 @ViewDebug.ExportedProperty(category = "drawing") 11546 public float getScaleX() { 11547 return mRenderNode.getScaleX(); 11548 } 11549 11550 /** 11551 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of 11552 * the view's unscaled width. A value of 1 means that no scaling is applied. 11553 * 11554 * @param scaleX The scaling factor. 11555 * @see #getPivotX() 11556 * @see #getPivotY() 11557 * 11558 * @attr ref android.R.styleable#View_scaleX 11559 */ 11560 public void setScaleX(float scaleX) { 11561 if (scaleX != getScaleX()) { 11562 invalidateViewProperty(true, false); 11563 mRenderNode.setScaleX(scaleX); 11564 invalidateViewProperty(false, true); 11565 11566 invalidateParentIfNeededAndWasQuickRejected(); 11567 notifySubtreeAccessibilityStateChangedIfNeeded(); 11568 } 11569 } 11570 11571 /** 11572 * The amount that the view is scaled in y around the pivot point, as a proportion of 11573 * the view's unscaled height. A value of 1, the default, means that no scaling is applied. 11574 * 11575 * <p>By default, this is 1.0f. 11576 * 11577 * @see #getPivotX() 11578 * @see #getPivotY() 11579 * @return The scaling factor. 11580 */ 11581 @ViewDebug.ExportedProperty(category = "drawing") 11582 public float getScaleY() { 11583 return mRenderNode.getScaleY(); 11584 } 11585 11586 /** 11587 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of 11588 * the view's unscaled width. A value of 1 means that no scaling is applied. 11589 * 11590 * @param scaleY The scaling factor. 11591 * @see #getPivotX() 11592 * @see #getPivotY() 11593 * 11594 * @attr ref android.R.styleable#View_scaleY 11595 */ 11596 public void setScaleY(float scaleY) { 11597 if (scaleY != getScaleY()) { 11598 invalidateViewProperty(true, false); 11599 mRenderNode.setScaleY(scaleY); 11600 invalidateViewProperty(false, true); 11601 11602 invalidateParentIfNeededAndWasQuickRejected(); 11603 notifySubtreeAccessibilityStateChangedIfNeeded(); 11604 } 11605 } 11606 11607 /** 11608 * The x location of the point around which the view is {@link #setRotation(float) rotated} 11609 * and {@link #setScaleX(float) scaled}. 11610 * 11611 * @see #getRotation() 11612 * @see #getScaleX() 11613 * @see #getScaleY() 11614 * @see #getPivotY() 11615 * @return The x location of the pivot point. 11616 * 11617 * @attr ref android.R.styleable#View_transformPivotX 11618 */ 11619 @ViewDebug.ExportedProperty(category = "drawing") 11620 public float getPivotX() { 11621 return mRenderNode.getPivotX(); 11622 } 11623 11624 /** 11625 * Sets the x location of the point around which the view is 11626 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. 11627 * By default, the pivot point is centered on the object. 11628 * Setting this property disables this behavior and causes the view to use only the 11629 * explicitly set pivotX and pivotY values. 11630 * 11631 * @param pivotX The x location of the pivot point. 11632 * @see #getRotation() 11633 * @see #getScaleX() 11634 * @see #getScaleY() 11635 * @see #getPivotY() 11636 * 11637 * @attr ref android.R.styleable#View_transformPivotX 11638 */ 11639 public void setPivotX(float pivotX) { 11640 if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) { 11641 invalidateViewProperty(true, false); 11642 mRenderNode.setPivotX(pivotX); 11643 invalidateViewProperty(false, true); 11644 11645 invalidateParentIfNeededAndWasQuickRejected(); 11646 } 11647 } 11648 11649 /** 11650 * The y location of the point around which the view is {@link #setRotation(float) rotated} 11651 * and {@link #setScaleY(float) scaled}. 11652 * 11653 * @see #getRotation() 11654 * @see #getScaleX() 11655 * @see #getScaleY() 11656 * @see #getPivotY() 11657 * @return The y location of the pivot point. 11658 * 11659 * @attr ref android.R.styleable#View_transformPivotY 11660 */ 11661 @ViewDebug.ExportedProperty(category = "drawing") 11662 public float getPivotY() { 11663 return mRenderNode.getPivotY(); 11664 } 11665 11666 /** 11667 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} 11668 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. 11669 * Setting this property disables this behavior and causes the view to use only the 11670 * explicitly set pivotX and pivotY values. 11671 * 11672 * @param pivotY The y location of the pivot point. 11673 * @see #getRotation() 11674 * @see #getScaleX() 11675 * @see #getScaleY() 11676 * @see #getPivotY() 11677 * 11678 * @attr ref android.R.styleable#View_transformPivotY 11679 */ 11680 public void setPivotY(float pivotY) { 11681 if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) { 11682 invalidateViewProperty(true, false); 11683 mRenderNode.setPivotY(pivotY); 11684 invalidateViewProperty(false, true); 11685 11686 invalidateParentIfNeededAndWasQuickRejected(); 11687 } 11688 } 11689 11690 /** 11691 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is 11692 * completely transparent and 1 means the view is completely opaque. 11693 * 11694 * <p>By default this is 1.0f. 11695 * @return The opacity of the view. 11696 */ 11697 @ViewDebug.ExportedProperty(category = "drawing") 11698 public float getAlpha() { 11699 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1; 11700 } 11701 11702 /** 11703 * Returns whether this View has content which overlaps. 11704 * 11705 * <p>This function, intended to be overridden by specific View types, is an optimization when 11706 * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to 11707 * an offscreen buffer and then composited into place, which can be expensive. If the view has 11708 * no overlapping rendering, the view can draw each primitive with the appropriate alpha value 11709 * directly. An example of overlapping rendering is a TextView with a background image, such as 11710 * a Button. An example of non-overlapping rendering is a TextView with no background, or an 11711 * ImageView with only the foreground image. The default implementation returns true; subclasses 11712 * should override if they have cases which can be optimized.</p> 11713 * 11714 * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas} 11715 * necessitates that a View return true if it uses the methods internally without passing the 11716 * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p> 11717 * 11718 * @return true if the content in this view might overlap, false otherwise. 11719 */ 11720 @ViewDebug.ExportedProperty(category = "drawing") 11721 public boolean hasOverlappingRendering() { 11722 return true; 11723 } 11724 11725 /** 11726 * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is 11727 * completely transparent and 1 means the view is completely opaque. 11728 * 11729 * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1) 11730 * can have significant performance implications, especially for large views. It is best to use 11731 * the alpha property sparingly and transiently, as in the case of fading animations.</p> 11732 * 11733 * <p>For a view with a frequently changing alpha, such as during a fading animation, it is 11734 * strongly recommended for performance reasons to either override 11735 * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a 11736 * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration 11737 * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below, 11738 * the default path for rendering an unlayered View with alpha could add multiple milliseconds 11739 * of rendering cost, even for simple or small views. Starting with 11740 * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically 11741 * applied to the view at the rendering level.</p> 11742 * 11743 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is 11744 * responsible for applying the opacity itself.</p> 11745 * 11746 * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if 11747 * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is 11748 * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an 11749 * alpha value less than 1.0 will supersede the alpha of the layer paint.</p> 11750 * 11751 * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha 11752 * value will clip a View to its bounds, unless the View returns <code>false</code> from 11753 * {@link #hasOverlappingRendering}.</p> 11754 * 11755 * @param alpha The opacity of the view. 11756 * 11757 * @see #hasOverlappingRendering() 11758 * @see #setLayerType(int, android.graphics.Paint) 11759 * 11760 * @attr ref android.R.styleable#View_alpha 11761 */ 11762 public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) { 11763 ensureTransformationInfo(); 11764 if (mTransformationInfo.mAlpha != alpha) { 11765 mTransformationInfo.mAlpha = alpha; 11766 if (onSetAlpha((int) (alpha * 255))) { 11767 mPrivateFlags |= PFLAG_ALPHA_SET; 11768 // subclass is handling alpha - don't optimize rendering cache invalidation 11769 invalidateParentCaches(); 11770 invalidate(true); 11771 } else { 11772 mPrivateFlags &= ~PFLAG_ALPHA_SET; 11773 invalidateViewProperty(true, false); 11774 mRenderNode.setAlpha(getFinalAlpha()); 11775 notifyViewAccessibilityStateChangedIfNeeded( 11776 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 11777 } 11778 } 11779 } 11780 11781 /** 11782 * Faster version of setAlpha() which performs the same steps except there are 11783 * no calls to invalidate(). The caller of this function should perform proper invalidation 11784 * on the parent and this object. The return value indicates whether the subclass handles 11785 * alpha (the return value for onSetAlpha()). 11786 * 11787 * @param alpha The new value for the alpha property 11788 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and 11789 * the new value for the alpha property is different from the old value 11790 */ 11791 boolean setAlphaNoInvalidation(float alpha) { 11792 ensureTransformationInfo(); 11793 if (mTransformationInfo.mAlpha != alpha) { 11794 mTransformationInfo.mAlpha = alpha; 11795 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255)); 11796 if (subclassHandlesAlpha) { 11797 mPrivateFlags |= PFLAG_ALPHA_SET; 11798 return true; 11799 } else { 11800 mPrivateFlags &= ~PFLAG_ALPHA_SET; 11801 mRenderNode.setAlpha(getFinalAlpha()); 11802 } 11803 } 11804 return false; 11805 } 11806 11807 /** 11808 * This property is hidden and intended only for use by the Fade transition, which 11809 * animates it to produce a visual translucency that does not side-effect (or get 11810 * affected by) the real alpha property. This value is composited with the other 11811 * alpha value (and the AlphaAnimation value, when that is present) to produce 11812 * a final visual translucency result, which is what is passed into the DisplayList. 11813 * 11814 * @hide 11815 */ 11816 public void setTransitionAlpha(float alpha) { 11817 ensureTransformationInfo(); 11818 if (mTransformationInfo.mTransitionAlpha != alpha) { 11819 mTransformationInfo.mTransitionAlpha = alpha; 11820 mPrivateFlags &= ~PFLAG_ALPHA_SET; 11821 invalidateViewProperty(true, false); 11822 mRenderNode.setAlpha(getFinalAlpha()); 11823 } 11824 } 11825 11826 /** 11827 * Calculates the visual alpha of this view, which is a combination of the actual 11828 * alpha value and the transitionAlpha value (if set). 11829 */ 11830 private float getFinalAlpha() { 11831 if (mTransformationInfo != null) { 11832 return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha; 11833 } 11834 return 1; 11835 } 11836 11837 /** 11838 * This property is hidden and intended only for use by the Fade transition, which 11839 * animates it to produce a visual translucency that does not side-effect (or get 11840 * affected by) the real alpha property. This value is composited with the other 11841 * alpha value (and the AlphaAnimation value, when that is present) to produce 11842 * a final visual translucency result, which is what is passed into the DisplayList. 11843 * 11844 * @hide 11845 */ 11846 @ViewDebug.ExportedProperty(category = "drawing") 11847 public float getTransitionAlpha() { 11848 return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1; 11849 } 11850 11851 /** 11852 * Top position of this view relative to its parent. 11853 * 11854 * @return The top of this view, in pixels. 11855 */ 11856 @ViewDebug.CapturedViewProperty 11857 public final int getTop() { 11858 return mTop; 11859 } 11860 11861 /** 11862 * Sets the top position of this view relative to its parent. This method is meant to be called 11863 * by the layout system and should not generally be called otherwise, because the property 11864 * may be changed at any time by the layout. 11865 * 11866 * @param top The top of this view, in pixels. 11867 */ 11868 public final void setTop(int top) { 11869 if (top != mTop) { 11870 final boolean matrixIsIdentity = hasIdentityMatrix(); 11871 if (matrixIsIdentity) { 11872 if (mAttachInfo != null) { 11873 int minTop; 11874 int yLoc; 11875 if (top < mTop) { 11876 minTop = top; 11877 yLoc = top - mTop; 11878 } else { 11879 minTop = mTop; 11880 yLoc = 0; 11881 } 11882 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop); 11883 } 11884 } else { 11885 // Double-invalidation is necessary to capture view's old and new areas 11886 invalidate(true); 11887 } 11888 11889 int width = mRight - mLeft; 11890 int oldHeight = mBottom - mTop; 11891 11892 mTop = top; 11893 mRenderNode.setTop(mTop); 11894 11895 sizeChange(width, mBottom - mTop, width, oldHeight); 11896 11897 if (!matrixIsIdentity) { 11898 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 11899 invalidate(true); 11900 } 11901 mBackgroundSizeChanged = true; 11902 if (mForegroundInfo != null) { 11903 mForegroundInfo.mBoundsChanged = true; 11904 } 11905 invalidateParentIfNeeded(); 11906 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 11907 // View was rejected last time it was drawn by its parent; this may have changed 11908 invalidateParentIfNeeded(); 11909 } 11910 } 11911 } 11912 11913 /** 11914 * Bottom position of this view relative to its parent. 11915 * 11916 * @return The bottom of this view, in pixels. 11917 */ 11918 @ViewDebug.CapturedViewProperty 11919 public final int getBottom() { 11920 return mBottom; 11921 } 11922 11923 /** 11924 * True if this view has changed since the last time being drawn. 11925 * 11926 * @return The dirty state of this view. 11927 */ 11928 public boolean isDirty() { 11929 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0; 11930 } 11931 11932 /** 11933 * Sets the bottom position of this view relative to its parent. This method is meant to be 11934 * called by the layout system and should not generally be called otherwise, because the 11935 * property may be changed at any time by the layout. 11936 * 11937 * @param bottom The bottom of this view, in pixels. 11938 */ 11939 public final void setBottom(int bottom) { 11940 if (bottom != mBottom) { 11941 final boolean matrixIsIdentity = hasIdentityMatrix(); 11942 if (matrixIsIdentity) { 11943 if (mAttachInfo != null) { 11944 int maxBottom; 11945 if (bottom < mBottom) { 11946 maxBottom = mBottom; 11947 } else { 11948 maxBottom = bottom; 11949 } 11950 invalidate(0, 0, mRight - mLeft, maxBottom - mTop); 11951 } 11952 } else { 11953 // Double-invalidation is necessary to capture view's old and new areas 11954 invalidate(true); 11955 } 11956 11957 int width = mRight - mLeft; 11958 int oldHeight = mBottom - mTop; 11959 11960 mBottom = bottom; 11961 mRenderNode.setBottom(mBottom); 11962 11963 sizeChange(width, mBottom - mTop, width, oldHeight); 11964 11965 if (!matrixIsIdentity) { 11966 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 11967 invalidate(true); 11968 } 11969 mBackgroundSizeChanged = true; 11970 if (mForegroundInfo != null) { 11971 mForegroundInfo.mBoundsChanged = true; 11972 } 11973 invalidateParentIfNeeded(); 11974 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 11975 // View was rejected last time it was drawn by its parent; this may have changed 11976 invalidateParentIfNeeded(); 11977 } 11978 } 11979 } 11980 11981 /** 11982 * Left position of this view relative to its parent. 11983 * 11984 * @return The left edge of this view, in pixels. 11985 */ 11986 @ViewDebug.CapturedViewProperty 11987 public final int getLeft() { 11988 return mLeft; 11989 } 11990 11991 /** 11992 * Sets the left position of this view relative to its parent. This method is meant to be called 11993 * by the layout system and should not generally be called otherwise, because the property 11994 * may be changed at any time by the layout. 11995 * 11996 * @param left The left of this view, in pixels. 11997 */ 11998 public final void setLeft(int left) { 11999 if (left != mLeft) { 12000 final boolean matrixIsIdentity = hasIdentityMatrix(); 12001 if (matrixIsIdentity) { 12002 if (mAttachInfo != null) { 12003 int minLeft; 12004 int xLoc; 12005 if (left < mLeft) { 12006 minLeft = left; 12007 xLoc = left - mLeft; 12008 } else { 12009 minLeft = mLeft; 12010 xLoc = 0; 12011 } 12012 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop); 12013 } 12014 } else { 12015 // Double-invalidation is necessary to capture view's old and new areas 12016 invalidate(true); 12017 } 12018 12019 int oldWidth = mRight - mLeft; 12020 int height = mBottom - mTop; 12021 12022 mLeft = left; 12023 mRenderNode.setLeft(left); 12024 12025 sizeChange(mRight - mLeft, height, oldWidth, height); 12026 12027 if (!matrixIsIdentity) { 12028 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12029 invalidate(true); 12030 } 12031 mBackgroundSizeChanged = true; 12032 if (mForegroundInfo != null) { 12033 mForegroundInfo.mBoundsChanged = true; 12034 } 12035 invalidateParentIfNeeded(); 12036 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12037 // View was rejected last time it was drawn by its parent; this may have changed 12038 invalidateParentIfNeeded(); 12039 } 12040 } 12041 } 12042 12043 /** 12044 * Right position of this view relative to its parent. 12045 * 12046 * @return The right edge of this view, in pixels. 12047 */ 12048 @ViewDebug.CapturedViewProperty 12049 public final int getRight() { 12050 return mRight; 12051 } 12052 12053 /** 12054 * Sets the right position of this view relative to its parent. This method is meant to be called 12055 * by the layout system and should not generally be called otherwise, because the property 12056 * may be changed at any time by the layout. 12057 * 12058 * @param right The right of this view, in pixels. 12059 */ 12060 public final void setRight(int right) { 12061 if (right != mRight) { 12062 final boolean matrixIsIdentity = hasIdentityMatrix(); 12063 if (matrixIsIdentity) { 12064 if (mAttachInfo != null) { 12065 int maxRight; 12066 if (right < mRight) { 12067 maxRight = mRight; 12068 } else { 12069 maxRight = right; 12070 } 12071 invalidate(0, 0, maxRight - mLeft, mBottom - mTop); 12072 } 12073 } else { 12074 // Double-invalidation is necessary to capture view's old and new areas 12075 invalidate(true); 12076 } 12077 12078 int oldWidth = mRight - mLeft; 12079 int height = mBottom - mTop; 12080 12081 mRight = right; 12082 mRenderNode.setRight(mRight); 12083 12084 sizeChange(mRight - mLeft, height, oldWidth, height); 12085 12086 if (!matrixIsIdentity) { 12087 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 12088 invalidate(true); 12089 } 12090 mBackgroundSizeChanged = true; 12091 if (mForegroundInfo != null) { 12092 mForegroundInfo.mBoundsChanged = true; 12093 } 12094 invalidateParentIfNeeded(); 12095 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) { 12096 // View was rejected last time it was drawn by its parent; this may have changed 12097 invalidateParentIfNeeded(); 12098 } 12099 } 12100 } 12101 12102 /** 12103 * The visual x position of this view, in pixels. This is equivalent to the 12104 * {@link #setTranslationX(float) translationX} property plus the current 12105 * {@link #getLeft() left} property. 12106 * 12107 * @return The visual x position of this view, in pixels. 12108 */ 12109 @ViewDebug.ExportedProperty(category = "drawing") 12110 public float getX() { 12111 return mLeft + getTranslationX(); 12112 } 12113 12114 /** 12115 * Sets the visual x position of this view, in pixels. This is equivalent to setting the 12116 * {@link #setTranslationX(float) translationX} property to be the difference between 12117 * the x value passed in and the current {@link #getLeft() left} property. 12118 * 12119 * @param x The visual x position of this view, in pixels. 12120 */ 12121 public void setX(float x) { 12122 setTranslationX(x - mLeft); 12123 } 12124 12125 /** 12126 * The visual y position of this view, in pixels. This is equivalent to the 12127 * {@link #setTranslationY(float) translationY} property plus the current 12128 * {@link #getTop() top} property. 12129 * 12130 * @return The visual y position of this view, in pixels. 12131 */ 12132 @ViewDebug.ExportedProperty(category = "drawing") 12133 public float getY() { 12134 return mTop + getTranslationY(); 12135 } 12136 12137 /** 12138 * Sets the visual y position of this view, in pixels. This is equivalent to setting the 12139 * {@link #setTranslationY(float) translationY} property to be the difference between 12140 * the y value passed in and the current {@link #getTop() top} property. 12141 * 12142 * @param y The visual y position of this view, in pixels. 12143 */ 12144 public void setY(float y) { 12145 setTranslationY(y - mTop); 12146 } 12147 12148 /** 12149 * The visual z position of this view, in pixels. This is equivalent to the 12150 * {@link #setTranslationZ(float) translationZ} property plus the current 12151 * {@link #getElevation() elevation} property. 12152 * 12153 * @return The visual z position of this view, in pixels. 12154 */ 12155 @ViewDebug.ExportedProperty(category = "drawing") 12156 public float getZ() { 12157 return getElevation() + getTranslationZ(); 12158 } 12159 12160 /** 12161 * Sets the visual z position of this view, in pixels. This is equivalent to setting the 12162 * {@link #setTranslationZ(float) translationZ} property to be the difference between 12163 * the x value passed in and the current {@link #getElevation() elevation} property. 12164 * 12165 * @param z The visual z position of this view, in pixels. 12166 */ 12167 public void setZ(float z) { 12168 setTranslationZ(z - getElevation()); 12169 } 12170 12171 /** 12172 * The base elevation of this view relative to its parent, in pixels. 12173 * 12174 * @return The base depth position of the view, in pixels. 12175 */ 12176 @ViewDebug.ExportedProperty(category = "drawing") 12177 public float getElevation() { 12178 return mRenderNode.getElevation(); 12179 } 12180 12181 /** 12182 * Sets the base elevation of this view, in pixels. 12183 * 12184 * @attr ref android.R.styleable#View_elevation 12185 */ 12186 public void setElevation(float elevation) { 12187 if (elevation != getElevation()) { 12188 invalidateViewProperty(true, false); 12189 mRenderNode.setElevation(elevation); 12190 invalidateViewProperty(false, true); 12191 12192 invalidateParentIfNeededAndWasQuickRejected(); 12193 } 12194 } 12195 12196 /** 12197 * The horizontal location of this view relative to its {@link #getLeft() left} position. 12198 * This position is post-layout, in addition to wherever the object's 12199 * layout placed it. 12200 * 12201 * @return The horizontal position of this view relative to its left position, in pixels. 12202 */ 12203 @ViewDebug.ExportedProperty(category = "drawing") 12204 public float getTranslationX() { 12205 return mRenderNode.getTranslationX(); 12206 } 12207 12208 /** 12209 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position. 12210 * This effectively positions the object post-layout, in addition to wherever the object's 12211 * layout placed it. 12212 * 12213 * @param translationX The horizontal position of this view relative to its left position, 12214 * in pixels. 12215 * 12216 * @attr ref android.R.styleable#View_translationX 12217 */ 12218 public void setTranslationX(float translationX) { 12219 if (translationX != getTranslationX()) { 12220 invalidateViewProperty(true, false); 12221 mRenderNode.setTranslationX(translationX); 12222 invalidateViewProperty(false, true); 12223 12224 invalidateParentIfNeededAndWasQuickRejected(); 12225 notifySubtreeAccessibilityStateChangedIfNeeded(); 12226 } 12227 } 12228 12229 /** 12230 * The vertical location of this view relative to its {@link #getTop() top} position. 12231 * This position is post-layout, in addition to wherever the object's 12232 * layout placed it. 12233 * 12234 * @return The vertical position of this view relative to its top position, 12235 * in pixels. 12236 */ 12237 @ViewDebug.ExportedProperty(category = "drawing") 12238 public float getTranslationY() { 12239 return mRenderNode.getTranslationY(); 12240 } 12241 12242 /** 12243 * Sets the vertical location of this view relative to its {@link #getTop() top} position. 12244 * This effectively positions the object post-layout, in addition to wherever the object's 12245 * layout placed it. 12246 * 12247 * @param translationY The vertical position of this view relative to its top position, 12248 * in pixels. 12249 * 12250 * @attr ref android.R.styleable#View_translationY 12251 */ 12252 public void setTranslationY(float translationY) { 12253 if (translationY != getTranslationY()) { 12254 invalidateViewProperty(true, false); 12255 mRenderNode.setTranslationY(translationY); 12256 invalidateViewProperty(false, true); 12257 12258 invalidateParentIfNeededAndWasQuickRejected(); 12259 notifySubtreeAccessibilityStateChangedIfNeeded(); 12260 } 12261 } 12262 12263 /** 12264 * The depth location of this view relative to its {@link #getElevation() elevation}. 12265 * 12266 * @return The depth of this view relative to its elevation. 12267 */ 12268 @ViewDebug.ExportedProperty(category = "drawing") 12269 public float getTranslationZ() { 12270 return mRenderNode.getTranslationZ(); 12271 } 12272 12273 /** 12274 * Sets the depth location of this view relative to its {@link #getElevation() elevation}. 12275 * 12276 * @attr ref android.R.styleable#View_translationZ 12277 */ 12278 public void setTranslationZ(float translationZ) { 12279 if (translationZ != getTranslationZ()) { 12280 invalidateViewProperty(true, false); 12281 mRenderNode.setTranslationZ(translationZ); 12282 invalidateViewProperty(false, true); 12283 12284 invalidateParentIfNeededAndWasQuickRejected(); 12285 } 12286 } 12287 12288 /** @hide */ 12289 public void setAnimationMatrix(Matrix matrix) { 12290 invalidateViewProperty(true, false); 12291 mRenderNode.setAnimationMatrix(matrix); 12292 invalidateViewProperty(false, true); 12293 12294 invalidateParentIfNeededAndWasQuickRejected(); 12295 } 12296 12297 /** 12298 * Returns the current StateListAnimator if exists. 12299 * 12300 * @return StateListAnimator or null if it does not exists 12301 * @see #setStateListAnimator(android.animation.StateListAnimator) 12302 */ 12303 public StateListAnimator getStateListAnimator() { 12304 return mStateListAnimator; 12305 } 12306 12307 /** 12308 * Attaches the provided StateListAnimator to this View. 12309 * <p> 12310 * Any previously attached StateListAnimator will be detached. 12311 * 12312 * @param stateListAnimator The StateListAnimator to update the view 12313 * @see {@link android.animation.StateListAnimator} 12314 */ 12315 public void setStateListAnimator(StateListAnimator stateListAnimator) { 12316 if (mStateListAnimator == stateListAnimator) { 12317 return; 12318 } 12319 if (mStateListAnimator != null) { 12320 mStateListAnimator.setTarget(null); 12321 } 12322 mStateListAnimator = stateListAnimator; 12323 if (stateListAnimator != null) { 12324 stateListAnimator.setTarget(this); 12325 if (isAttachedToWindow()) { 12326 stateListAnimator.setState(getDrawableState()); 12327 } 12328 } 12329 } 12330 12331 /** 12332 * Returns whether the Outline should be used to clip the contents of the View. 12333 * <p> 12334 * Note that this flag will only be respected if the View's Outline returns true from 12335 * {@link Outline#canClip()}. 12336 * 12337 * @see #setOutlineProvider(ViewOutlineProvider) 12338 * @see #setClipToOutline(boolean) 12339 */ 12340 public final boolean getClipToOutline() { 12341 return mRenderNode.getClipToOutline(); 12342 } 12343 12344 /** 12345 * Sets whether the View's Outline should be used to clip the contents of the View. 12346 * <p> 12347 * Only a single non-rectangular clip can be applied on a View at any time. 12348 * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float) 12349 * circular reveal} animation take priority over Outline clipping, and 12350 * child Outline clipping takes priority over Outline clipping done by a 12351 * parent. 12352 * <p> 12353 * Note that this flag will only be respected if the View's Outline returns true from 12354 * {@link Outline#canClip()}. 12355 * 12356 * @see #setOutlineProvider(ViewOutlineProvider) 12357 * @see #getClipToOutline() 12358 */ 12359 public void setClipToOutline(boolean clipToOutline) { 12360 damageInParent(); 12361 if (getClipToOutline() != clipToOutline) { 12362 mRenderNode.setClipToOutline(clipToOutline); 12363 } 12364 } 12365 12366 // correspond to the enum values of View_outlineProvider 12367 private static final int PROVIDER_BACKGROUND = 0; 12368 private static final int PROVIDER_NONE = 1; 12369 private static final int PROVIDER_BOUNDS = 2; 12370 private static final int PROVIDER_PADDED_BOUNDS = 3; 12371 private void setOutlineProviderFromAttribute(int providerInt) { 12372 switch (providerInt) { 12373 case PROVIDER_BACKGROUND: 12374 setOutlineProvider(ViewOutlineProvider.BACKGROUND); 12375 break; 12376 case PROVIDER_NONE: 12377 setOutlineProvider(null); 12378 break; 12379 case PROVIDER_BOUNDS: 12380 setOutlineProvider(ViewOutlineProvider.BOUNDS); 12381 break; 12382 case PROVIDER_PADDED_BOUNDS: 12383 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS); 12384 break; 12385 } 12386 } 12387 12388 /** 12389 * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines 12390 * the shape of the shadow it casts, and enables outline clipping. 12391 * <p> 12392 * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline 12393 * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the 12394 * outline provider with this method allows this behavior to be overridden. 12395 * <p> 12396 * If the ViewOutlineProvider is null, if querying it for an outline returns false, 12397 * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast. 12398 * <p> 12399 * Only outlines that return true from {@link Outline#canClip()} may be used for clipping. 12400 * 12401 * @see #setClipToOutline(boolean) 12402 * @see #getClipToOutline() 12403 * @see #getOutlineProvider() 12404 */ 12405 public void setOutlineProvider(ViewOutlineProvider provider) { 12406 mOutlineProvider = provider; 12407 invalidateOutline(); 12408 } 12409 12410 /** 12411 * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline 12412 * that defines the shape of the shadow it casts, and enables outline clipping. 12413 * 12414 * @see #setOutlineProvider(ViewOutlineProvider) 12415 */ 12416 public ViewOutlineProvider getOutlineProvider() { 12417 return mOutlineProvider; 12418 } 12419 12420 /** 12421 * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider} 12422 * 12423 * @see #setOutlineProvider(ViewOutlineProvider) 12424 */ 12425 public void invalidateOutline() { 12426 rebuildOutline(); 12427 12428 notifySubtreeAccessibilityStateChangedIfNeeded(); 12429 invalidateViewProperty(false, false); 12430 } 12431 12432 /** 12433 * Internal version of {@link #invalidateOutline()} which invalidates the 12434 * outline without invalidating the view itself. This is intended to be called from 12435 * within methods in the View class itself which are the result of the view being 12436 * invalidated already. For example, when we are drawing the background of a View, 12437 * we invalidate the outline in case it changed in the meantime, but we do not 12438 * need to invalidate the view because we're already drawing the background as part 12439 * of drawing the view in response to an earlier invalidation of the view. 12440 */ 12441 private void rebuildOutline() { 12442 // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow() 12443 if (mAttachInfo == null) return; 12444 12445 if (mOutlineProvider == null) { 12446 // no provider, remove outline 12447 mRenderNode.setOutline(null); 12448 } else { 12449 final Outline outline = mAttachInfo.mTmpOutline; 12450 outline.setEmpty(); 12451 outline.setAlpha(1.0f); 12452 12453 mOutlineProvider.getOutline(this, outline); 12454 mRenderNode.setOutline(outline); 12455 } 12456 } 12457 12458 /** 12459 * HierarchyViewer only 12460 * 12461 * @hide 12462 */ 12463 @ViewDebug.ExportedProperty(category = "drawing") 12464 public boolean hasShadow() { 12465 return mRenderNode.hasShadow(); 12466 } 12467 12468 12469 /** @hide */ 12470 public void setRevealClip(boolean shouldClip, float x, float y, float radius) { 12471 mRenderNode.setRevealClip(shouldClip, x, y, radius); 12472 invalidateViewProperty(false, false); 12473 } 12474 12475 /** 12476 * Hit rectangle in parent's coordinates 12477 * 12478 * @param outRect The hit rectangle of the view. 12479 */ 12480 public void getHitRect(Rect outRect) { 12481 if (hasIdentityMatrix() || mAttachInfo == null) { 12482 outRect.set(mLeft, mTop, mRight, mBottom); 12483 } else { 12484 final RectF tmpRect = mAttachInfo.mTmpTransformRect; 12485 tmpRect.set(0, 0, getWidth(), getHeight()); 12486 getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect) 12487 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop, 12488 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop); 12489 } 12490 } 12491 12492 /** 12493 * Determines whether the given point, in local coordinates is inside the view. 12494 */ 12495 /*package*/ final boolean pointInView(float localX, float localY) { 12496 return localX >= 0 && localX < (mRight - mLeft) 12497 && localY >= 0 && localY < (mBottom - mTop); 12498 } 12499 12500 /** 12501 * Utility method to determine whether the given point, in local coordinates, 12502 * is inside the view, where the area of the view is expanded by the slop factor. 12503 * This method is called while processing touch-move events to determine if the event 12504 * is still within the view. 12505 * 12506 * @hide 12507 */ 12508 public boolean pointInView(float localX, float localY, float slop) { 12509 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) && 12510 localY < ((mBottom - mTop) + slop); 12511 } 12512 12513 /** 12514 * When a view has focus and the user navigates away from it, the next view is searched for 12515 * starting from the rectangle filled in by this method. 12516 * 12517 * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)}) 12518 * of the view. However, if your view maintains some idea of internal selection, 12519 * such as a cursor, or a selected row or column, you should override this method and 12520 * fill in a more specific rectangle. 12521 * 12522 * @param r The rectangle to fill in, in this view's coordinates. 12523 */ 12524 public void getFocusedRect(Rect r) { 12525 getDrawingRect(r); 12526 } 12527 12528 /** 12529 * If some part of this view is not clipped by any of its parents, then 12530 * return that area in r in global (root) coordinates. To convert r to local 12531 * coordinates (without taking possible View rotations into account), offset 12532 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)). 12533 * If the view is completely clipped or translated out, return false. 12534 * 12535 * @param r If true is returned, r holds the global coordinates of the 12536 * visible portion of this view. 12537 * @param globalOffset If true is returned, globalOffset holds the dx,dy 12538 * between this view and its root. globalOffet may be null. 12539 * @return true if r is non-empty (i.e. part of the view is visible at the 12540 * root level. 12541 */ 12542 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) { 12543 int width = mRight - mLeft; 12544 int height = mBottom - mTop; 12545 if (width > 0 && height > 0) { 12546 r.set(0, 0, width, height); 12547 if (globalOffset != null) { 12548 globalOffset.set(-mScrollX, -mScrollY); 12549 } 12550 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset); 12551 } 12552 return false; 12553 } 12554 12555 public final boolean getGlobalVisibleRect(Rect r) { 12556 return getGlobalVisibleRect(r, null); 12557 } 12558 12559 public final boolean getLocalVisibleRect(Rect r) { 12560 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point(); 12561 if (getGlobalVisibleRect(r, offset)) { 12562 r.offset(-offset.x, -offset.y); // make r local 12563 return true; 12564 } 12565 return false; 12566 } 12567 12568 /** 12569 * Offset this view's vertical location by the specified number of pixels. 12570 * 12571 * @param offset the number of pixels to offset the view by 12572 */ 12573 public void offsetTopAndBottom(int offset) { 12574 if (offset != 0) { 12575 final boolean matrixIsIdentity = hasIdentityMatrix(); 12576 if (matrixIsIdentity) { 12577 if (isHardwareAccelerated()) { 12578 invalidateViewProperty(false, false); 12579 } else { 12580 final ViewParent p = mParent; 12581 if (p != null && mAttachInfo != null) { 12582 final Rect r = mAttachInfo.mTmpInvalRect; 12583 int minTop; 12584 int maxBottom; 12585 int yLoc; 12586 if (offset < 0) { 12587 minTop = mTop + offset; 12588 maxBottom = mBottom; 12589 yLoc = offset; 12590 } else { 12591 minTop = mTop; 12592 maxBottom = mBottom + offset; 12593 yLoc = 0; 12594 } 12595 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop); 12596 p.invalidateChild(this, r); 12597 } 12598 } 12599 } else { 12600 invalidateViewProperty(false, false); 12601 } 12602 12603 mTop += offset; 12604 mBottom += offset; 12605 mRenderNode.offsetTopAndBottom(offset); 12606 if (isHardwareAccelerated()) { 12607 invalidateViewProperty(false, false); 12608 invalidateParentIfNeededAndWasQuickRejected(); 12609 } else { 12610 if (!matrixIsIdentity) { 12611 invalidateViewProperty(false, true); 12612 } 12613 invalidateParentIfNeeded(); 12614 } 12615 notifySubtreeAccessibilityStateChangedIfNeeded(); 12616 } 12617 } 12618 12619 /** 12620 * Offset this view's horizontal location by the specified amount of pixels. 12621 * 12622 * @param offset the number of pixels to offset the view by 12623 */ 12624 public void offsetLeftAndRight(int offset) { 12625 if (offset != 0) { 12626 final boolean matrixIsIdentity = hasIdentityMatrix(); 12627 if (matrixIsIdentity) { 12628 if (isHardwareAccelerated()) { 12629 invalidateViewProperty(false, false); 12630 } else { 12631 final ViewParent p = mParent; 12632 if (p != null && mAttachInfo != null) { 12633 final Rect r = mAttachInfo.mTmpInvalRect; 12634 int minLeft; 12635 int maxRight; 12636 if (offset < 0) { 12637 minLeft = mLeft + offset; 12638 maxRight = mRight; 12639 } else { 12640 minLeft = mLeft; 12641 maxRight = mRight + offset; 12642 } 12643 r.set(0, 0, maxRight - minLeft, mBottom - mTop); 12644 p.invalidateChild(this, r); 12645 } 12646 } 12647 } else { 12648 invalidateViewProperty(false, false); 12649 } 12650 12651 mLeft += offset; 12652 mRight += offset; 12653 mRenderNode.offsetLeftAndRight(offset); 12654 if (isHardwareAccelerated()) { 12655 invalidateViewProperty(false, false); 12656 invalidateParentIfNeededAndWasQuickRejected(); 12657 } else { 12658 if (!matrixIsIdentity) { 12659 invalidateViewProperty(false, true); 12660 } 12661 invalidateParentIfNeeded(); 12662 } 12663 notifySubtreeAccessibilityStateChangedIfNeeded(); 12664 } 12665 } 12666 12667 /** 12668 * Get the LayoutParams associated with this view. All views should have 12669 * layout parameters. These supply parameters to the <i>parent</i> of this 12670 * view specifying how it should be arranged. There are many subclasses of 12671 * ViewGroup.LayoutParams, and these correspond to the different subclasses 12672 * of ViewGroup that are responsible for arranging their children. 12673 * 12674 * <p>This method may return null if this View is not attached to a parent 12675 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)} 12676 * was not invoked successfully. When a View is attached to a parent 12677 * ViewGroup, this method must not return null.</p> 12678 * 12679 * <p>Callers that modify the returned LayoutParams object should call 12680 * {@link #setLayoutParams(LayoutParams)} to explicitly inform the view that 12681 * LayoutParams have changed.</p> 12682 * 12683 * @return The LayoutParams associated with this view, or null if no 12684 * parameters have been set yet 12685 */ 12686 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_") 12687 public ViewGroup.LayoutParams getLayoutParams() { 12688 return mLayoutParams; 12689 } 12690 12691 /** 12692 * Set the layout parameters associated with this view. These supply 12693 * parameters to the <i>parent</i> of this view specifying how it should be 12694 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these 12695 * correspond to the different subclasses of ViewGroup that are responsible 12696 * for arranging their children. 12697 * 12698 * <p>If the View's existing LayoutParams object as obtained by {@link #getLayoutParams()} is 12699 * modified, you should call this method to inform the view that it has changed.</p> 12700 * 12701 * @param params The layout parameters for this view, cannot be null 12702 */ 12703 public void setLayoutParams(ViewGroup.LayoutParams params) { 12704 if (params == null) { 12705 throw new NullPointerException("Layout parameters cannot be null"); 12706 } 12707 mLayoutParams = params; 12708 mPrivateFlags3 |= PFLAG3_LAYOUT_PARAMS_CHANGED; 12709 resolveLayoutParams(); 12710 if (mParent instanceof ViewGroup) { 12711 ((ViewGroup) mParent).onSetLayoutParams(this, params); 12712 } 12713 requestLayout(); 12714 } 12715 12716 /** 12717 * Resolve the layout parameters depending on the resolved layout direction 12718 * 12719 * @hide 12720 */ 12721 public void resolveLayoutParams() { 12722 if (mLayoutParams != null) { 12723 mLayoutParams.resolveLayoutDirection(getLayoutDirection()); 12724 } 12725 } 12726 12727 /** 12728 * Set the scrolled position of your view. This will cause a call to 12729 * {@link #onScrollChanged(int, int, int, int)} and the view will be 12730 * invalidated. 12731 * @param x the x position to scroll to 12732 * @param y the y position to scroll to 12733 */ 12734 public void scrollTo(int x, int y) { 12735 if (mScrollX != x || mScrollY != y) { 12736 int oldX = mScrollX; 12737 int oldY = mScrollY; 12738 mScrollX = x; 12739 mScrollY = y; 12740 invalidateParentCaches(); 12741 onScrollChanged(mScrollX, mScrollY, oldX, oldY); 12742 if (!awakenScrollBars()) { 12743 postInvalidateOnAnimation(); 12744 } 12745 } 12746 } 12747 12748 /** 12749 * Move the scrolled position of your view. This will cause a call to 12750 * {@link #onScrollChanged(int, int, int, int)} and the view will be 12751 * invalidated. 12752 * @param x the amount of pixels to scroll by horizontally 12753 * @param y the amount of pixels to scroll by vertically 12754 */ 12755 public void scrollBy(int x, int y) { 12756 scrollTo(mScrollX + x, mScrollY + y); 12757 } 12758 12759 /** 12760 * <p>Trigger the scrollbars to draw. When invoked this method starts an 12761 * animation to fade the scrollbars out after a default delay. If a subclass 12762 * provides animated scrolling, the start delay should equal the duration 12763 * of the scrolling animation.</p> 12764 * 12765 * <p>The animation starts only if at least one of the scrollbars is 12766 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and 12767 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 12768 * this method returns true, and false otherwise. If the animation is 12769 * started, this method calls {@link #invalidate()}; in that case the 12770 * caller should not call {@link #invalidate()}.</p> 12771 * 12772 * <p>This method should be invoked every time a subclass directly updates 12773 * the scroll parameters.</p> 12774 * 12775 * <p>This method is automatically invoked by {@link #scrollBy(int, int)} 12776 * and {@link #scrollTo(int, int)}.</p> 12777 * 12778 * @return true if the animation is played, false otherwise 12779 * 12780 * @see #awakenScrollBars(int) 12781 * @see #scrollBy(int, int) 12782 * @see #scrollTo(int, int) 12783 * @see #isHorizontalScrollBarEnabled() 12784 * @see #isVerticalScrollBarEnabled() 12785 * @see #setHorizontalScrollBarEnabled(boolean) 12786 * @see #setVerticalScrollBarEnabled(boolean) 12787 */ 12788 protected boolean awakenScrollBars() { 12789 return mScrollCache != null && 12790 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true); 12791 } 12792 12793 /** 12794 * Trigger the scrollbars to draw. 12795 * This method differs from awakenScrollBars() only in its default duration. 12796 * initialAwakenScrollBars() will show the scroll bars for longer than 12797 * usual to give the user more of a chance to notice them. 12798 * 12799 * @return true if the animation is played, false otherwise. 12800 */ 12801 private boolean initialAwakenScrollBars() { 12802 return mScrollCache != null && 12803 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true); 12804 } 12805 12806 /** 12807 * <p> 12808 * Trigger the scrollbars to draw. When invoked this method starts an 12809 * animation to fade the scrollbars out after a fixed delay. If a subclass 12810 * provides animated scrolling, the start delay should equal the duration of 12811 * the scrolling animation. 12812 * </p> 12813 * 12814 * <p> 12815 * The animation starts only if at least one of the scrollbars is enabled, 12816 * as specified by {@link #isHorizontalScrollBarEnabled()} and 12817 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 12818 * this method returns true, and false otherwise. If the animation is 12819 * started, this method calls {@link #invalidate()}; in that case the caller 12820 * should not call {@link #invalidate()}. 12821 * </p> 12822 * 12823 * <p> 12824 * This method should be invoked every time a subclass directly updates the 12825 * scroll parameters. 12826 * </p> 12827 * 12828 * @param startDelay the delay, in milliseconds, after which the animation 12829 * should start; when the delay is 0, the animation starts 12830 * immediately 12831 * @return true if the animation is played, false otherwise 12832 * 12833 * @see #scrollBy(int, int) 12834 * @see #scrollTo(int, int) 12835 * @see #isHorizontalScrollBarEnabled() 12836 * @see #isVerticalScrollBarEnabled() 12837 * @see #setHorizontalScrollBarEnabled(boolean) 12838 * @see #setVerticalScrollBarEnabled(boolean) 12839 */ 12840 protected boolean awakenScrollBars(int startDelay) { 12841 return awakenScrollBars(startDelay, true); 12842 } 12843 12844 /** 12845 * <p> 12846 * Trigger the scrollbars to draw. When invoked this method starts an 12847 * animation to fade the scrollbars out after a fixed delay. If a subclass 12848 * provides animated scrolling, the start delay should equal the duration of 12849 * the scrolling animation. 12850 * </p> 12851 * 12852 * <p> 12853 * The animation starts only if at least one of the scrollbars is enabled, 12854 * as specified by {@link #isHorizontalScrollBarEnabled()} and 12855 * {@link #isVerticalScrollBarEnabled()}. When the animation is started, 12856 * this method returns true, and false otherwise. If the animation is 12857 * started, this method calls {@link #invalidate()} if the invalidate parameter 12858 * is set to true; in that case the caller 12859 * should not call {@link #invalidate()}. 12860 * </p> 12861 * 12862 * <p> 12863 * This method should be invoked every time a subclass directly updates the 12864 * scroll parameters. 12865 * </p> 12866 * 12867 * @param startDelay the delay, in milliseconds, after which the animation 12868 * should start; when the delay is 0, the animation starts 12869 * immediately 12870 * 12871 * @param invalidate Whether this method should call invalidate 12872 * 12873 * @return true if the animation is played, false otherwise 12874 * 12875 * @see #scrollBy(int, int) 12876 * @see #scrollTo(int, int) 12877 * @see #isHorizontalScrollBarEnabled() 12878 * @see #isVerticalScrollBarEnabled() 12879 * @see #setHorizontalScrollBarEnabled(boolean) 12880 * @see #setVerticalScrollBarEnabled(boolean) 12881 */ 12882 protected boolean awakenScrollBars(int startDelay, boolean invalidate) { 12883 final ScrollabilityCache scrollCache = mScrollCache; 12884 12885 if (scrollCache == null || !scrollCache.fadeScrollBars) { 12886 return false; 12887 } 12888 12889 if (scrollCache.scrollBar == null) { 12890 scrollCache.scrollBar = new ScrollBarDrawable(); 12891 scrollCache.scrollBar.setCallback(this); 12892 scrollCache.scrollBar.setState(getDrawableState()); 12893 } 12894 12895 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { 12896 12897 if (invalidate) { 12898 // Invalidate to show the scrollbars 12899 postInvalidateOnAnimation(); 12900 } 12901 12902 if (scrollCache.state == ScrollabilityCache.OFF) { 12903 // FIXME: this is copied from WindowManagerService. 12904 // We should get this value from the system when it 12905 // is possible to do so. 12906 final int KEY_REPEAT_FIRST_DELAY = 750; 12907 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay); 12908 } 12909 12910 // Tell mScrollCache when we should start fading. This may 12911 // extend the fade start time if one was already scheduled 12912 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay; 12913 scrollCache.fadeStartTime = fadeStartTime; 12914 scrollCache.state = ScrollabilityCache.ON; 12915 12916 // Schedule our fader to run, unscheduling any old ones first 12917 if (mAttachInfo != null) { 12918 mAttachInfo.mHandler.removeCallbacks(scrollCache); 12919 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime); 12920 } 12921 12922 return true; 12923 } 12924 12925 return false; 12926 } 12927 12928 /** 12929 * Do not invalidate views which are not visible and which are not running an animation. They 12930 * will not get drawn and they should not set dirty flags as if they will be drawn 12931 */ 12932 private boolean skipInvalidate() { 12933 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null && 12934 (!(mParent instanceof ViewGroup) || 12935 !((ViewGroup) mParent).isViewTransitioning(this)); 12936 } 12937 12938 /** 12939 * Mark the area defined by dirty as needing to be drawn. If the view is 12940 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 12941 * point in the future. 12942 * <p> 12943 * This must be called from a UI thread. To call from a non-UI thread, call 12944 * {@link #postInvalidate()}. 12945 * <p> 12946 * <b>WARNING:</b> In API 19 and below, this method may be destructive to 12947 * {@code dirty}. 12948 * 12949 * @param dirty the rectangle representing the bounds of the dirty region 12950 */ 12951 public void invalidate(Rect dirty) { 12952 final int scrollX = mScrollX; 12953 final int scrollY = mScrollY; 12954 invalidateInternal(dirty.left - scrollX, dirty.top - scrollY, 12955 dirty.right - scrollX, dirty.bottom - scrollY, true, false); 12956 } 12957 12958 /** 12959 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The 12960 * coordinates of the dirty rect are relative to the view. If the view is 12961 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some 12962 * point in the future. 12963 * <p> 12964 * This must be called from a UI thread. To call from a non-UI thread, call 12965 * {@link #postInvalidate()}. 12966 * 12967 * @param l the left position of the dirty region 12968 * @param t the top position of the dirty region 12969 * @param r the right position of the dirty region 12970 * @param b the bottom position of the dirty region 12971 */ 12972 public void invalidate(int l, int t, int r, int b) { 12973 final int scrollX = mScrollX; 12974 final int scrollY = mScrollY; 12975 invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false); 12976 } 12977 12978 /** 12979 * Invalidate the whole view. If the view is visible, 12980 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in 12981 * the future. 12982 * <p> 12983 * This must be called from a UI thread. To call from a non-UI thread, call 12984 * {@link #postInvalidate()}. 12985 */ 12986 public void invalidate() { 12987 invalidate(true); 12988 } 12989 12990 /** 12991 * This is where the invalidate() work actually happens. A full invalidate() 12992 * causes the drawing cache to be invalidated, but this function can be 12993 * called with invalidateCache set to false to skip that invalidation step 12994 * for cases that do not need it (for example, a component that remains at 12995 * the same dimensions with the same content). 12996 * 12997 * @param invalidateCache Whether the drawing cache for this view should be 12998 * invalidated as well. This is usually true for a full 12999 * invalidate, but may be set to false if the View's contents or 13000 * dimensions have not changed. 13001 */ 13002 void invalidate(boolean invalidateCache) { 13003 invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); 13004 } 13005 13006 void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, 13007 boolean fullInvalidate) { 13008 if (mGhostView != null) { 13009 mGhostView.invalidate(true); 13010 return; 13011 } 13012 13013 if (skipInvalidate()) { 13014 return; 13015 } 13016 13017 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) 13018 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) 13019 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED 13020 || (fullInvalidate && isOpaque() != mLastIsOpaque)) { 13021 if (fullInvalidate) { 13022 mLastIsOpaque = isOpaque(); 13023 mPrivateFlags &= ~PFLAG_DRAWN; 13024 } 13025 13026 mPrivateFlags |= PFLAG_DIRTY; 13027 13028 if (invalidateCache) { 13029 mPrivateFlags |= PFLAG_INVALIDATED; 13030 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 13031 } 13032 13033 // Propagate the damage rectangle to the parent view. 13034 final AttachInfo ai = mAttachInfo; 13035 final ViewParent p = mParent; 13036 if (p != null && ai != null && l < r && t < b) { 13037 final Rect damage = ai.mTmpInvalRect; 13038 damage.set(l, t, r, b); 13039 p.invalidateChild(this, damage); 13040 } 13041 13042 // Damage the entire projection receiver, if necessary. 13043 if (mBackground != null && mBackground.isProjected()) { 13044 final View receiver = getProjectionReceiver(); 13045 if (receiver != null) { 13046 receiver.damageInParent(); 13047 } 13048 } 13049 13050 // Damage the entire IsolatedZVolume receiving this view's shadow. 13051 if (isHardwareAccelerated() && getZ() != 0) { 13052 damageShadowReceiver(); 13053 } 13054 } 13055 } 13056 13057 /** 13058 * @return this view's projection receiver, or {@code null} if none exists 13059 */ 13060 private View getProjectionReceiver() { 13061 ViewParent p = getParent(); 13062 while (p != null && p instanceof View) { 13063 final View v = (View) p; 13064 if (v.isProjectionReceiver()) { 13065 return v; 13066 } 13067 p = p.getParent(); 13068 } 13069 13070 return null; 13071 } 13072 13073 /** 13074 * @return whether the view is a projection receiver 13075 */ 13076 private boolean isProjectionReceiver() { 13077 return mBackground != null; 13078 } 13079 13080 /** 13081 * Damage area of the screen that can be covered by this View's shadow. 13082 * 13083 * This method will guarantee that any changes to shadows cast by a View 13084 * are damaged on the screen for future redraw. 13085 */ 13086 private void damageShadowReceiver() { 13087 final AttachInfo ai = mAttachInfo; 13088 if (ai != null) { 13089 ViewParent p = getParent(); 13090 if (p != null && p instanceof ViewGroup) { 13091 final ViewGroup vg = (ViewGroup) p; 13092 vg.damageInParent(); 13093 } 13094 } 13095 } 13096 13097 /** 13098 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to 13099 * set any flags or handle all of the cases handled by the default invalidation methods. 13100 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate 13101 * dirty rect. This method calls into fast invalidation methods in ViewGroup that 13102 * walk up the hierarchy, transforming the dirty rect as necessary. 13103 * 13104 * The method also handles normal invalidation logic if display list properties are not 13105 * being used in this view. The invalidateParent and forceRedraw flags are used by that 13106 * backup approach, to handle these cases used in the various property-setting methods. 13107 * 13108 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties 13109 * are not being used in this view 13110 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display 13111 * list properties are not being used in this view 13112 */ 13113 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) { 13114 if (!isHardwareAccelerated() 13115 || !mRenderNode.isValid() 13116 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) { 13117 if (invalidateParent) { 13118 invalidateParentCaches(); 13119 } 13120 if (forceRedraw) { 13121 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation 13122 } 13123 invalidate(false); 13124 } else { 13125 damageInParent(); 13126 } 13127 if (isHardwareAccelerated() && invalidateParent && getZ() != 0) { 13128 damageShadowReceiver(); 13129 } 13130 } 13131 13132 /** 13133 * Tells the parent view to damage this view's bounds. 13134 * 13135 * @hide 13136 */ 13137 protected void damageInParent() { 13138 final AttachInfo ai = mAttachInfo; 13139 final ViewParent p = mParent; 13140 if (p != null && ai != null) { 13141 final Rect r = ai.mTmpInvalRect; 13142 r.set(0, 0, mRight - mLeft, mBottom - mTop); 13143 if (mParent instanceof ViewGroup) { 13144 ((ViewGroup) mParent).damageChild(this, r); 13145 } else { 13146 mParent.invalidateChild(this, r); 13147 } 13148 } 13149 } 13150 13151 /** 13152 * Utility method to transform a given Rect by the current matrix of this view. 13153 */ 13154 void transformRect(final Rect rect) { 13155 if (!getMatrix().isIdentity()) { 13156 RectF boundingRect = mAttachInfo.mTmpTransformRect; 13157 boundingRect.set(rect); 13158 getMatrix().mapRect(boundingRect); 13159 rect.set((int) Math.floor(boundingRect.left), 13160 (int) Math.floor(boundingRect.top), 13161 (int) Math.ceil(boundingRect.right), 13162 (int) Math.ceil(boundingRect.bottom)); 13163 } 13164 } 13165 13166 /** 13167 * Used to indicate that the parent of this view should clear its caches. This functionality 13168 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13169 * which is necessary when various parent-managed properties of the view change, such as 13170 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only 13171 * clears the parent caches and does not causes an invalidate event. 13172 * 13173 * @hide 13174 */ 13175 protected void invalidateParentCaches() { 13176 if (mParent instanceof View) { 13177 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; 13178 } 13179 } 13180 13181 /** 13182 * Used to indicate that the parent of this view should be invalidated. This functionality 13183 * is used to force the parent to rebuild its display list (when hardware-accelerated), 13184 * which is necessary when various parent-managed properties of the view change, such as 13185 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate 13186 * an invalidation event to the parent. 13187 * 13188 * @hide 13189 */ 13190 protected void invalidateParentIfNeeded() { 13191 if (isHardwareAccelerated() && mParent instanceof View) { 13192 ((View) mParent).invalidate(true); 13193 } 13194 } 13195 13196 /** 13197 * @hide 13198 */ 13199 protected void invalidateParentIfNeededAndWasQuickRejected() { 13200 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) { 13201 // View was rejected last time it was drawn by its parent; this may have changed 13202 invalidateParentIfNeeded(); 13203 } 13204 } 13205 13206 /** 13207 * Indicates whether this View is opaque. An opaque View guarantees that it will 13208 * draw all the pixels overlapping its bounds using a fully opaque color. 13209 * 13210 * Subclasses of View should override this method whenever possible to indicate 13211 * whether an instance is opaque. Opaque Views are treated in a special way by 13212 * the View hierarchy, possibly allowing it to perform optimizations during 13213 * invalidate/draw passes. 13214 * 13215 * @return True if this View is guaranteed to be fully opaque, false otherwise. 13216 */ 13217 @ViewDebug.ExportedProperty(category = "drawing") 13218 public boolean isOpaque() { 13219 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK && 13220 getFinalAlpha() >= 1.0f; 13221 } 13222 13223 /** 13224 * @hide 13225 */ 13226 protected void computeOpaqueFlags() { 13227 // Opaque if: 13228 // - Has a background 13229 // - Background is opaque 13230 // - Doesn't have scrollbars or scrollbars overlay 13231 13232 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) { 13233 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND; 13234 } else { 13235 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND; 13236 } 13237 13238 final int flags = mViewFlags; 13239 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) || 13240 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY || 13241 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) { 13242 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS; 13243 } else { 13244 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS; 13245 } 13246 } 13247 13248 /** 13249 * @hide 13250 */ 13251 protected boolean hasOpaqueScrollbars() { 13252 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS; 13253 } 13254 13255 /** 13256 * @return A handler associated with the thread running the View. This 13257 * handler can be used to pump events in the UI events queue. 13258 */ 13259 public Handler getHandler() { 13260 final AttachInfo attachInfo = mAttachInfo; 13261 if (attachInfo != null) { 13262 return attachInfo.mHandler; 13263 } 13264 return null; 13265 } 13266 13267 /** 13268 * Returns the queue of runnable for this view. 13269 * 13270 * @return the queue of runnables for this view 13271 */ 13272 private HandlerActionQueue getRunQueue() { 13273 if (mRunQueue == null) { 13274 mRunQueue = new HandlerActionQueue(); 13275 } 13276 return mRunQueue; 13277 } 13278 13279 /** 13280 * Gets the view root associated with the View. 13281 * @return The view root, or null if none. 13282 * @hide 13283 */ 13284 public ViewRootImpl getViewRootImpl() { 13285 if (mAttachInfo != null) { 13286 return mAttachInfo.mViewRootImpl; 13287 } 13288 return null; 13289 } 13290 13291 /** 13292 * @hide 13293 */ 13294 public ThreadedRenderer getHardwareRenderer() { 13295 return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null; 13296 } 13297 13298 /** 13299 * <p>Causes the Runnable to be added to the message queue. 13300 * The runnable will be run on the user interface thread.</p> 13301 * 13302 * @param action The Runnable that will be executed. 13303 * 13304 * @return Returns true if the Runnable was successfully placed in to the 13305 * message queue. Returns false on failure, usually because the 13306 * looper processing the message queue is exiting. 13307 * 13308 * @see #postDelayed 13309 * @see #removeCallbacks 13310 */ 13311 public boolean post(Runnable action) { 13312 final AttachInfo attachInfo = mAttachInfo; 13313 if (attachInfo != null) { 13314 return attachInfo.mHandler.post(action); 13315 } 13316 13317 // Postpone the runnable until we know on which thread it needs to run. 13318 // Assume that the runnable will be successfully placed after attach. 13319 getRunQueue().post(action); 13320 return true; 13321 } 13322 13323 /** 13324 * <p>Causes the Runnable to be added to the message queue, to be run 13325 * after the specified amount of time elapses. 13326 * The runnable will be run on the user interface thread.</p> 13327 * 13328 * @param action The Runnable that will be executed. 13329 * @param delayMillis The delay (in milliseconds) until the Runnable 13330 * will be executed. 13331 * 13332 * @return true if the Runnable was successfully placed in to the 13333 * message queue. Returns false on failure, usually because the 13334 * looper processing the message queue is exiting. Note that a 13335 * result of true does not mean the Runnable will be processed -- 13336 * if the looper is quit before the delivery time of the message 13337 * occurs then the message will be dropped. 13338 * 13339 * @see #post 13340 * @see #removeCallbacks 13341 */ 13342 public boolean postDelayed(Runnable action, long delayMillis) { 13343 final AttachInfo attachInfo = mAttachInfo; 13344 if (attachInfo != null) { 13345 return attachInfo.mHandler.postDelayed(action, delayMillis); 13346 } 13347 13348 // Postpone the runnable until we know on which thread it needs to run. 13349 // Assume that the runnable will be successfully placed after attach. 13350 getRunQueue().postDelayed(action, delayMillis); 13351 return true; 13352 } 13353 13354 /** 13355 * <p>Causes the Runnable to execute on the next animation time step. 13356 * The runnable will be run on the user interface thread.</p> 13357 * 13358 * @param action The Runnable that will be executed. 13359 * 13360 * @see #postOnAnimationDelayed 13361 * @see #removeCallbacks 13362 */ 13363 public void postOnAnimation(Runnable action) { 13364 final AttachInfo attachInfo = mAttachInfo; 13365 if (attachInfo != null) { 13366 attachInfo.mViewRootImpl.mChoreographer.postCallback( 13367 Choreographer.CALLBACK_ANIMATION, action, null); 13368 } else { 13369 // Postpone the runnable until we know 13370 // on which thread it needs to run. 13371 getRunQueue().post(action); 13372 } 13373 } 13374 13375 /** 13376 * <p>Causes the Runnable to execute on the next animation time step, 13377 * after the specified amount of time elapses. 13378 * The runnable will be run on the user interface thread.</p> 13379 * 13380 * @param action The Runnable that will be executed. 13381 * @param delayMillis The delay (in milliseconds) until the Runnable 13382 * will be executed. 13383 * 13384 * @see #postOnAnimation 13385 * @see #removeCallbacks 13386 */ 13387 public void postOnAnimationDelayed(Runnable action, long delayMillis) { 13388 final AttachInfo attachInfo = mAttachInfo; 13389 if (attachInfo != null) { 13390 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 13391 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis); 13392 } else { 13393 // Postpone the runnable until we know 13394 // on which thread it needs to run. 13395 getRunQueue().postDelayed(action, delayMillis); 13396 } 13397 } 13398 13399 /** 13400 * <p>Removes the specified Runnable from the message queue.</p> 13401 * 13402 * @param action The Runnable to remove from the message handling queue 13403 * 13404 * @return true if this view could ask the Handler to remove the Runnable, 13405 * false otherwise. When the returned value is true, the Runnable 13406 * may or may not have been actually removed from the message queue 13407 * (for instance, if the Runnable was not in the queue already.) 13408 * 13409 * @see #post 13410 * @see #postDelayed 13411 * @see #postOnAnimation 13412 * @see #postOnAnimationDelayed 13413 */ 13414 public boolean removeCallbacks(Runnable action) { 13415 if (action != null) { 13416 final AttachInfo attachInfo = mAttachInfo; 13417 if (attachInfo != null) { 13418 attachInfo.mHandler.removeCallbacks(action); 13419 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 13420 Choreographer.CALLBACK_ANIMATION, action, null); 13421 } 13422 getRunQueue().removeCallbacks(action); 13423 } 13424 return true; 13425 } 13426 13427 /** 13428 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop. 13429 * Use this to invalidate the View from a non-UI thread.</p> 13430 * 13431 * <p>This method can be invoked from outside of the UI thread 13432 * only when this View is attached to a window.</p> 13433 * 13434 * @see #invalidate() 13435 * @see #postInvalidateDelayed(long) 13436 */ 13437 public void postInvalidate() { 13438 postInvalidateDelayed(0); 13439 } 13440 13441 /** 13442 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 13443 * through the event loop. Use this to invalidate the View from a non-UI thread.</p> 13444 * 13445 * <p>This method can be invoked from outside of the UI thread 13446 * only when this View is attached to a window.</p> 13447 * 13448 * @param left The left coordinate of the rectangle to invalidate. 13449 * @param top The top coordinate of the rectangle to invalidate. 13450 * @param right The right coordinate of the rectangle to invalidate. 13451 * @param bottom The bottom coordinate of the rectangle to invalidate. 13452 * 13453 * @see #invalidate(int, int, int, int) 13454 * @see #invalidate(Rect) 13455 * @see #postInvalidateDelayed(long, int, int, int, int) 13456 */ 13457 public void postInvalidate(int left, int top, int right, int bottom) { 13458 postInvalidateDelayed(0, left, top, right, bottom); 13459 } 13460 13461 /** 13462 * <p>Cause an invalidate to happen on a subsequent cycle through the event 13463 * loop. Waits for the specified amount of time.</p> 13464 * 13465 * <p>This method can be invoked from outside of the UI thread 13466 * only when this View is attached to a window.</p> 13467 * 13468 * @param delayMilliseconds the duration in milliseconds to delay the 13469 * invalidation by 13470 * 13471 * @see #invalidate() 13472 * @see #postInvalidate() 13473 */ 13474 public void postInvalidateDelayed(long delayMilliseconds) { 13475 // We try only with the AttachInfo because there's no point in invalidating 13476 // if we are not attached to our window 13477 final AttachInfo attachInfo = mAttachInfo; 13478 if (attachInfo != null) { 13479 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds); 13480 } 13481 } 13482 13483 /** 13484 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle 13485 * through the event loop. Waits for the specified amount of time.</p> 13486 * 13487 * <p>This method can be invoked from outside of the UI thread 13488 * only when this View is attached to a window.</p> 13489 * 13490 * @param delayMilliseconds the duration in milliseconds to delay the 13491 * invalidation by 13492 * @param left The left coordinate of the rectangle to invalidate. 13493 * @param top The top coordinate of the rectangle to invalidate. 13494 * @param right The right coordinate of the rectangle to invalidate. 13495 * @param bottom The bottom coordinate of the rectangle to invalidate. 13496 * 13497 * @see #invalidate(int, int, int, int) 13498 * @see #invalidate(Rect) 13499 * @see #postInvalidate(int, int, int, int) 13500 */ 13501 public void postInvalidateDelayed(long delayMilliseconds, int left, int top, 13502 int right, int bottom) { 13503 13504 // We try only with the AttachInfo because there's no point in invalidating 13505 // if we are not attached to our window 13506 final AttachInfo attachInfo = mAttachInfo; 13507 if (attachInfo != null) { 13508 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 13509 info.target = this; 13510 info.left = left; 13511 info.top = top; 13512 info.right = right; 13513 info.bottom = bottom; 13514 13515 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds); 13516 } 13517 } 13518 13519 /** 13520 * <p>Cause an invalidate to happen on the next animation time step, typically the 13521 * next display frame.</p> 13522 * 13523 * <p>This method can be invoked from outside of the UI thread 13524 * only when this View is attached to a window.</p> 13525 * 13526 * @see #invalidate() 13527 */ 13528 public void postInvalidateOnAnimation() { 13529 // We try only with the AttachInfo because there's no point in invalidating 13530 // if we are not attached to our window 13531 final AttachInfo attachInfo = mAttachInfo; 13532 if (attachInfo != null) { 13533 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this); 13534 } 13535 } 13536 13537 /** 13538 * <p>Cause an invalidate of the specified area to happen on the next animation 13539 * time step, typically the next display frame.</p> 13540 * 13541 * <p>This method can be invoked from outside of the UI thread 13542 * only when this View is attached to a window.</p> 13543 * 13544 * @param left The left coordinate of the rectangle to invalidate. 13545 * @param top The top coordinate of the rectangle to invalidate. 13546 * @param right The right coordinate of the rectangle to invalidate. 13547 * @param bottom The bottom coordinate of the rectangle to invalidate. 13548 * 13549 * @see #invalidate(int, int, int, int) 13550 * @see #invalidate(Rect) 13551 */ 13552 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) { 13553 // We try only with the AttachInfo because there's no point in invalidating 13554 // if we are not attached to our window 13555 final AttachInfo attachInfo = mAttachInfo; 13556 if (attachInfo != null) { 13557 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain(); 13558 info.target = this; 13559 info.left = left; 13560 info.top = top; 13561 info.right = right; 13562 info.bottom = bottom; 13563 13564 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info); 13565 } 13566 } 13567 13568 /** 13569 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event. 13570 * This event is sent at most once every 13571 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}. 13572 */ 13573 private void postSendViewScrolledAccessibilityEventCallback() { 13574 if (mSendViewScrolledAccessibilityEvent == null) { 13575 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent(); 13576 } 13577 if (!mSendViewScrolledAccessibilityEvent.mIsPending) { 13578 mSendViewScrolledAccessibilityEvent.mIsPending = true; 13579 postDelayed(mSendViewScrolledAccessibilityEvent, 13580 ViewConfiguration.getSendRecurringAccessibilityEventsInterval()); 13581 } 13582 } 13583 13584 /** 13585 * Called by a parent to request that a child update its values for mScrollX 13586 * and mScrollY if necessary. This will typically be done if the child is 13587 * animating a scroll using a {@link android.widget.Scroller Scroller} 13588 * object. 13589 */ 13590 public void computeScroll() { 13591 } 13592 13593 /** 13594 * <p>Indicate whether the horizontal edges are faded when the view is 13595 * scrolled horizontally.</p> 13596 * 13597 * @return true if the horizontal edges should are faded on scroll, false 13598 * otherwise 13599 * 13600 * @see #setHorizontalFadingEdgeEnabled(boolean) 13601 * 13602 * @attr ref android.R.styleable#View_requiresFadingEdge 13603 */ 13604 public boolean isHorizontalFadingEdgeEnabled() { 13605 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL; 13606 } 13607 13608 /** 13609 * <p>Define whether the horizontal edges should be faded when this view 13610 * is scrolled horizontally.</p> 13611 * 13612 * @param horizontalFadingEdgeEnabled true if the horizontal edges should 13613 * be faded when the view is scrolled 13614 * horizontally 13615 * 13616 * @see #isHorizontalFadingEdgeEnabled() 13617 * 13618 * @attr ref android.R.styleable#View_requiresFadingEdge 13619 */ 13620 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) { 13621 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) { 13622 if (horizontalFadingEdgeEnabled) { 13623 initScrollCache(); 13624 } 13625 13626 mViewFlags ^= FADING_EDGE_HORIZONTAL; 13627 } 13628 } 13629 13630 /** 13631 * <p>Indicate whether the vertical edges are faded when the view is 13632 * scrolled horizontally.</p> 13633 * 13634 * @return true if the vertical edges should are faded on scroll, false 13635 * otherwise 13636 * 13637 * @see #setVerticalFadingEdgeEnabled(boolean) 13638 * 13639 * @attr ref android.R.styleable#View_requiresFadingEdge 13640 */ 13641 public boolean isVerticalFadingEdgeEnabled() { 13642 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL; 13643 } 13644 13645 /** 13646 * <p>Define whether the vertical edges should be faded when this view 13647 * is scrolled vertically.</p> 13648 * 13649 * @param verticalFadingEdgeEnabled true if the vertical edges should 13650 * be faded when the view is scrolled 13651 * vertically 13652 * 13653 * @see #isVerticalFadingEdgeEnabled() 13654 * 13655 * @attr ref android.R.styleable#View_requiresFadingEdge 13656 */ 13657 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) { 13658 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) { 13659 if (verticalFadingEdgeEnabled) { 13660 initScrollCache(); 13661 } 13662 13663 mViewFlags ^= FADING_EDGE_VERTICAL; 13664 } 13665 } 13666 13667 /** 13668 * Returns the strength, or intensity, of the top faded edge. The strength is 13669 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 13670 * returns 0.0 or 1.0 but no value in between. 13671 * 13672 * Subclasses should override this method to provide a smoother fade transition 13673 * when scrolling occurs. 13674 * 13675 * @return the intensity of the top fade as a float between 0.0f and 1.0f 13676 */ 13677 protected float getTopFadingEdgeStrength() { 13678 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f; 13679 } 13680 13681 /** 13682 * Returns the strength, or intensity, of the bottom faded edge. The strength is 13683 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 13684 * returns 0.0 or 1.0 but no value in between. 13685 * 13686 * Subclasses should override this method to provide a smoother fade transition 13687 * when scrolling occurs. 13688 * 13689 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f 13690 */ 13691 protected float getBottomFadingEdgeStrength() { 13692 return computeVerticalScrollOffset() + computeVerticalScrollExtent() < 13693 computeVerticalScrollRange() ? 1.0f : 0.0f; 13694 } 13695 13696 /** 13697 * Returns the strength, or intensity, of the left faded edge. The strength is 13698 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 13699 * returns 0.0 or 1.0 but no value in between. 13700 * 13701 * Subclasses should override this method to provide a smoother fade transition 13702 * when scrolling occurs. 13703 * 13704 * @return the intensity of the left fade as a float between 0.0f and 1.0f 13705 */ 13706 protected float getLeftFadingEdgeStrength() { 13707 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f; 13708 } 13709 13710 /** 13711 * Returns the strength, or intensity, of the right faded edge. The strength is 13712 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation 13713 * returns 0.0 or 1.0 but no value in between. 13714 * 13715 * Subclasses should override this method to provide a smoother fade transition 13716 * when scrolling occurs. 13717 * 13718 * @return the intensity of the right fade as a float between 0.0f and 1.0f 13719 */ 13720 protected float getRightFadingEdgeStrength() { 13721 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() < 13722 computeHorizontalScrollRange() ? 1.0f : 0.0f; 13723 } 13724 13725 /** 13726 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The 13727 * scrollbar is not drawn by default.</p> 13728 * 13729 * @return true if the horizontal scrollbar should be painted, false 13730 * otherwise 13731 * 13732 * @see #setHorizontalScrollBarEnabled(boolean) 13733 */ 13734 public boolean isHorizontalScrollBarEnabled() { 13735 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 13736 } 13737 13738 /** 13739 * <p>Define whether the horizontal scrollbar should be drawn or not. The 13740 * scrollbar is not drawn by default.</p> 13741 * 13742 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should 13743 * be painted 13744 * 13745 * @see #isHorizontalScrollBarEnabled() 13746 */ 13747 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) { 13748 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) { 13749 mViewFlags ^= SCROLLBARS_HORIZONTAL; 13750 computeOpaqueFlags(); 13751 resolvePadding(); 13752 } 13753 } 13754 13755 /** 13756 * <p>Indicate whether the vertical scrollbar should be drawn or not. The 13757 * scrollbar is not drawn by default.</p> 13758 * 13759 * @return true if the vertical scrollbar should be painted, false 13760 * otherwise 13761 * 13762 * @see #setVerticalScrollBarEnabled(boolean) 13763 */ 13764 public boolean isVerticalScrollBarEnabled() { 13765 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL; 13766 } 13767 13768 /** 13769 * <p>Define whether the vertical scrollbar should be drawn or not. The 13770 * scrollbar is not drawn by default.</p> 13771 * 13772 * @param verticalScrollBarEnabled true if the vertical scrollbar should 13773 * be painted 13774 * 13775 * @see #isVerticalScrollBarEnabled() 13776 */ 13777 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) { 13778 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) { 13779 mViewFlags ^= SCROLLBARS_VERTICAL; 13780 computeOpaqueFlags(); 13781 resolvePadding(); 13782 } 13783 } 13784 13785 /** 13786 * @hide 13787 */ 13788 protected void recomputePadding() { 13789 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 13790 } 13791 13792 /** 13793 * Define whether scrollbars will fade when the view is not scrolling. 13794 * 13795 * @param fadeScrollbars whether to enable fading 13796 * 13797 * @attr ref android.R.styleable#View_fadeScrollbars 13798 */ 13799 public void setScrollbarFadingEnabled(boolean fadeScrollbars) { 13800 initScrollCache(); 13801 final ScrollabilityCache scrollabilityCache = mScrollCache; 13802 scrollabilityCache.fadeScrollBars = fadeScrollbars; 13803 if (fadeScrollbars) { 13804 scrollabilityCache.state = ScrollabilityCache.OFF; 13805 } else { 13806 scrollabilityCache.state = ScrollabilityCache.ON; 13807 } 13808 } 13809 13810 /** 13811 * 13812 * Returns true if scrollbars will fade when this view is not scrolling 13813 * 13814 * @return true if scrollbar fading is enabled 13815 * 13816 * @attr ref android.R.styleable#View_fadeScrollbars 13817 */ 13818 public boolean isScrollbarFadingEnabled() { 13819 return mScrollCache != null && mScrollCache.fadeScrollBars; 13820 } 13821 13822 /** 13823 * 13824 * Returns the delay before scrollbars fade. 13825 * 13826 * @return the delay before scrollbars fade 13827 * 13828 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 13829 */ 13830 public int getScrollBarDefaultDelayBeforeFade() { 13831 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() : 13832 mScrollCache.scrollBarDefaultDelayBeforeFade; 13833 } 13834 13835 /** 13836 * Define the delay before scrollbars fade. 13837 * 13838 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade 13839 * 13840 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade 13841 */ 13842 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) { 13843 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade; 13844 } 13845 13846 /** 13847 * 13848 * Returns the scrollbar fade duration. 13849 * 13850 * @return the scrollbar fade duration 13851 * 13852 * @attr ref android.R.styleable#View_scrollbarFadeDuration 13853 */ 13854 public int getScrollBarFadeDuration() { 13855 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() : 13856 mScrollCache.scrollBarFadeDuration; 13857 } 13858 13859 /** 13860 * Define the scrollbar fade duration. 13861 * 13862 * @param scrollBarFadeDuration - the scrollbar fade duration 13863 * 13864 * @attr ref android.R.styleable#View_scrollbarFadeDuration 13865 */ 13866 public void setScrollBarFadeDuration(int scrollBarFadeDuration) { 13867 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration; 13868 } 13869 13870 /** 13871 * 13872 * Returns the scrollbar size. 13873 * 13874 * @return the scrollbar size 13875 * 13876 * @attr ref android.R.styleable#View_scrollbarSize 13877 */ 13878 public int getScrollBarSize() { 13879 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() : 13880 mScrollCache.scrollBarSize; 13881 } 13882 13883 /** 13884 * Define the scrollbar size. 13885 * 13886 * @param scrollBarSize - the scrollbar size 13887 * 13888 * @attr ref android.R.styleable#View_scrollbarSize 13889 */ 13890 public void setScrollBarSize(int scrollBarSize) { 13891 getScrollCache().scrollBarSize = scrollBarSize; 13892 } 13893 13894 /** 13895 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or 13896 * inset. When inset, they add to the padding of the view. And the scrollbars 13897 * can be drawn inside the padding area or on the edge of the view. For example, 13898 * if a view has a background drawable and you want to draw the scrollbars 13899 * inside the padding specified by the drawable, you can use 13900 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to 13901 * appear at the edge of the view, ignoring the padding, then you can use 13902 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p> 13903 * @param style the style of the scrollbars. Should be one of 13904 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET, 13905 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET. 13906 * @see #SCROLLBARS_INSIDE_OVERLAY 13907 * @see #SCROLLBARS_INSIDE_INSET 13908 * @see #SCROLLBARS_OUTSIDE_OVERLAY 13909 * @see #SCROLLBARS_OUTSIDE_INSET 13910 * 13911 * @attr ref android.R.styleable#View_scrollbarStyle 13912 */ 13913 public void setScrollBarStyle(@ScrollBarStyle int style) { 13914 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) { 13915 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK); 13916 computeOpaqueFlags(); 13917 resolvePadding(); 13918 } 13919 } 13920 13921 /** 13922 * <p>Returns the current scrollbar style.</p> 13923 * @return the current scrollbar style 13924 * @see #SCROLLBARS_INSIDE_OVERLAY 13925 * @see #SCROLLBARS_INSIDE_INSET 13926 * @see #SCROLLBARS_OUTSIDE_OVERLAY 13927 * @see #SCROLLBARS_OUTSIDE_INSET 13928 * 13929 * @attr ref android.R.styleable#View_scrollbarStyle 13930 */ 13931 @ViewDebug.ExportedProperty(mapping = { 13932 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"), 13933 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"), 13934 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"), 13935 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET") 13936 }) 13937 @ScrollBarStyle 13938 public int getScrollBarStyle() { 13939 return mViewFlags & SCROLLBARS_STYLE_MASK; 13940 } 13941 13942 /** 13943 * <p>Compute the horizontal range that the horizontal scrollbar 13944 * represents.</p> 13945 * 13946 * <p>The range is expressed in arbitrary units that must be the same as the 13947 * units used by {@link #computeHorizontalScrollExtent()} and 13948 * {@link #computeHorizontalScrollOffset()}.</p> 13949 * 13950 * <p>The default range is the drawing width of this view.</p> 13951 * 13952 * @return the total horizontal range represented by the horizontal 13953 * scrollbar 13954 * 13955 * @see #computeHorizontalScrollExtent() 13956 * @see #computeHorizontalScrollOffset() 13957 * @see android.widget.ScrollBarDrawable 13958 */ 13959 protected int computeHorizontalScrollRange() { 13960 return getWidth(); 13961 } 13962 13963 /** 13964 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb 13965 * within the horizontal range. This value is used to compute the position 13966 * of the thumb within the scrollbar's track.</p> 13967 * 13968 * <p>The range is expressed in arbitrary units that must be the same as the 13969 * units used by {@link #computeHorizontalScrollRange()} and 13970 * {@link #computeHorizontalScrollExtent()}.</p> 13971 * 13972 * <p>The default offset is the scroll offset of this view.</p> 13973 * 13974 * @return the horizontal offset of the scrollbar's thumb 13975 * 13976 * @see #computeHorizontalScrollRange() 13977 * @see #computeHorizontalScrollExtent() 13978 * @see android.widget.ScrollBarDrawable 13979 */ 13980 protected int computeHorizontalScrollOffset() { 13981 return mScrollX; 13982 } 13983 13984 /** 13985 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb 13986 * within the horizontal range. This value is used to compute the length 13987 * of the thumb within the scrollbar's track.</p> 13988 * 13989 * <p>The range is expressed in arbitrary units that must be the same as the 13990 * units used by {@link #computeHorizontalScrollRange()} and 13991 * {@link #computeHorizontalScrollOffset()}.</p> 13992 * 13993 * <p>The default extent is the drawing width of this view.</p> 13994 * 13995 * @return the horizontal extent of the scrollbar's thumb 13996 * 13997 * @see #computeHorizontalScrollRange() 13998 * @see #computeHorizontalScrollOffset() 13999 * @see android.widget.ScrollBarDrawable 14000 */ 14001 protected int computeHorizontalScrollExtent() { 14002 return getWidth(); 14003 } 14004 14005 /** 14006 * <p>Compute the vertical range that the vertical scrollbar represents.</p> 14007 * 14008 * <p>The range is expressed in arbitrary units that must be the same as the 14009 * units used by {@link #computeVerticalScrollExtent()} and 14010 * {@link #computeVerticalScrollOffset()}.</p> 14011 * 14012 * @return the total vertical range represented by the vertical scrollbar 14013 * 14014 * <p>The default range is the drawing height of this view.</p> 14015 * 14016 * @see #computeVerticalScrollExtent() 14017 * @see #computeVerticalScrollOffset() 14018 * @see android.widget.ScrollBarDrawable 14019 */ 14020 protected int computeVerticalScrollRange() { 14021 return getHeight(); 14022 } 14023 14024 /** 14025 * <p>Compute the vertical offset of the vertical scrollbar's thumb 14026 * within the horizontal range. This value is used to compute the position 14027 * of the thumb within the scrollbar's track.</p> 14028 * 14029 * <p>The range is expressed in arbitrary units that must be the same as the 14030 * units used by {@link #computeVerticalScrollRange()} and 14031 * {@link #computeVerticalScrollExtent()}.</p> 14032 * 14033 * <p>The default offset is the scroll offset of this view.</p> 14034 * 14035 * @return the vertical offset of the scrollbar's thumb 14036 * 14037 * @see #computeVerticalScrollRange() 14038 * @see #computeVerticalScrollExtent() 14039 * @see android.widget.ScrollBarDrawable 14040 */ 14041 protected int computeVerticalScrollOffset() { 14042 return mScrollY; 14043 } 14044 14045 /** 14046 * <p>Compute the vertical extent of the vertical scrollbar's thumb 14047 * within the vertical range. This value is used to compute the length 14048 * of the thumb within the scrollbar's track.</p> 14049 * 14050 * <p>The range is expressed in arbitrary units that must be the same as the 14051 * units used by {@link #computeVerticalScrollRange()} and 14052 * {@link #computeVerticalScrollOffset()}.</p> 14053 * 14054 * <p>The default extent is the drawing height of this view.</p> 14055 * 14056 * @return the vertical extent of the scrollbar's thumb 14057 * 14058 * @see #computeVerticalScrollRange() 14059 * @see #computeVerticalScrollOffset() 14060 * @see android.widget.ScrollBarDrawable 14061 */ 14062 protected int computeVerticalScrollExtent() { 14063 return getHeight(); 14064 } 14065 14066 /** 14067 * Check if this view can be scrolled horizontally in a certain direction. 14068 * 14069 * @param direction Negative to check scrolling left, positive to check scrolling right. 14070 * @return true if this view can be scrolled in the specified direction, false otherwise. 14071 */ 14072 public boolean canScrollHorizontally(int direction) { 14073 final int offset = computeHorizontalScrollOffset(); 14074 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent(); 14075 if (range == 0) return false; 14076 if (direction < 0) { 14077 return offset > 0; 14078 } else { 14079 return offset < range - 1; 14080 } 14081 } 14082 14083 /** 14084 * Check if this view can be scrolled vertically in a certain direction. 14085 * 14086 * @param direction Negative to check scrolling up, positive to check scrolling down. 14087 * @return true if this view can be scrolled in the specified direction, false otherwise. 14088 */ 14089 public boolean canScrollVertically(int direction) { 14090 final int offset = computeVerticalScrollOffset(); 14091 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent(); 14092 if (range == 0) return false; 14093 if (direction < 0) { 14094 return offset > 0; 14095 } else { 14096 return offset < range - 1; 14097 } 14098 } 14099 14100 void getScrollIndicatorBounds(@NonNull Rect out) { 14101 out.left = mScrollX; 14102 out.right = mScrollX + mRight - mLeft; 14103 out.top = mScrollY; 14104 out.bottom = mScrollY + mBottom - mTop; 14105 } 14106 14107 private void onDrawScrollIndicators(Canvas c) { 14108 if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) { 14109 // No scroll indicators enabled. 14110 return; 14111 } 14112 14113 final Drawable dr = mScrollIndicatorDrawable; 14114 if (dr == null) { 14115 // Scroll indicators aren't supported here. 14116 return; 14117 } 14118 14119 final int h = dr.getIntrinsicHeight(); 14120 final int w = dr.getIntrinsicWidth(); 14121 final Rect rect = mAttachInfo.mTmpInvalRect; 14122 getScrollIndicatorBounds(rect); 14123 14124 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) { 14125 final boolean canScrollUp = canScrollVertically(-1); 14126 if (canScrollUp) { 14127 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h); 14128 dr.draw(c); 14129 } 14130 } 14131 14132 if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) { 14133 final boolean canScrollDown = canScrollVertically(1); 14134 if (canScrollDown) { 14135 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom); 14136 dr.draw(c); 14137 } 14138 } 14139 14140 final int leftRtl; 14141 final int rightRtl; 14142 if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 14143 leftRtl = PFLAG3_SCROLL_INDICATOR_END; 14144 rightRtl = PFLAG3_SCROLL_INDICATOR_START; 14145 } else { 14146 leftRtl = PFLAG3_SCROLL_INDICATOR_START; 14147 rightRtl = PFLAG3_SCROLL_INDICATOR_END; 14148 } 14149 14150 final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl; 14151 if ((mPrivateFlags3 & leftMask) != 0) { 14152 final boolean canScrollLeft = canScrollHorizontally(-1); 14153 if (canScrollLeft) { 14154 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom); 14155 dr.draw(c); 14156 } 14157 } 14158 14159 final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl; 14160 if ((mPrivateFlags3 & rightMask) != 0) { 14161 final boolean canScrollRight = canScrollHorizontally(1); 14162 if (canScrollRight) { 14163 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom); 14164 dr.draw(c); 14165 } 14166 } 14167 } 14168 14169 /** 14170 * <p>Request the drawing of the horizontal and the vertical scrollbar. The 14171 * scrollbars are painted only if they have been awakened first.</p> 14172 * 14173 * @param canvas the canvas on which to draw the scrollbars 14174 * 14175 * @see #awakenScrollBars(int) 14176 */ 14177 protected final void onDrawScrollBars(Canvas canvas) { 14178 // scrollbars are drawn only when the animation is running 14179 final ScrollabilityCache cache = mScrollCache; 14180 if (cache != null) { 14181 14182 int state = cache.state; 14183 14184 if (state == ScrollabilityCache.OFF) { 14185 return; 14186 } 14187 14188 boolean invalidate = false; 14189 14190 if (state == ScrollabilityCache.FADING) { 14191 // We're fading -- get our fade interpolation 14192 if (cache.interpolatorValues == null) { 14193 cache.interpolatorValues = new float[1]; 14194 } 14195 14196 float[] values = cache.interpolatorValues; 14197 14198 // Stops the animation if we're done 14199 if (cache.scrollBarInterpolator.timeToValues(values) == 14200 Interpolator.Result.FREEZE_END) { 14201 cache.state = ScrollabilityCache.OFF; 14202 } else { 14203 cache.scrollBar.mutate().setAlpha(Math.round(values[0])); 14204 } 14205 14206 // This will make the scroll bars inval themselves after 14207 // drawing. We only want this when we're fading so that 14208 // we prevent excessive redraws 14209 invalidate = true; 14210 } else { 14211 // We're just on -- but we may have been fading before so 14212 // reset alpha 14213 cache.scrollBar.mutate().setAlpha(255); 14214 } 14215 14216 14217 final int viewFlags = mViewFlags; 14218 14219 final boolean drawHorizontalScrollBar = 14220 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL; 14221 final boolean drawVerticalScrollBar = 14222 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL 14223 && !isVerticalScrollBarHidden(); 14224 14225 if (drawVerticalScrollBar || drawHorizontalScrollBar) { 14226 final int width = mRight - mLeft; 14227 final int height = mBottom - mTop; 14228 14229 final ScrollBarDrawable scrollBar = cache.scrollBar; 14230 14231 final int scrollX = mScrollX; 14232 final int scrollY = mScrollY; 14233 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; 14234 14235 int left; 14236 int top; 14237 int right; 14238 int bottom; 14239 14240 if (drawHorizontalScrollBar) { 14241 int size = scrollBar.getSize(false); 14242 if (size <= 0) { 14243 size = cache.scrollBarSize; 14244 } 14245 14246 scrollBar.setParameters(computeHorizontalScrollRange(), 14247 computeHorizontalScrollOffset(), 14248 computeHorizontalScrollExtent(), false); 14249 final int verticalScrollBarGap = drawVerticalScrollBar ? 14250 getVerticalScrollbarWidth() : 0; 14251 top = scrollY + height - size - (mUserPaddingBottom & inside); 14252 left = scrollX + (mPaddingLeft & inside); 14253 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap; 14254 bottom = top + size; 14255 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom); 14256 if (invalidate) { 14257 invalidate(left, top, right, bottom); 14258 } 14259 } 14260 14261 if (drawVerticalScrollBar) { 14262 int size = scrollBar.getSize(true); 14263 if (size <= 0) { 14264 size = cache.scrollBarSize; 14265 } 14266 14267 scrollBar.setParameters(computeVerticalScrollRange(), 14268 computeVerticalScrollOffset(), 14269 computeVerticalScrollExtent(), true); 14270 int verticalScrollbarPosition = mVerticalScrollbarPosition; 14271 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) { 14272 verticalScrollbarPosition = isLayoutRtl() ? 14273 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT; 14274 } 14275 switch (verticalScrollbarPosition) { 14276 default: 14277 case SCROLLBAR_POSITION_RIGHT: 14278 left = scrollX + width - size - (mUserPaddingRight & inside); 14279 break; 14280 case SCROLLBAR_POSITION_LEFT: 14281 left = scrollX + (mUserPaddingLeft & inside); 14282 break; 14283 } 14284 top = scrollY + (mPaddingTop & inside); 14285 right = left + size; 14286 bottom = scrollY + height - (mUserPaddingBottom & inside); 14287 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom); 14288 if (invalidate) { 14289 invalidate(left, top, right, bottom); 14290 } 14291 } 14292 } 14293 } 14294 } 14295 14296 /** 14297 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when 14298 * FastScroller is visible. 14299 * @return whether to temporarily hide the vertical scrollbar 14300 * @hide 14301 */ 14302 protected boolean isVerticalScrollBarHidden() { 14303 return false; 14304 } 14305 14306 /** 14307 * <p>Draw the horizontal scrollbar if 14308 * {@link #isHorizontalScrollBarEnabled()} returns true.</p> 14309 * 14310 * @param canvas the canvas on which to draw the scrollbar 14311 * @param scrollBar the scrollbar's drawable 14312 * 14313 * @see #isHorizontalScrollBarEnabled() 14314 * @see #computeHorizontalScrollRange() 14315 * @see #computeHorizontalScrollExtent() 14316 * @see #computeHorizontalScrollOffset() 14317 * @see android.widget.ScrollBarDrawable 14318 * @hide 14319 */ 14320 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, 14321 int l, int t, int r, int b) { 14322 scrollBar.setBounds(l, t, r, b); 14323 scrollBar.draw(canvas); 14324 } 14325 14326 /** 14327 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} 14328 * returns true.</p> 14329 * 14330 * @param canvas the canvas on which to draw the scrollbar 14331 * @param scrollBar the scrollbar's drawable 14332 * 14333 * @see #isVerticalScrollBarEnabled() 14334 * @see #computeVerticalScrollRange() 14335 * @see #computeVerticalScrollExtent() 14336 * @see #computeVerticalScrollOffset() 14337 * @see android.widget.ScrollBarDrawable 14338 * @hide 14339 */ 14340 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, 14341 int l, int t, int r, int b) { 14342 scrollBar.setBounds(l, t, r, b); 14343 scrollBar.draw(canvas); 14344 } 14345 14346 /** 14347 * Implement this to do your drawing. 14348 * 14349 * @param canvas the canvas on which the background will be drawn 14350 */ 14351 protected void onDraw(Canvas canvas) { 14352 } 14353 14354 /* 14355 * Caller is responsible for calling requestLayout if necessary. 14356 * (This allows addViewInLayout to not request a new layout.) 14357 */ 14358 void assignParent(ViewParent parent) { 14359 if (mParent == null) { 14360 mParent = parent; 14361 } else if (parent == null) { 14362 mParent = null; 14363 } else { 14364 throw new RuntimeException("view " + this + " being added, but" 14365 + " it already has a parent"); 14366 } 14367 } 14368 14369 /** 14370 * This is called when the view is attached to a window. At this point it 14371 * has a Surface and will start drawing. Note that this function is 14372 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)}, 14373 * however it may be called any time before the first onDraw -- including 14374 * before or after {@link #onMeasure(int, int)}. 14375 * 14376 * @see #onDetachedFromWindow() 14377 */ 14378 @CallSuper 14379 protected void onAttachedToWindow() { 14380 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) { 14381 mParent.requestTransparentRegion(this); 14382 } 14383 14384 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) { 14385 initialAwakenScrollBars(); 14386 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH; 14387 } 14388 14389 mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED); 14390 14391 jumpDrawablesToCurrentState(); 14392 14393 resetSubtreeAccessibilityStateChanged(); 14394 14395 // rebuild, since Outline not maintained while View is detached 14396 rebuildOutline(); 14397 14398 if (isFocused()) { 14399 InputMethodManager imm = InputMethodManager.peekInstance(); 14400 if (imm != null) { 14401 imm.focusIn(this); 14402 } 14403 } 14404 } 14405 14406 /** 14407 * Resolve all RTL related properties. 14408 * 14409 * @return true if resolution of RTL properties has been done 14410 * 14411 * @hide 14412 */ 14413 public boolean resolveRtlPropertiesIfNeeded() { 14414 if (!needRtlPropertiesResolution()) return false; 14415 14416 // Order is important here: LayoutDirection MUST be resolved first 14417 if (!isLayoutDirectionResolved()) { 14418 resolveLayoutDirection(); 14419 resolveLayoutParams(); 14420 } 14421 // ... then we can resolve the others properties depending on the resolved LayoutDirection. 14422 if (!isTextDirectionResolved()) { 14423 resolveTextDirection(); 14424 } 14425 if (!isTextAlignmentResolved()) { 14426 resolveTextAlignment(); 14427 } 14428 // Should resolve Drawables before Padding because we need the layout direction of the 14429 // Drawable to correctly resolve Padding. 14430 if (!areDrawablesResolved()) { 14431 resolveDrawables(); 14432 } 14433 if (!isPaddingResolved()) { 14434 resolvePadding(); 14435 } 14436 onRtlPropertiesChanged(getLayoutDirection()); 14437 return true; 14438 } 14439 14440 /** 14441 * Reset resolution of all RTL related properties. 14442 * 14443 * @hide 14444 */ 14445 public void resetRtlProperties() { 14446 resetResolvedLayoutDirection(); 14447 resetResolvedTextDirection(); 14448 resetResolvedTextAlignment(); 14449 resetResolvedPadding(); 14450 resetResolvedDrawables(); 14451 } 14452 14453 /** 14454 * @see #onScreenStateChanged(int) 14455 */ 14456 void dispatchScreenStateChanged(int screenState) { 14457 onScreenStateChanged(screenState); 14458 } 14459 14460 /** 14461 * This method is called whenever the state of the screen this view is 14462 * attached to changes. A state change will usually occurs when the screen 14463 * turns on or off (whether it happens automatically or the user does it 14464 * manually.) 14465 * 14466 * @param screenState The new state of the screen. Can be either 14467 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF} 14468 */ 14469 public void onScreenStateChanged(int screenState) { 14470 } 14471 14472 /** 14473 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 14474 */ 14475 private boolean hasRtlSupport() { 14476 return mContext.getApplicationInfo().hasRtlSupport(); 14477 } 14478 14479 /** 14480 * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 14481 * RTL not supported) 14482 */ 14483 private boolean isRtlCompatibilityMode() { 14484 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion; 14485 return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 14486 } 14487 14488 /** 14489 * @return true if RTL properties need resolution. 14490 * 14491 */ 14492 private boolean needRtlPropertiesResolution() { 14493 return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED; 14494 } 14495 14496 /** 14497 * Called when any RTL property (layout direction or text direction or text alignment) has 14498 * been changed. 14499 * 14500 * Subclasses need to override this method to take care of cached information that depends on the 14501 * resolved layout direction, or to inform child views that inherit their layout direction. 14502 * 14503 * The default implementation does nothing. 14504 * 14505 * @param layoutDirection the direction of the layout 14506 * 14507 * @see #LAYOUT_DIRECTION_LTR 14508 * @see #LAYOUT_DIRECTION_RTL 14509 */ 14510 public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) { 14511 } 14512 14513 /** 14514 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing 14515 * that the parent directionality can and will be resolved before its children. 14516 * 14517 * @return true if resolution has been done, false otherwise. 14518 * 14519 * @hide 14520 */ 14521 public boolean resolveLayoutDirection() { 14522 // Clear any previous layout direction resolution 14523 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 14524 14525 if (hasRtlSupport()) { 14526 // Set resolved depending on layout direction 14527 switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> 14528 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) { 14529 case LAYOUT_DIRECTION_INHERIT: 14530 // We cannot resolve yet. LTR is by default and let the resolution happen again 14531 // later to get the correct resolved value 14532 if (!canResolveLayoutDirection()) return false; 14533 14534 // Parent has not yet resolved, LTR is still the default 14535 try { 14536 if (!mParent.isLayoutDirectionResolved()) return false; 14537 14538 if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) { 14539 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 14540 } 14541 } catch (AbstractMethodError e) { 14542 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 14543 " does not fully implement ViewParent", e); 14544 } 14545 break; 14546 case LAYOUT_DIRECTION_RTL: 14547 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 14548 break; 14549 case LAYOUT_DIRECTION_LOCALE: 14550 if((LAYOUT_DIRECTION_RTL == 14551 TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) { 14552 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL; 14553 } 14554 break; 14555 default: 14556 // Nothing to do, LTR by default 14557 } 14558 } 14559 14560 // Set to resolved 14561 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED; 14562 return true; 14563 } 14564 14565 /** 14566 * Check if layout direction resolution can be done. 14567 * 14568 * @return true if layout direction resolution can be done otherwise return false. 14569 */ 14570 public boolean canResolveLayoutDirection() { 14571 switch (getRawLayoutDirection()) { 14572 case LAYOUT_DIRECTION_INHERIT: 14573 if (mParent != null) { 14574 try { 14575 return mParent.canResolveLayoutDirection(); 14576 } catch (AbstractMethodError e) { 14577 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 14578 " does not fully implement ViewParent", e); 14579 } 14580 } 14581 return false; 14582 14583 default: 14584 return true; 14585 } 14586 } 14587 14588 /** 14589 * Reset the resolved layout direction. Layout direction will be resolved during a call to 14590 * {@link #onMeasure(int, int)}. 14591 * 14592 * @hide 14593 */ 14594 public void resetResolvedLayoutDirection() { 14595 // Reset the current resolved bits 14596 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK; 14597 } 14598 14599 /** 14600 * @return true if the layout direction is inherited. 14601 * 14602 * @hide 14603 */ 14604 public boolean isLayoutDirectionInherited() { 14605 return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT); 14606 } 14607 14608 /** 14609 * @return true if layout direction has been resolved. 14610 */ 14611 public boolean isLayoutDirectionResolved() { 14612 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED; 14613 } 14614 14615 /** 14616 * Return if padding has been resolved 14617 * 14618 * @hide 14619 */ 14620 boolean isPaddingResolved() { 14621 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED; 14622 } 14623 14624 /** 14625 * Resolves padding depending on layout direction, if applicable, and 14626 * recomputes internal padding values to adjust for scroll bars. 14627 * 14628 * @hide 14629 */ 14630 public void resolvePadding() { 14631 final int resolvedLayoutDirection = getLayoutDirection(); 14632 14633 if (!isRtlCompatibilityMode()) { 14634 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account. 14635 // If start / end padding are defined, they will be resolved (hence overriding) to 14636 // left / right or right / left depending on the resolved layout direction. 14637 // If start / end padding are not defined, use the left / right ones. 14638 if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { 14639 Rect padding = sThreadLocal.get(); 14640 if (padding == null) { 14641 padding = new Rect(); 14642 sThreadLocal.set(padding); 14643 } 14644 mBackground.getPadding(padding); 14645 if (!mLeftPaddingDefined) { 14646 mUserPaddingLeftInitial = padding.left; 14647 } 14648 if (!mRightPaddingDefined) { 14649 mUserPaddingRightInitial = padding.right; 14650 } 14651 } 14652 switch (resolvedLayoutDirection) { 14653 case LAYOUT_DIRECTION_RTL: 14654 if (mUserPaddingStart != UNDEFINED_PADDING) { 14655 mUserPaddingRight = mUserPaddingStart; 14656 } else { 14657 mUserPaddingRight = mUserPaddingRightInitial; 14658 } 14659 if (mUserPaddingEnd != UNDEFINED_PADDING) { 14660 mUserPaddingLeft = mUserPaddingEnd; 14661 } else { 14662 mUserPaddingLeft = mUserPaddingLeftInitial; 14663 } 14664 break; 14665 case LAYOUT_DIRECTION_LTR: 14666 default: 14667 if (mUserPaddingStart != UNDEFINED_PADDING) { 14668 mUserPaddingLeft = mUserPaddingStart; 14669 } else { 14670 mUserPaddingLeft = mUserPaddingLeftInitial; 14671 } 14672 if (mUserPaddingEnd != UNDEFINED_PADDING) { 14673 mUserPaddingRight = mUserPaddingEnd; 14674 } else { 14675 mUserPaddingRight = mUserPaddingRightInitial; 14676 } 14677 } 14678 14679 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom; 14680 } 14681 14682 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); 14683 onRtlPropertiesChanged(resolvedLayoutDirection); 14684 14685 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED; 14686 } 14687 14688 /** 14689 * Reset the resolved layout direction. 14690 * 14691 * @hide 14692 */ 14693 public void resetResolvedPadding() { 14694 resetResolvedPaddingInternal(); 14695 } 14696 14697 /** 14698 * Used when we only want to reset *this* view's padding and not trigger overrides 14699 * in ViewGroup that reset children too. 14700 */ 14701 void resetResolvedPaddingInternal() { 14702 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED; 14703 } 14704 14705 /** 14706 * This is called when the view is detached from a window. At this point it 14707 * no longer has a surface for drawing. 14708 * 14709 * @see #onAttachedToWindow() 14710 */ 14711 @CallSuper 14712 protected void onDetachedFromWindow() { 14713 } 14714 14715 /** 14716 * This is a framework-internal mirror of onDetachedFromWindow() that's called 14717 * after onDetachedFromWindow(). 14718 * 14719 * If you override this you *MUST* call super.onDetachedFromWindowInternal()! 14720 * The super method should be called at the end of the overridden method to ensure 14721 * subclasses are destroyed first 14722 * 14723 * @hide 14724 */ 14725 @CallSuper 14726 protected void onDetachedFromWindowInternal() { 14727 if (mAttachInfo != null && isPartialLayoutRequested()) { 14728 mAttachInfo.mPartialLayoutViews.remove(this); 14729 } 14730 14731 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; 14732 mPrivateFlags3 &= ~(PFLAG3_IS_LAID_OUT | PFLAG3_PARTIAL_LAYOUT_REQUESTED 14733 | PFLAG3_LAYOUT_PARAMS_CHANGED); 14734 14735 removeUnsetPressCallback(); 14736 removeLongPressCallback(); 14737 removePerformClickCallback(); 14738 removeSendViewScrolledAccessibilityEventCallback(); 14739 stopNestedScroll(); 14740 14741 // Anything that started animating right before detach should already 14742 // be in its final state when re-attached. 14743 jumpDrawablesToCurrentState(); 14744 14745 destroyDrawingCache(); 14746 14747 cleanupDraw(); 14748 mCurrentAnimation = null; 14749 } 14750 14751 private void cleanupDraw() { 14752 resetDisplayList(); 14753 if (mAttachInfo != null) { 14754 mAttachInfo.mViewRootImpl.cancelInvalidate(this); 14755 } 14756 } 14757 14758 void invalidateInheritedLayoutMode(int layoutModeOfRoot) { 14759 } 14760 14761 /** 14762 * @return The number of times this view has been attached to a window 14763 */ 14764 protected int getWindowAttachCount() { 14765 return mWindowAttachCount; 14766 } 14767 14768 /** 14769 * Retrieve a unique token identifying the window this view is attached to. 14770 * @return Return the window's token for use in 14771 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}. 14772 */ 14773 public IBinder getWindowToken() { 14774 return mAttachInfo != null ? mAttachInfo.mWindowToken : null; 14775 } 14776 14777 /** 14778 * Retrieve the {@link WindowId} for the window this view is 14779 * currently attached to. 14780 */ 14781 public WindowId getWindowId() { 14782 if (mAttachInfo == null) { 14783 return null; 14784 } 14785 if (mAttachInfo.mWindowId == null) { 14786 try { 14787 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId( 14788 mAttachInfo.mWindowToken); 14789 mAttachInfo.mWindowId = new WindowId( 14790 mAttachInfo.mIWindowId); 14791 } catch (RemoteException e) { 14792 } 14793 } 14794 return mAttachInfo.mWindowId; 14795 } 14796 14797 /** 14798 * Retrieve a unique token identifying the top-level "real" window of 14799 * the window that this view is attached to. That is, this is like 14800 * {@link #getWindowToken}, except if the window this view in is a panel 14801 * window (attached to another containing window), then the token of 14802 * the containing window is returned instead. 14803 * 14804 * @return Returns the associated window token, either 14805 * {@link #getWindowToken()} or the containing window's token. 14806 */ 14807 public IBinder getApplicationWindowToken() { 14808 AttachInfo ai = mAttachInfo; 14809 if (ai != null) { 14810 IBinder appWindowToken = ai.mPanelParentWindowToken; 14811 if (appWindowToken == null) { 14812 appWindowToken = ai.mWindowToken; 14813 } 14814 return appWindowToken; 14815 } 14816 return null; 14817 } 14818 14819 /** 14820 * Gets the logical display to which the view's window has been attached. 14821 * 14822 * @return The logical display, or null if the view is not currently attached to a window. 14823 */ 14824 public Display getDisplay() { 14825 return mAttachInfo != null ? mAttachInfo.mDisplay : null; 14826 } 14827 14828 /** 14829 * Retrieve private session object this view hierarchy is using to 14830 * communicate with the window manager. 14831 * @return the session object to communicate with the window manager 14832 */ 14833 /*package*/ IWindowSession getWindowSession() { 14834 return mAttachInfo != null ? mAttachInfo.mSession : null; 14835 } 14836 14837 /** 14838 * Return the visibility value of the least visible component passed. 14839 */ 14840 int combineVisibility(int vis1, int vis2) { 14841 // This works because VISIBLE < INVISIBLE < GONE. 14842 return Math.max(vis1, vis2); 14843 } 14844 14845 /** 14846 * @param info the {@link android.view.View.AttachInfo} to associated with 14847 * this view 14848 */ 14849 void dispatchAttachedToWindow(AttachInfo info, int visibility) { 14850 mAttachInfo = info; 14851 if (mOverlay != null) { 14852 mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility); 14853 } 14854 mWindowAttachCount++; 14855 // We will need to evaluate the drawable state at least once. 14856 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 14857 if (mFloatingTreeObserver != null) { 14858 info.mTreeObserver.merge(mFloatingTreeObserver); 14859 mFloatingTreeObserver = null; 14860 } 14861 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { 14862 mAttachInfo.mScrollContainers.add(this); 14863 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; 14864 } 14865 // Transfer all pending runnables. 14866 if (mRunQueue != null) { 14867 mRunQueue.executeActions(info.mHandler); 14868 mRunQueue = null; 14869 } 14870 performCollectViewAttributes(mAttachInfo, visibility); 14871 onAttachedToWindow(); 14872 14873 ListenerInfo li = mListenerInfo; 14874 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 14875 li != null ? li.mOnAttachStateChangeListeners : null; 14876 if (listeners != null && listeners.size() > 0) { 14877 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 14878 // perform the dispatching. The iterator is a safe guard against listeners that 14879 // could mutate the list by calling the various add/remove methods. This prevents 14880 // the array from being modified while we iterate it. 14881 for (OnAttachStateChangeListener listener : listeners) { 14882 listener.onViewAttachedToWindow(this); 14883 } 14884 } 14885 14886 int vis = info.mWindowVisibility; 14887 if (vis != GONE) { 14888 onWindowVisibilityChanged(vis); 14889 } 14890 14891 // Send onVisibilityChanged directly instead of dispatchVisibilityChanged. 14892 // As all views in the subtree will already receive dispatchAttachedToWindow 14893 // traversing the subtree again here is not desired. 14894 onVisibilityChanged(this, visibility); 14895 14896 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { 14897 // If nobody has evaluated the drawable state yet, then do it now. 14898 refreshDrawableState(); 14899 } 14900 needGlobalAttributesUpdate(false); 14901 } 14902 14903 void dispatchDetachedFromWindow() { 14904 AttachInfo info = mAttachInfo; 14905 if (info != null) { 14906 int vis = info.mWindowVisibility; 14907 if (vis != GONE) { 14908 onWindowVisibilityChanged(GONE); 14909 } 14910 } 14911 14912 onDetachedFromWindow(); 14913 onDetachedFromWindowInternal(); 14914 14915 InputMethodManager imm = InputMethodManager.peekInstance(); 14916 if (imm != null) { 14917 imm.onViewDetachedFromWindow(this); 14918 } 14919 14920 ListenerInfo li = mListenerInfo; 14921 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = 14922 li != null ? li.mOnAttachStateChangeListeners : null; 14923 if (listeners != null && listeners.size() > 0) { 14924 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to 14925 // perform the dispatching. The iterator is a safe guard against listeners that 14926 // could mutate the list by calling the various add/remove methods. This prevents 14927 // the array from being modified while we iterate it. 14928 for (OnAttachStateChangeListener listener : listeners) { 14929 listener.onViewDetachedFromWindow(this); 14930 } 14931 } 14932 14933 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) { 14934 mAttachInfo.mScrollContainers.remove(this); 14935 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED; 14936 } 14937 14938 mAttachInfo = null; 14939 if (mOverlay != null) { 14940 mOverlay.getOverlayView().dispatchDetachedFromWindow(); 14941 } 14942 } 14943 14944 /** 14945 * Cancel any deferred high-level input events that were previously posted to the event queue. 14946 * 14947 * <p>Many views post high-level events such as click handlers to the event queue 14948 * to run deferred in order to preserve a desired user experience - clearing visible 14949 * pressed states before executing, etc. This method will abort any events of this nature 14950 * that are currently in flight.</p> 14951 * 14952 * <p>Custom views that generate their own high-level deferred input events should override 14953 * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p> 14954 * 14955 * <p>This will also cancel pending input events for any child views.</p> 14956 * 14957 * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases. 14958 * This will not impact newer events posted after this call that may occur as a result of 14959 * lower-level input events still waiting in the queue. If you are trying to prevent 14960 * double-submitted events for the duration of some sort of asynchronous transaction 14961 * you should also take other steps to protect against unexpected double inputs e.g. calling 14962 * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when 14963 * the transaction completes, tracking already submitted transaction IDs, etc.</p> 14964 */ 14965 public final void cancelPendingInputEvents() { 14966 dispatchCancelPendingInputEvents(); 14967 } 14968 14969 /** 14970 * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight. 14971 * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling. 14972 */ 14973 void dispatchCancelPendingInputEvents() { 14974 mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER; 14975 onCancelPendingInputEvents(); 14976 if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) { 14977 throw new SuperNotCalledException("View " + getClass().getSimpleName() + 14978 " did not call through to super.onCancelPendingInputEvents()"); 14979 } 14980 } 14981 14982 /** 14983 * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or 14984 * a parent view. 14985 * 14986 * <p>This method is responsible for removing any pending high-level input events that were 14987 * posted to the event queue to run later. Custom view classes that post their own deferred 14988 * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or 14989 * {@link android.os.Handler} should override this method, call 14990 * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate. 14991 * </p> 14992 */ 14993 public void onCancelPendingInputEvents() { 14994 removePerformClickCallback(); 14995 cancelLongPress(); 14996 mPrivateFlags3 |= PFLAG3_CALLED_SUPER; 14997 } 14998 14999 /** 15000 * Store this view hierarchy's frozen state into the given container. 15001 * 15002 * @param container The SparseArray in which to save the view's state. 15003 * 15004 * @see #restoreHierarchyState(android.util.SparseArray) 15005 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15006 * @see #onSaveInstanceState() 15007 */ 15008 public void saveHierarchyState(SparseArray<Parcelable> container) { 15009 dispatchSaveInstanceState(container); 15010 } 15011 15012 /** 15013 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for 15014 * this view and its children. May be overridden to modify how freezing happens to a 15015 * view's children; for example, some views may want to not store state for their children. 15016 * 15017 * @param container The SparseArray in which to save the view's state. 15018 * 15019 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15020 * @see #saveHierarchyState(android.util.SparseArray) 15021 * @see #onSaveInstanceState() 15022 */ 15023 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { 15024 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) { 15025 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15026 Parcelable state = onSaveInstanceState(); 15027 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15028 throw new IllegalStateException( 15029 "Derived class did not call super.onSaveInstanceState()"); 15030 } 15031 if (state != null) { 15032 // Log.i("View", "Freezing #" + Integer.toHexString(mID) 15033 // + ": " + state); 15034 container.put(mID, state); 15035 } 15036 } 15037 } 15038 15039 /** 15040 * Hook allowing a view to generate a representation of its internal state 15041 * that can later be used to create a new instance with that same state. 15042 * This state should only contain information that is not persistent or can 15043 * not be reconstructed later. For example, you will never store your 15044 * current position on screen because that will be computed again when a 15045 * new instance of the view is placed in its view hierarchy. 15046 * <p> 15047 * Some examples of things you may store here: the current cursor position 15048 * in a text view (but usually not the text itself since that is stored in a 15049 * content provider or other persistent storage), the currently selected 15050 * item in a list view. 15051 * 15052 * @return Returns a Parcelable object containing the view's current dynamic 15053 * state, or null if there is nothing interesting to save. The 15054 * default implementation returns null. 15055 * @see #onRestoreInstanceState(android.os.Parcelable) 15056 * @see #saveHierarchyState(android.util.SparseArray) 15057 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15058 * @see #setSaveEnabled(boolean) 15059 */ 15060 @CallSuper 15061 protected Parcelable onSaveInstanceState() { 15062 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15063 if (mStartActivityRequestWho != null) { 15064 BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE); 15065 state.mStartActivityRequestWhoSaved = mStartActivityRequestWho; 15066 return state; 15067 } 15068 return BaseSavedState.EMPTY_STATE; 15069 } 15070 15071 /** 15072 * Restore this view hierarchy's frozen state from the given container. 15073 * 15074 * @param container The SparseArray which holds previously frozen states. 15075 * 15076 * @see #saveHierarchyState(android.util.SparseArray) 15077 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15078 * @see #onRestoreInstanceState(android.os.Parcelable) 15079 */ 15080 public void restoreHierarchyState(SparseArray<Parcelable> container) { 15081 dispatchRestoreInstanceState(container); 15082 } 15083 15084 /** 15085 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the 15086 * state for this view and its children. May be overridden to modify how restoring 15087 * happens to a view's children; for example, some views may want to not store state 15088 * for their children. 15089 * 15090 * @param container The SparseArray which holds previously saved state. 15091 * 15092 * @see #dispatchSaveInstanceState(android.util.SparseArray) 15093 * @see #restoreHierarchyState(android.util.SparseArray) 15094 * @see #onRestoreInstanceState(android.os.Parcelable) 15095 */ 15096 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { 15097 if (mID != NO_ID) { 15098 Parcelable state = container.get(mID); 15099 if (state != null) { 15100 // Log.i("View", "Restoreing #" + Integer.toHexString(mID) 15101 // + ": " + state); 15102 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED; 15103 onRestoreInstanceState(state); 15104 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) { 15105 throw new IllegalStateException( 15106 "Derived class did not call super.onRestoreInstanceState()"); 15107 } 15108 } 15109 } 15110 } 15111 15112 /** 15113 * Hook allowing a view to re-apply a representation of its internal state that had previously 15114 * been generated by {@link #onSaveInstanceState}. This function will never be called with a 15115 * null state. 15116 * 15117 * @param state The frozen state that had previously been returned by 15118 * {@link #onSaveInstanceState}. 15119 * 15120 * @see #onSaveInstanceState() 15121 * @see #restoreHierarchyState(android.util.SparseArray) 15122 * @see #dispatchRestoreInstanceState(android.util.SparseArray) 15123 */ 15124 @CallSuper 15125 protected void onRestoreInstanceState(Parcelable state) { 15126 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED; 15127 if (state != null && !(state instanceof AbsSavedState)) { 15128 throw new IllegalArgumentException("Wrong state class, expecting View State but " 15129 + "received " + state.getClass().toString() + " instead. This usually happens " 15130 + "when two views of different type have the same id in the same hierarchy. " 15131 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure " 15132 + "other views do not use the same id."); 15133 } 15134 if (state != null && state instanceof BaseSavedState) { 15135 mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved; 15136 } 15137 } 15138 15139 /** 15140 * <p>Return the time at which the drawing of the view hierarchy started.</p> 15141 * 15142 * @return the drawing start time in milliseconds 15143 */ 15144 public long getDrawingTime() { 15145 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0; 15146 } 15147 15148 /** 15149 * <p>Enables or disables the duplication of the parent's state into this view. When 15150 * duplication is enabled, this view gets its drawable state from its parent rather 15151 * than from its own internal properties.</p> 15152 * 15153 * <p>Note: in the current implementation, setting this property to true after the 15154 * view was added to a ViewGroup might have no effect at all. This property should 15155 * always be used from XML or set to true before adding this view to a ViewGroup.</p> 15156 * 15157 * <p>Note: if this view's parent addStateFromChildren property is enabled and this 15158 * property is enabled, an exception will be thrown.</p> 15159 * 15160 * <p>Note: if the child view uses and updates additional states which are unknown to the 15161 * parent, these states should not be affected by this method.</p> 15162 * 15163 * @param enabled True to enable duplication of the parent's drawable state, false 15164 * to disable it. 15165 * 15166 * @see #getDrawableState() 15167 * @see #isDuplicateParentStateEnabled() 15168 */ 15169 public void setDuplicateParentStateEnabled(boolean enabled) { 15170 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE); 15171 } 15172 15173 /** 15174 * <p>Indicates whether this duplicates its drawable state from its parent.</p> 15175 * 15176 * @return True if this view's drawable state is duplicated from the parent, 15177 * false otherwise 15178 * 15179 * @see #getDrawableState() 15180 * @see #setDuplicateParentStateEnabled(boolean) 15181 */ 15182 public boolean isDuplicateParentStateEnabled() { 15183 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE; 15184 } 15185 15186 /** 15187 * <p>Specifies the type of layer backing this view. The layer can be 15188 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15189 * {@link #LAYER_TYPE_HARDWARE}.</p> 15190 * 15191 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15192 * instance that controls how the layer is composed on screen. The following 15193 * properties of the paint are taken into account when composing the layer:</p> 15194 * <ul> 15195 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15196 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15197 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15198 * </ul> 15199 * 15200 * <p>If this view has an alpha value set to < 1.0 by calling 15201 * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded 15202 * by this view's alpha value.</p> 15203 * 15204 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE}, 15205 * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE} 15206 * for more information on when and how to use layers.</p> 15207 * 15208 * @param layerType The type of layer to use with this view, must be one of 15209 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15210 * {@link #LAYER_TYPE_HARDWARE} 15211 * @param paint The paint used to compose the layer. This argument is optional 15212 * and can be null. It is ignored when the layer type is 15213 * {@link #LAYER_TYPE_NONE} 15214 * 15215 * @see #getLayerType() 15216 * @see #LAYER_TYPE_NONE 15217 * @see #LAYER_TYPE_SOFTWARE 15218 * @see #LAYER_TYPE_HARDWARE 15219 * @see #setAlpha(float) 15220 * 15221 * @attr ref android.R.styleable#View_layerType 15222 */ 15223 public void setLayerType(int layerType, Paint paint) { 15224 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { 15225 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " 15226 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); 15227 } 15228 15229 boolean typeChanged = mRenderNode.setLayerType(layerType); 15230 15231 if (!typeChanged) { 15232 setLayerPaint(paint); 15233 return; 15234 } 15235 15236 // Destroy any previous software drawing cache if needed 15237 if (mLayerType == LAYER_TYPE_SOFTWARE) { 15238 destroyDrawingCache(); 15239 } 15240 15241 mLayerType = layerType; 15242 final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE); 15243 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint); 15244 mRenderNode.setLayerPaint(mLayerPaint); 15245 15246 // draw() behaves differently if we are on a layer, so we need to 15247 // invalidate() here 15248 invalidateParentCaches(); 15249 invalidate(true); 15250 } 15251 15252 /** 15253 * Updates the {@link Paint} object used with the current layer (used only if the current 15254 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint 15255 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time 15256 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to 15257 * ensure that the view gets redrawn immediately. 15258 * 15259 * <p>A layer is associated with an optional {@link android.graphics.Paint} 15260 * instance that controls how the layer is composed on screen. The following 15261 * properties of the paint are taken into account when composing the layer:</p> 15262 * <ul> 15263 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li> 15264 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li> 15265 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li> 15266 * </ul> 15267 * 15268 * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the 15269 * alpha value of the layer's paint is superseded by this view's alpha value.</p> 15270 * 15271 * @param paint The paint used to compose the layer. This argument is optional 15272 * and can be null. It is ignored when the layer type is 15273 * {@link #LAYER_TYPE_NONE} 15274 * 15275 * @see #setLayerType(int, android.graphics.Paint) 15276 */ 15277 public void setLayerPaint(Paint paint) { 15278 int layerType = getLayerType(); 15279 if (layerType != LAYER_TYPE_NONE) { 15280 mLayerPaint = paint == null ? new Paint() : paint; 15281 if (layerType == LAYER_TYPE_HARDWARE) { 15282 if (mRenderNode.setLayerPaint(mLayerPaint)) { 15283 invalidateViewProperty(false, false); 15284 } 15285 } else { 15286 invalidate(); 15287 } 15288 } 15289 } 15290 15291 /** 15292 * Indicates what type of layer is currently associated with this view. By default 15293 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. 15294 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} 15295 * for more information on the different types of layers. 15296 * 15297 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or 15298 * {@link #LAYER_TYPE_HARDWARE} 15299 * 15300 * @see #setLayerType(int, android.graphics.Paint) 15301 * @see #buildLayer() 15302 * @see #LAYER_TYPE_NONE 15303 * @see #LAYER_TYPE_SOFTWARE 15304 * @see #LAYER_TYPE_HARDWARE 15305 */ 15306 public int getLayerType() { 15307 return mLayerType; 15308 } 15309 15310 /** 15311 * Forces this view's layer to be created and this view to be rendered 15312 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE}, 15313 * invoking this method will have no effect. 15314 * 15315 * This method can for instance be used to render a view into its layer before 15316 * starting an animation. If this view is complex, rendering into the layer 15317 * before starting the animation will avoid skipping frames. 15318 * 15319 * @throws IllegalStateException If this view is not attached to a window 15320 * 15321 * @see #setLayerType(int, android.graphics.Paint) 15322 */ 15323 public void buildLayer() { 15324 if (mLayerType == LAYER_TYPE_NONE) return; 15325 15326 final AttachInfo attachInfo = mAttachInfo; 15327 if (attachInfo == null) { 15328 throw new IllegalStateException("This view must be attached to a window first"); 15329 } 15330 15331 if (getWidth() == 0 || getHeight() == 0) { 15332 return; 15333 } 15334 15335 switch (mLayerType) { 15336 case LAYER_TYPE_HARDWARE: 15337 updateDisplayListIfDirty(); 15338 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) { 15339 attachInfo.mHardwareRenderer.buildLayer(mRenderNode); 15340 } 15341 break; 15342 case LAYER_TYPE_SOFTWARE: 15343 buildDrawingCache(true); 15344 break; 15345 } 15346 } 15347 15348 /** 15349 * Destroys all hardware rendering resources. This method is invoked 15350 * when the system needs to reclaim resources. Upon execution of this 15351 * method, you should free any OpenGL resources created by the view. 15352 * 15353 * Note: you <strong>must</strong> call 15354 * <code>super.destroyHardwareResources()</code> when overriding 15355 * this method. 15356 * 15357 * @hide 15358 */ 15359 @CallSuper 15360 protected void destroyHardwareResources() { 15361 // Although the Layer will be destroyed by RenderNode, we want to release 15362 // the staging display list, which is also a signal to RenderNode that it's 15363 // safe to free its copy of the display list as it knows that we will 15364 // push an updated DisplayList if we try to draw again 15365 resetDisplayList(); 15366 } 15367 15368 /** 15369 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call 15370 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a 15371 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when 15372 * the cache is enabled. To benefit from the cache, you must request the drawing cache by 15373 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not 15374 * null.</p> 15375 * 15376 * <p>Enabling the drawing cache is similar to 15377 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware 15378 * acceleration is turned off. When hardware acceleration is turned on, enabling the 15379 * drawing cache has no effect on rendering because the system uses a different mechanism 15380 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even 15381 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)} 15382 * for information on how to enable software and hardware layers.</p> 15383 * 15384 * <p>This API can be used to manually generate 15385 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling 15386 * {@link #getDrawingCache()}.</p> 15387 * 15388 * @param enabled true to enable the drawing cache, false otherwise 15389 * 15390 * @see #isDrawingCacheEnabled() 15391 * @see #getDrawingCache() 15392 * @see #buildDrawingCache() 15393 * @see #setLayerType(int, android.graphics.Paint) 15394 */ 15395 public void setDrawingCacheEnabled(boolean enabled) { 15396 mCachingFailed = false; 15397 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); 15398 } 15399 15400 /** 15401 * <p>Indicates whether the drawing cache is enabled for this view.</p> 15402 * 15403 * @return true if the drawing cache is enabled 15404 * 15405 * @see #setDrawingCacheEnabled(boolean) 15406 * @see #getDrawingCache() 15407 */ 15408 @ViewDebug.ExportedProperty(category = "drawing") 15409 public boolean isDrawingCacheEnabled() { 15410 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED; 15411 } 15412 15413 /** 15414 * Debugging utility which recursively outputs the dirty state of a view and its 15415 * descendants. 15416 * 15417 * @hide 15418 */ 15419 @SuppressWarnings({"UnusedDeclaration"}) 15420 public void outputDirtyFlags(String indent, boolean clear, int clearMask) { 15421 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) + 15422 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" + 15423 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) + 15424 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")"); 15425 if (clear) { 15426 mPrivateFlags &= clearMask; 15427 } 15428 if (this instanceof ViewGroup) { 15429 ViewGroup parent = (ViewGroup) this; 15430 final int count = parent.getChildCount(); 15431 for (int i = 0; i < count; i++) { 15432 final View child = parent.getChildAt(i); 15433 child.outputDirtyFlags(indent + " ", clear, clearMask); 15434 } 15435 } 15436 } 15437 15438 /** 15439 * This method is used by ViewGroup to cause its children to restore or recreate their 15440 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need 15441 * to recreate its own display list, which would happen if it went through the normal 15442 * draw/dispatchDraw mechanisms. 15443 * 15444 * @hide 15445 */ 15446 protected void dispatchGetDisplayList() {} 15447 15448 /** 15449 * A view that is not attached or hardware accelerated cannot create a display list. 15450 * This method checks these conditions and returns the appropriate result. 15451 * 15452 * @return true if view has the ability to create a display list, false otherwise. 15453 * 15454 * @hide 15455 */ 15456 public boolean canHaveDisplayList() { 15457 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null); 15458 } 15459 15460 /** 15461 * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported) 15462 * @hide 15463 */ 15464 @NonNull 15465 public RenderNode updateDisplayListIfDirty() { 15466 final RenderNode renderNode = mRenderNode; 15467 if (!canHaveDisplayList()) { 15468 // can't populate RenderNode, don't try 15469 return renderNode; 15470 } 15471 15472 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 15473 || !renderNode.isValid() 15474 || (mRecreateDisplayList)) { 15475 // Don't need to recreate the display list, just need to tell our 15476 // children to restore/recreate theirs 15477 if (renderNode.isValid() 15478 && !mRecreateDisplayList) { 15479 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 15480 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 15481 dispatchGetDisplayList(); 15482 15483 return renderNode; // no work needed 15484 } 15485 15486 // If we got here, we're recreating it. Mark it as such to ensure that 15487 // we copy in child display lists into ours in drawChild() 15488 mRecreateDisplayList = true; 15489 15490 int width = mRight - mLeft; 15491 int height = mBottom - mTop; 15492 int layerType = getLayerType(); 15493 15494 final DisplayListCanvas canvas = renderNode.start(width, height); 15495 canvas.setHighContrastText(mAttachInfo.mHighContrastText); 15496 15497 try { 15498 if (layerType == LAYER_TYPE_SOFTWARE) { 15499 buildDrawingCache(true); 15500 Bitmap cache = getDrawingCache(true); 15501 if (cache != null) { 15502 canvas.drawBitmap(cache, 0, 0, mLayerPaint); 15503 } 15504 } else { 15505 computeScroll(); 15506 15507 canvas.translate(-mScrollX, -mScrollY); 15508 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 15509 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 15510 15511 // Fast path for layouts with no backgrounds 15512 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 15513 dispatchDraw(canvas); 15514 if (mOverlay != null && !mOverlay.isEmpty()) { 15515 mOverlay.getOverlayView().draw(canvas); 15516 } 15517 } else { 15518 draw(canvas); 15519 } 15520 } 15521 } finally { 15522 renderNode.end(canvas); 15523 setDisplayListProperties(renderNode); 15524 } 15525 } else { 15526 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID; 15527 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 15528 } 15529 return renderNode; 15530 } 15531 15532 private void resetDisplayList() { 15533 if (mRenderNode.isValid()) { 15534 mRenderNode.discardDisplayList(); 15535 } 15536 15537 if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) { 15538 mBackgroundRenderNode.discardDisplayList(); 15539 } 15540 } 15541 15542 /** 15543 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p> 15544 * 15545 * @return A non-scaled bitmap representing this view or null if cache is disabled. 15546 * 15547 * @see #getDrawingCache(boolean) 15548 */ 15549 public Bitmap getDrawingCache() { 15550 return getDrawingCache(false); 15551 } 15552 15553 /** 15554 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap 15555 * is null when caching is disabled. If caching is enabled and the cache is not ready, 15556 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not 15557 * draw from the cache when the cache is enabled. To benefit from the cache, you must 15558 * request the drawing cache by calling this method and draw it on screen if the 15559 * returned bitmap is not null.</p> 15560 * 15561 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 15562 * this method will create a bitmap of the same size as this view. Because this bitmap 15563 * will be drawn scaled by the parent ViewGroup, the result on screen might show 15564 * scaling artifacts. To avoid such artifacts, you should call this method by setting 15565 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 15566 * size than the view. This implies that your application must be able to handle this 15567 * size.</p> 15568 * 15569 * @param autoScale Indicates whether the generated bitmap should be scaled based on 15570 * the current density of the screen when the application is in compatibility 15571 * mode. 15572 * 15573 * @return A bitmap representing this view or null if cache is disabled. 15574 * 15575 * @see #setDrawingCacheEnabled(boolean) 15576 * @see #isDrawingCacheEnabled() 15577 * @see #buildDrawingCache(boolean) 15578 * @see #destroyDrawingCache() 15579 */ 15580 public Bitmap getDrawingCache(boolean autoScale) { 15581 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) { 15582 return null; 15583 } 15584 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) { 15585 buildDrawingCache(autoScale); 15586 } 15587 return autoScale ? mDrawingCache : mUnscaledDrawingCache; 15588 } 15589 15590 /** 15591 * <p>Frees the resources used by the drawing cache. If you call 15592 * {@link #buildDrawingCache()} manually without calling 15593 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 15594 * should cleanup the cache with this method afterwards.</p> 15595 * 15596 * @see #setDrawingCacheEnabled(boolean) 15597 * @see #buildDrawingCache() 15598 * @see #getDrawingCache() 15599 */ 15600 public void destroyDrawingCache() { 15601 if (mDrawingCache != null) { 15602 mDrawingCache.recycle(); 15603 mDrawingCache = null; 15604 } 15605 if (mUnscaledDrawingCache != null) { 15606 mUnscaledDrawingCache.recycle(); 15607 mUnscaledDrawingCache = null; 15608 } 15609 } 15610 15611 /** 15612 * Setting a solid background color for the drawing cache's bitmaps will improve 15613 * performance and memory usage. Note, though that this should only be used if this 15614 * view will always be drawn on top of a solid color. 15615 * 15616 * @param color The background color to use for the drawing cache's bitmap 15617 * 15618 * @see #setDrawingCacheEnabled(boolean) 15619 * @see #buildDrawingCache() 15620 * @see #getDrawingCache() 15621 */ 15622 public void setDrawingCacheBackgroundColor(@ColorInt int color) { 15623 if (color != mDrawingCacheBackgroundColor) { 15624 mDrawingCacheBackgroundColor = color; 15625 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID; 15626 } 15627 } 15628 15629 /** 15630 * @see #setDrawingCacheBackgroundColor(int) 15631 * 15632 * @return The background color to used for the drawing cache's bitmap 15633 */ 15634 @ColorInt 15635 public int getDrawingCacheBackgroundColor() { 15636 return mDrawingCacheBackgroundColor; 15637 } 15638 15639 /** 15640 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p> 15641 * 15642 * @see #buildDrawingCache(boolean) 15643 */ 15644 public void buildDrawingCache() { 15645 buildDrawingCache(false); 15646 } 15647 15648 /** 15649 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p> 15650 * 15651 * <p>If you call {@link #buildDrawingCache()} manually without calling 15652 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you 15653 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p> 15654 * 15655 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled, 15656 * this method will create a bitmap of the same size as this view. Because this bitmap 15657 * will be drawn scaled by the parent ViewGroup, the result on screen might show 15658 * scaling artifacts. To avoid such artifacts, you should call this method by setting 15659 * the auto scaling to true. Doing so, however, will generate a bitmap of a different 15660 * size than the view. This implies that your application must be able to handle this 15661 * size.</p> 15662 * 15663 * <p>You should avoid calling this method when hardware acceleration is enabled. If 15664 * you do not need the drawing cache bitmap, calling this method will increase memory 15665 * usage and cause the view to be rendered in software once, thus negatively impacting 15666 * performance.</p> 15667 * 15668 * @see #getDrawingCache() 15669 * @see #destroyDrawingCache() 15670 */ 15671 public void buildDrawingCache(boolean autoScale) { 15672 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? 15673 mDrawingCache == null : mUnscaledDrawingCache == null)) { 15674 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 15675 Trace.traceBegin(Trace.TRACE_TAG_VIEW, 15676 "buildDrawingCache/SW Layer for " + getClass().getSimpleName()); 15677 } 15678 try { 15679 buildDrawingCacheImpl(autoScale); 15680 } finally { 15681 Trace.traceEnd(Trace.TRACE_TAG_VIEW); 15682 } 15683 } 15684 } 15685 15686 /** 15687 * private, internal implementation of buildDrawingCache, used to enable tracing 15688 */ 15689 private void buildDrawingCacheImpl(boolean autoScale) { 15690 mCachingFailed = false; 15691 15692 int width = mRight - mLeft; 15693 int height = mBottom - mTop; 15694 15695 final AttachInfo attachInfo = mAttachInfo; 15696 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; 15697 15698 if (autoScale && scalingRequired) { 15699 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); 15700 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); 15701 } 15702 15703 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; 15704 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); 15705 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; 15706 15707 final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); 15708 final long drawingCacheSize = 15709 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); 15710 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { 15711 if (width > 0 && height > 0) { 15712 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is" 15713 + " too large to fit into a software layer (or drawing cache), needs " 15714 + projectedBitmapSize + " bytes, only " 15715 + drawingCacheSize + " available"); 15716 } 15717 destroyDrawingCache(); 15718 mCachingFailed = true; 15719 return; 15720 } 15721 15722 boolean clear = true; 15723 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; 15724 15725 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { 15726 Bitmap.Config quality; 15727 if (!opaque) { 15728 // Never pick ARGB_4444 because it looks awful 15729 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case 15730 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { 15731 case DRAWING_CACHE_QUALITY_AUTO: 15732 case DRAWING_CACHE_QUALITY_LOW: 15733 case DRAWING_CACHE_QUALITY_HIGH: 15734 default: 15735 quality = Bitmap.Config.ARGB_8888; 15736 break; 15737 } 15738 } else { 15739 // Optimization for translucent windows 15740 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() 15741 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; 15742 } 15743 15744 // Try to cleanup memory 15745 if (bitmap != null) bitmap.recycle(); 15746 15747 try { 15748 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 15749 width, height, quality); 15750 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); 15751 if (autoScale) { 15752 mDrawingCache = bitmap; 15753 } else { 15754 mUnscaledDrawingCache = bitmap; 15755 } 15756 if (opaque && use32BitCache) bitmap.setHasAlpha(false); 15757 } catch (OutOfMemoryError e) { 15758 // If there is not enough memory to create the bitmap cache, just 15759 // ignore the issue as bitmap caches are not required to draw the 15760 // view hierarchy 15761 if (autoScale) { 15762 mDrawingCache = null; 15763 } else { 15764 mUnscaledDrawingCache = null; 15765 } 15766 mCachingFailed = true; 15767 return; 15768 } 15769 15770 clear = drawingCacheBackgroundColor != 0; 15771 } 15772 15773 Canvas canvas; 15774 if (attachInfo != null) { 15775 canvas = attachInfo.mCanvas; 15776 if (canvas == null) { 15777 canvas = new Canvas(); 15778 } 15779 canvas.setBitmap(bitmap); 15780 // Temporarily clobber the cached Canvas in case one of our children 15781 // is also using a drawing cache. Without this, the children would 15782 // steal the canvas by attaching their own bitmap to it and bad, bad 15783 // thing would happen (invisible views, corrupted drawings, etc.) 15784 attachInfo.mCanvas = null; 15785 } else { 15786 // This case should hopefully never or seldom happen 15787 canvas = new Canvas(bitmap); 15788 } 15789 15790 if (clear) { 15791 bitmap.eraseColor(drawingCacheBackgroundColor); 15792 } 15793 15794 computeScroll(); 15795 final int restoreCount = canvas.save(); 15796 15797 if (autoScale && scalingRequired) { 15798 final float scale = attachInfo.mApplicationScale; 15799 canvas.scale(scale, scale); 15800 } 15801 15802 canvas.translate(-mScrollX, -mScrollY); 15803 15804 mPrivateFlags |= PFLAG_DRAWN; 15805 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || 15806 mLayerType != LAYER_TYPE_NONE) { 15807 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; 15808 } 15809 15810 // Fast path for layouts with no backgrounds 15811 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 15812 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 15813 dispatchDraw(canvas); 15814 if (mOverlay != null && !mOverlay.isEmpty()) { 15815 mOverlay.getOverlayView().draw(canvas); 15816 } 15817 } else { 15818 draw(canvas); 15819 } 15820 15821 canvas.restoreToCount(restoreCount); 15822 canvas.setBitmap(null); 15823 15824 if (attachInfo != null) { 15825 // Restore the cached Canvas for our siblings 15826 attachInfo.mCanvas = canvas; 15827 } 15828 } 15829 15830 /** 15831 * Create a snapshot of the view into a bitmap. We should probably make 15832 * some form of this public, but should think about the API. 15833 */ 15834 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) { 15835 int width = mRight - mLeft; 15836 int height = mBottom - mTop; 15837 15838 final AttachInfo attachInfo = mAttachInfo; 15839 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; 15840 width = (int) ((width * scale) + 0.5f); 15841 height = (int) ((height * scale) + 0.5f); 15842 15843 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), 15844 width > 0 ? width : 1, height > 0 ? height : 1, quality); 15845 if (bitmap == null) { 15846 throw new OutOfMemoryError(); 15847 } 15848 15849 Resources resources = getResources(); 15850 if (resources != null) { 15851 bitmap.setDensity(resources.getDisplayMetrics().densityDpi); 15852 } 15853 15854 Canvas canvas; 15855 if (attachInfo != null) { 15856 canvas = attachInfo.mCanvas; 15857 if (canvas == null) { 15858 canvas = new Canvas(); 15859 } 15860 canvas.setBitmap(bitmap); 15861 // Temporarily clobber the cached Canvas in case one of our children 15862 // is also using a drawing cache. Without this, the children would 15863 // steal the canvas by attaching their own bitmap to it and bad, bad 15864 // things would happen (invisible views, corrupted drawings, etc.) 15865 attachInfo.mCanvas = null; 15866 } else { 15867 // This case should hopefully never or seldom happen 15868 canvas = new Canvas(bitmap); 15869 } 15870 15871 if ((backgroundColor & 0xff000000) != 0) { 15872 bitmap.eraseColor(backgroundColor); 15873 } 15874 15875 computeScroll(); 15876 final int restoreCount = canvas.save(); 15877 canvas.scale(scale, scale); 15878 canvas.translate(-mScrollX, -mScrollY); 15879 15880 // Temporarily remove the dirty mask 15881 int flags = mPrivateFlags; 15882 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 15883 15884 // Fast path for layouts with no backgrounds 15885 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 15886 dispatchDraw(canvas); 15887 if (mOverlay != null && !mOverlay.isEmpty()) { 15888 mOverlay.getOverlayView().draw(canvas); 15889 } 15890 } else { 15891 draw(canvas); 15892 } 15893 15894 mPrivateFlags = flags; 15895 15896 canvas.restoreToCount(restoreCount); 15897 canvas.setBitmap(null); 15898 15899 if (attachInfo != null) { 15900 // Restore the cached Canvas for our siblings 15901 attachInfo.mCanvas = canvas; 15902 } 15903 15904 return bitmap; 15905 } 15906 15907 /** 15908 * Indicates whether this View is currently in edit mode. A View is usually 15909 * in edit mode when displayed within a developer tool. For instance, if 15910 * this View is being drawn by a visual user interface builder, this method 15911 * should return true. 15912 * 15913 * Subclasses should check the return value of this method to provide 15914 * different behaviors if their normal behavior might interfere with the 15915 * host environment. For instance: the class spawns a thread in its 15916 * constructor, the drawing code relies on device-specific features, etc. 15917 * 15918 * This method is usually checked in the drawing code of custom widgets. 15919 * 15920 * @return True if this View is in edit mode, false otherwise. 15921 */ 15922 public boolean isInEditMode() { 15923 return false; 15924 } 15925 15926 /** 15927 * If the View draws content inside its padding and enables fading edges, 15928 * it needs to support padding offsets. Padding offsets are added to the 15929 * fading edges to extend the length of the fade so that it covers pixels 15930 * drawn inside the padding. 15931 * 15932 * Subclasses of this class should override this method if they need 15933 * to draw content inside the padding. 15934 * 15935 * @return True if padding offset must be applied, false otherwise. 15936 * 15937 * @see #getLeftPaddingOffset() 15938 * @see #getRightPaddingOffset() 15939 * @see #getTopPaddingOffset() 15940 * @see #getBottomPaddingOffset() 15941 * 15942 * @since CURRENT 15943 */ 15944 protected boolean isPaddingOffsetRequired() { 15945 return false; 15946 } 15947 15948 /** 15949 * Amount by which to extend the left fading region. Called only when 15950 * {@link #isPaddingOffsetRequired()} returns true. 15951 * 15952 * @return The left padding offset in pixels. 15953 * 15954 * @see #isPaddingOffsetRequired() 15955 * 15956 * @since CURRENT 15957 */ 15958 protected int getLeftPaddingOffset() { 15959 return 0; 15960 } 15961 15962 /** 15963 * Amount by which to extend the right fading region. Called only when 15964 * {@link #isPaddingOffsetRequired()} returns true. 15965 * 15966 * @return The right padding offset in pixels. 15967 * 15968 * @see #isPaddingOffsetRequired() 15969 * 15970 * @since CURRENT 15971 */ 15972 protected int getRightPaddingOffset() { 15973 return 0; 15974 } 15975 15976 /** 15977 * Amount by which to extend the top fading region. Called only when 15978 * {@link #isPaddingOffsetRequired()} returns true. 15979 * 15980 * @return The top padding offset in pixels. 15981 * 15982 * @see #isPaddingOffsetRequired() 15983 * 15984 * @since CURRENT 15985 */ 15986 protected int getTopPaddingOffset() { 15987 return 0; 15988 } 15989 15990 /** 15991 * Amount by which to extend the bottom fading region. Called only when 15992 * {@link #isPaddingOffsetRequired()} returns true. 15993 * 15994 * @return The bottom padding offset in pixels. 15995 * 15996 * @see #isPaddingOffsetRequired() 15997 * 15998 * @since CURRENT 15999 */ 16000 protected int getBottomPaddingOffset() { 16001 return 0; 16002 } 16003 16004 /** 16005 * @hide 16006 * @param offsetRequired 16007 */ 16008 protected int getFadeTop(boolean offsetRequired) { 16009 int top = mPaddingTop; 16010 if (offsetRequired) top += getTopPaddingOffset(); 16011 return top; 16012 } 16013 16014 /** 16015 * @hide 16016 * @param offsetRequired 16017 */ 16018 protected int getFadeHeight(boolean offsetRequired) { 16019 int padding = mPaddingTop; 16020 if (offsetRequired) padding += getTopPaddingOffset(); 16021 return mBottom - mTop - mPaddingBottom - padding; 16022 } 16023 16024 /** 16025 * <p>Indicates whether this view is attached to a hardware accelerated 16026 * window or not.</p> 16027 * 16028 * <p>Even if this method returns true, it does not mean that every call 16029 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware 16030 * accelerated {@link android.graphics.Canvas}. For instance, if this view 16031 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its 16032 * window is hardware accelerated, 16033 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely 16034 * return false, and this method will return true.</p> 16035 * 16036 * @return True if the view is attached to a window and the window is 16037 * hardware accelerated; false in any other case. 16038 */ 16039 @ViewDebug.ExportedProperty(category = "drawing") 16040 public boolean isHardwareAccelerated() { 16041 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated; 16042 } 16043 16044 /** 16045 * Sets a rectangular area on this view to which the view will be clipped 16046 * when it is drawn. Setting the value to null will remove the clip bounds 16047 * and the view will draw normally, using its full bounds. 16048 * 16049 * @param clipBounds The rectangular area, in the local coordinates of 16050 * this view, to which future drawing operations will be clipped. 16051 */ 16052 public void setClipBounds(Rect clipBounds) { 16053 if (clipBounds == mClipBounds 16054 || (clipBounds != null && clipBounds.equals(mClipBounds))) { 16055 return; 16056 } 16057 if (clipBounds != null) { 16058 if (mClipBounds == null) { 16059 mClipBounds = new Rect(clipBounds); 16060 } else { 16061 mClipBounds.set(clipBounds); 16062 } 16063 } else { 16064 mClipBounds = null; 16065 } 16066 mRenderNode.setClipBounds(mClipBounds); 16067 invalidateViewProperty(false, false); 16068 } 16069 16070 /** 16071 * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}. 16072 * 16073 * @return A copy of the current clip bounds if clip bounds are set, 16074 * otherwise null. 16075 */ 16076 public Rect getClipBounds() { 16077 return (mClipBounds != null) ? new Rect(mClipBounds) : null; 16078 } 16079 16080 16081 /** 16082 * Populates an output rectangle with the clip bounds of the view, 16083 * returning {@code true} if successful or {@code false} if the view's 16084 * clip bounds are {@code null}. 16085 * 16086 * @param outRect rectangle in which to place the clip bounds of the view 16087 * @return {@code true} if successful or {@code false} if the view's 16088 * clip bounds are {@code null} 16089 */ 16090 public boolean getClipBounds(Rect outRect) { 16091 if (mClipBounds != null) { 16092 outRect.set(mClipBounds); 16093 return true; 16094 } 16095 return false; 16096 } 16097 16098 /** 16099 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common 16100 * case of an active Animation being run on the view. 16101 */ 16102 private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, 16103 Animation a, boolean scalingRequired) { 16104 Transformation invalidationTransform; 16105 final int flags = parent.mGroupFlags; 16106 final boolean initialized = a.isInitialized(); 16107 if (!initialized) { 16108 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); 16109 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); 16110 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); 16111 onAnimationStart(); 16112 } 16113 16114 final Transformation t = parent.getChildTransformation(); 16115 boolean more = a.getTransformation(drawingTime, t, 1f); 16116 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { 16117 if (parent.mInvalidationTransformation == null) { 16118 parent.mInvalidationTransformation = new Transformation(); 16119 } 16120 invalidationTransform = parent.mInvalidationTransformation; 16121 a.getTransformation(drawingTime, invalidationTransform, 1f); 16122 } else { 16123 invalidationTransform = t; 16124 } 16125 16126 if (more) { 16127 if (!a.willChangeBounds()) { 16128 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) == 16129 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) { 16130 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED; 16131 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) { 16132 // The child need to draw an animation, potentially offscreen, so 16133 // make sure we do not cancel invalidate requests 16134 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16135 parent.invalidate(mLeft, mTop, mRight, mBottom); 16136 } 16137 } else { 16138 if (parent.mInvalidateRegion == null) { 16139 parent.mInvalidateRegion = new RectF(); 16140 } 16141 final RectF region = parent.mInvalidateRegion; 16142 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, 16143 invalidationTransform); 16144 16145 // The child need to draw an animation, potentially offscreen, so 16146 // make sure we do not cancel invalidate requests 16147 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; 16148 16149 final int left = mLeft + (int) region.left; 16150 final int top = mTop + (int) region.top; 16151 parent.invalidate(left, top, left + (int) (region.width() + .5f), 16152 top + (int) (region.height() + .5f)); 16153 } 16154 } 16155 return more; 16156 } 16157 16158 /** 16159 * This method is called by getDisplayList() when a display list is recorded for a View. 16160 * It pushes any properties to the RenderNode that aren't managed by the RenderNode. 16161 */ 16162 void setDisplayListProperties(RenderNode renderNode) { 16163 if (renderNode != null) { 16164 renderNode.setHasOverlappingRendering(hasOverlappingRendering()); 16165 renderNode.setClipToBounds(mParent instanceof ViewGroup 16166 && ((ViewGroup) mParent).getClipChildren()); 16167 16168 float alpha = 1; 16169 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags & 16170 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16171 ViewGroup parentVG = (ViewGroup) mParent; 16172 final Transformation t = parentVG.getChildTransformation(); 16173 if (parentVG.getChildStaticTransformation(this, t)) { 16174 final int transformType = t.getTransformationType(); 16175 if (transformType != Transformation.TYPE_IDENTITY) { 16176 if ((transformType & Transformation.TYPE_ALPHA) != 0) { 16177 alpha = t.getAlpha(); 16178 } 16179 if ((transformType & Transformation.TYPE_MATRIX) != 0) { 16180 renderNode.setStaticMatrix(t.getMatrix()); 16181 } 16182 } 16183 } 16184 } 16185 if (mTransformationInfo != null) { 16186 alpha *= getFinalAlpha(); 16187 if (alpha < 1) { 16188 final int multipliedAlpha = (int) (255 * alpha); 16189 if (onSetAlpha(multipliedAlpha)) { 16190 alpha = 1; 16191 } 16192 } 16193 renderNode.setAlpha(alpha); 16194 } else if (alpha < 1) { 16195 renderNode.setAlpha(alpha); 16196 } 16197 } 16198 } 16199 16200 /** 16201 * This method is called by ViewGroup.drawChild() to have each child view draw itself. 16202 * 16203 * This is where the View specializes rendering behavior based on layer type, 16204 * and hardware acceleration. 16205 */ 16206 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { 16207 final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated(); 16208 /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList. 16209 * 16210 * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't 16211 * HW accelerated, it can't handle drawing RenderNodes. 16212 */ 16213 boolean drawingWithRenderNode = mAttachInfo != null 16214 && mAttachInfo.mHardwareAccelerated 16215 && hardwareAcceleratedCanvas; 16216 16217 boolean more = false; 16218 final boolean childHasIdentityMatrix = hasIdentityMatrix(); 16219 final int parentFlags = parent.mGroupFlags; 16220 16221 if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) { 16222 parent.getChildTransformation().clear(); 16223 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16224 } 16225 16226 Transformation transformToApply = null; 16227 boolean concatMatrix = false; 16228 final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired; 16229 final Animation a = getAnimation(); 16230 if (a != null) { 16231 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); 16232 concatMatrix = a.willChangeTransformationMatrix(); 16233 if (concatMatrix) { 16234 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16235 } 16236 transformToApply = parent.getChildTransformation(); 16237 } else { 16238 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) { 16239 // No longer animating: clear out old animation matrix 16240 mRenderNode.setAnimationMatrix(null); 16241 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; 16242 } 16243 if (!drawingWithRenderNode 16244 && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) { 16245 final Transformation t = parent.getChildTransformation(); 16246 final boolean hasTransform = parent.getChildStaticTransformation(this, t); 16247 if (hasTransform) { 16248 final int transformType = t.getTransformationType(); 16249 transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null; 16250 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0; 16251 } 16252 } 16253 } 16254 16255 concatMatrix |= !childHasIdentityMatrix; 16256 16257 // Sets the flag as early as possible to allow draw() implementations 16258 // to call invalidate() successfully when doing animations 16259 mPrivateFlags |= PFLAG_DRAWN; 16260 16261 if (!concatMatrix && 16262 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS | 16263 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN && 16264 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) && 16265 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) { 16266 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED; 16267 return more; 16268 } 16269 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED; 16270 16271 if (hardwareAcceleratedCanvas) { 16272 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but 16273 // retain the flag's value temporarily in the mRecreateDisplayList flag 16274 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0; 16275 mPrivateFlags &= ~PFLAG_INVALIDATED; 16276 } 16277 16278 RenderNode renderNode = null; 16279 Bitmap cache = null; 16280 int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local 16281 if (layerType == LAYER_TYPE_SOFTWARE 16282 || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) { 16283 // If not drawing with RenderNode, treat HW layers as SW 16284 layerType = LAYER_TYPE_SOFTWARE; 16285 buildDrawingCache(true); 16286 cache = getDrawingCache(true); 16287 } 16288 16289 if (drawingWithRenderNode) { 16290 // Delay getting the display list until animation-driven alpha values are 16291 // set up and possibly passed on to the view 16292 renderNode = updateDisplayListIfDirty(); 16293 if (!renderNode.isValid()) { 16294 // Uncommon, but possible. If a view is removed from the hierarchy during the call 16295 // to getDisplayList(), the display list will be marked invalid and we should not 16296 // try to use it again. 16297 renderNode = null; 16298 drawingWithRenderNode = false; 16299 } 16300 } 16301 16302 int sx = 0; 16303 int sy = 0; 16304 if (!drawingWithRenderNode) { 16305 computeScroll(); 16306 sx = mScrollX; 16307 sy = mScrollY; 16308 } 16309 16310 final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode; 16311 final boolean offsetForScroll = cache == null && !drawingWithRenderNode; 16312 16313 int restoreTo = -1; 16314 if (!drawingWithRenderNode || transformToApply != null) { 16315 restoreTo = canvas.save(); 16316 } 16317 if (offsetForScroll) { 16318 canvas.translate(mLeft - sx, mTop - sy); 16319 } else { 16320 if (!drawingWithRenderNode) { 16321 canvas.translate(mLeft, mTop); 16322 } 16323 if (scalingRequired) { 16324 if (drawingWithRenderNode) { 16325 // TODO: Might not need this if we put everything inside the DL 16326 restoreTo = canvas.save(); 16327 } 16328 // mAttachInfo cannot be null, otherwise scalingRequired == false 16329 final float scale = 1.0f / mAttachInfo.mApplicationScale; 16330 canvas.scale(scale, scale); 16331 } 16332 } 16333 16334 float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha()); 16335 if (transformToApply != null 16336 || alpha < 1 16337 || !hasIdentityMatrix() 16338 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 16339 if (transformToApply != null || !childHasIdentityMatrix) { 16340 int transX = 0; 16341 int transY = 0; 16342 16343 if (offsetForScroll) { 16344 transX = -sx; 16345 transY = -sy; 16346 } 16347 16348 if (transformToApply != null) { 16349 if (concatMatrix) { 16350 if (drawingWithRenderNode) { 16351 renderNode.setAnimationMatrix(transformToApply.getMatrix()); 16352 } else { 16353 // Undo the scroll translation, apply the transformation matrix, 16354 // then redo the scroll translate to get the correct result. 16355 canvas.translate(-transX, -transY); 16356 canvas.concat(transformToApply.getMatrix()); 16357 canvas.translate(transX, transY); 16358 } 16359 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16360 } 16361 16362 float transformAlpha = transformToApply.getAlpha(); 16363 if (transformAlpha < 1) { 16364 alpha *= transformAlpha; 16365 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16366 } 16367 } 16368 16369 if (!childHasIdentityMatrix && !drawingWithRenderNode) { 16370 canvas.translate(-transX, -transY); 16371 canvas.concat(getMatrix()); 16372 canvas.translate(transX, transY); 16373 } 16374 } 16375 16376 // Deal with alpha if it is or used to be <1 16377 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { 16378 if (alpha < 1) { 16379 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; 16380 } else { 16381 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; 16382 } 16383 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; 16384 if (!drawingWithDrawingCache) { 16385 final int multipliedAlpha = (int) (255 * alpha); 16386 if (!onSetAlpha(multipliedAlpha)) { 16387 if (drawingWithRenderNode) { 16388 renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); 16389 } else if (layerType == LAYER_TYPE_NONE) { 16390 canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), 16391 multipliedAlpha); 16392 } 16393 } else { 16394 // Alpha is handled by the child directly, clobber the layer's alpha 16395 mPrivateFlags |= PFLAG_ALPHA_SET; 16396 } 16397 } 16398 } 16399 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 16400 onSetAlpha(255); 16401 mPrivateFlags &= ~PFLAG_ALPHA_SET; 16402 } 16403 16404 if (!drawingWithRenderNode) { 16405 // apply clips directly, since RenderNode won't do it for this draw 16406 if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) { 16407 if (offsetForScroll) { 16408 canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight()); 16409 } else { 16410 if (!scalingRequired || cache == null) { 16411 canvas.clipRect(0, 0, getWidth(), getHeight()); 16412 } else { 16413 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); 16414 } 16415 } 16416 } 16417 16418 if (mClipBounds != null) { 16419 // clip bounds ignore scroll 16420 canvas.clipRect(mClipBounds); 16421 } 16422 } 16423 16424 if (!drawingWithDrawingCache) { 16425 if (drawingWithRenderNode) { 16426 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16427 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 16428 } else { 16429 // Fast path for layouts with no backgrounds 16430 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 16431 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16432 dispatchDraw(canvas); 16433 } else { 16434 draw(canvas); 16435 } 16436 } 16437 } else if (cache != null) { 16438 mPrivateFlags &= ~PFLAG_DIRTY_MASK; 16439 if (layerType == LAYER_TYPE_NONE) { 16440 // no layer paint, use temporary paint to draw bitmap 16441 Paint cachePaint = parent.mCachePaint; 16442 if (cachePaint == null) { 16443 cachePaint = new Paint(); 16444 cachePaint.setDither(false); 16445 parent.mCachePaint = cachePaint; 16446 } 16447 cachePaint.setAlpha((int) (alpha * 255)); 16448 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); 16449 } else { 16450 // use layer paint to draw the bitmap, merging the two alphas, but also restore 16451 int layerPaintAlpha = mLayerPaint.getAlpha(); 16452 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha)); 16453 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint); 16454 mLayerPaint.setAlpha(layerPaintAlpha); 16455 } 16456 } 16457 16458 if (restoreTo >= 0) { 16459 canvas.restoreToCount(restoreTo); 16460 } 16461 16462 if (a != null && !more) { 16463 if (!hardwareAcceleratedCanvas && !a.getFillAfter()) { 16464 onSetAlpha(255); 16465 } 16466 parent.finishAnimatingView(this, a); 16467 } 16468 16469 if (more && hardwareAcceleratedCanvas) { 16470 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { 16471 // alpha animations should cause the child to recreate its display list 16472 invalidate(true); 16473 } 16474 } 16475 16476 mRecreateDisplayList = false; 16477 16478 return more; 16479 } 16480 16481 /** 16482 * Manually render this view (and all of its children) to the given Canvas. 16483 * The view must have already done a full layout before this function is 16484 * called. When implementing a view, implement 16485 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 16486 * If you do need to override this method, call the superclass version. 16487 * 16488 * @param canvas The Canvas to which the View is rendered. 16489 */ 16490 @CallSuper 16491 public void draw(Canvas canvas) { 16492 final int privateFlags = mPrivateFlags; 16493 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE && 16494 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 16495 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; 16496 16497 /* 16498 * Draw traversal performs several drawing steps which must be executed 16499 * in the appropriate order: 16500 * 16501 * 1. Draw the background 16502 * 2. If necessary, save the canvas' layers to prepare for fading 16503 * 3. Draw view's content 16504 * 4. Draw children 16505 * 5. If necessary, draw the fading edges and restore layers 16506 * 6. Draw decorations (scrollbars for instance) 16507 */ 16508 16509 // Step 1, draw the background, if needed 16510 int saveCount; 16511 16512 if (!dirtyOpaque) { 16513 drawBackground(canvas); 16514 } 16515 16516 // skip step 2 & 5 if possible (common case) 16517 final int viewFlags = mViewFlags; 16518 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; 16519 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; 16520 if (!verticalEdges && !horizontalEdges) { 16521 // Step 3, draw the content 16522 if (!dirtyOpaque) onDraw(canvas); 16523 16524 // Step 4, draw the children 16525 dispatchDraw(canvas); 16526 16527 // Overlay is part of the content and draws beneath Foreground 16528 if (mOverlay != null && !mOverlay.isEmpty()) { 16529 mOverlay.getOverlayView().dispatchDraw(canvas); 16530 } 16531 16532 // Step 6, draw decorations (foreground, scrollbars) 16533 onDrawForeground(canvas); 16534 16535 // we're done... 16536 return; 16537 } 16538 16539 /* 16540 * Here we do the full fledged routine... 16541 * (this is an uncommon case where speed matters less, 16542 * this is why we repeat some of the tests that have been 16543 * done above) 16544 */ 16545 16546 boolean drawTop = false; 16547 boolean drawBottom = false; 16548 boolean drawLeft = false; 16549 boolean drawRight = false; 16550 16551 float topFadeStrength = 0.0f; 16552 float bottomFadeStrength = 0.0f; 16553 float leftFadeStrength = 0.0f; 16554 float rightFadeStrength = 0.0f; 16555 16556 // Step 2, save the canvas' layers 16557 int paddingLeft = mPaddingLeft; 16558 16559 final boolean offsetRequired = isPaddingOffsetRequired(); 16560 if (offsetRequired) { 16561 paddingLeft += getLeftPaddingOffset(); 16562 } 16563 16564 int left = mScrollX + paddingLeft; 16565 int right = left + mRight - mLeft - mPaddingRight - paddingLeft; 16566 int top = mScrollY + getFadeTop(offsetRequired); 16567 int bottom = top + getFadeHeight(offsetRequired); 16568 16569 if (offsetRequired) { 16570 right += getRightPaddingOffset(); 16571 bottom += getBottomPaddingOffset(); 16572 } 16573 16574 final ScrollabilityCache scrollabilityCache = mScrollCache; 16575 final float fadeHeight = scrollabilityCache.fadingEdgeLength; 16576 int length = (int) fadeHeight; 16577 16578 // clip the fade length if top and bottom fades overlap 16579 // overlapping fades produce odd-looking artifacts 16580 if (verticalEdges && (top + length > bottom - length)) { 16581 length = (bottom - top) / 2; 16582 } 16583 16584 // also clip horizontal fades if necessary 16585 if (horizontalEdges && (left + length > right - length)) { 16586 length = (right - left) / 2; 16587 } 16588 16589 if (verticalEdges) { 16590 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); 16591 drawTop = topFadeStrength * fadeHeight > 1.0f; 16592 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); 16593 drawBottom = bottomFadeStrength * fadeHeight > 1.0f; 16594 } 16595 16596 if (horizontalEdges) { 16597 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); 16598 drawLeft = leftFadeStrength * fadeHeight > 1.0f; 16599 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); 16600 drawRight = rightFadeStrength * fadeHeight > 1.0f; 16601 } 16602 16603 saveCount = canvas.getSaveCount(); 16604 16605 int solidColor = getSolidColor(); 16606 if (solidColor == 0) { 16607 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; 16608 16609 if (drawTop) { 16610 canvas.saveLayer(left, top, right, top + length, null, flags); 16611 } 16612 16613 if (drawBottom) { 16614 canvas.saveLayer(left, bottom - length, right, bottom, null, flags); 16615 } 16616 16617 if (drawLeft) { 16618 canvas.saveLayer(left, top, left + length, bottom, null, flags); 16619 } 16620 16621 if (drawRight) { 16622 canvas.saveLayer(right - length, top, right, bottom, null, flags); 16623 } 16624 } else { 16625 scrollabilityCache.setFadeColor(solidColor); 16626 } 16627 16628 // Step 3, draw the content 16629 if (!dirtyOpaque) onDraw(canvas); 16630 16631 // Step 4, draw the children 16632 dispatchDraw(canvas); 16633 16634 // Step 5, draw the fade effect and restore layers 16635 final Paint p = scrollabilityCache.paint; 16636 final Matrix matrix = scrollabilityCache.matrix; 16637 final Shader fade = scrollabilityCache.shader; 16638 16639 if (drawTop) { 16640 matrix.setScale(1, fadeHeight * topFadeStrength); 16641 matrix.postTranslate(left, top); 16642 fade.setLocalMatrix(matrix); 16643 p.setShader(fade); 16644 canvas.drawRect(left, top, right, top + length, p); 16645 } 16646 16647 if (drawBottom) { 16648 matrix.setScale(1, fadeHeight * bottomFadeStrength); 16649 matrix.postRotate(180); 16650 matrix.postTranslate(left, bottom); 16651 fade.setLocalMatrix(matrix); 16652 p.setShader(fade); 16653 canvas.drawRect(left, bottom - length, right, bottom, p); 16654 } 16655 16656 if (drawLeft) { 16657 matrix.setScale(1, fadeHeight * leftFadeStrength); 16658 matrix.postRotate(-90); 16659 matrix.postTranslate(left, top); 16660 fade.setLocalMatrix(matrix); 16661 p.setShader(fade); 16662 canvas.drawRect(left, top, left + length, bottom, p); 16663 } 16664 16665 if (drawRight) { 16666 matrix.setScale(1, fadeHeight * rightFadeStrength); 16667 matrix.postRotate(90); 16668 matrix.postTranslate(right, top); 16669 fade.setLocalMatrix(matrix); 16670 p.setShader(fade); 16671 canvas.drawRect(right - length, top, right, bottom, p); 16672 } 16673 16674 canvas.restoreToCount(saveCount); 16675 16676 // Overlay is part of the content and draws beneath Foreground 16677 if (mOverlay != null && !mOverlay.isEmpty()) { 16678 mOverlay.getOverlayView().dispatchDraw(canvas); 16679 } 16680 16681 // Step 6, draw decorations (foreground, scrollbars) 16682 onDrawForeground(canvas); 16683 } 16684 16685 /** 16686 * Draws the background onto the specified canvas. 16687 * 16688 * @param canvas Canvas on which to draw the background 16689 */ 16690 private void drawBackground(Canvas canvas) { 16691 final Drawable background = mBackground; 16692 if (background == null) { 16693 return; 16694 } 16695 16696 setBackgroundBounds(); 16697 16698 // Attempt to use a display list if requested. 16699 if (canvas.isHardwareAccelerated() && mAttachInfo != null 16700 && mAttachInfo.mHardwareRenderer != null) { 16701 mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); 16702 16703 final RenderNode renderNode = mBackgroundRenderNode; 16704 if (renderNode != null && renderNode.isValid()) { 16705 setBackgroundRenderNodeProperties(renderNode); 16706 ((DisplayListCanvas) canvas).drawRenderNode(renderNode); 16707 return; 16708 } 16709 } 16710 16711 final int scrollX = mScrollX; 16712 final int scrollY = mScrollY; 16713 if ((scrollX | scrollY) == 0) { 16714 background.draw(canvas); 16715 } else { 16716 canvas.translate(scrollX, scrollY); 16717 background.draw(canvas); 16718 canvas.translate(-scrollX, -scrollY); 16719 } 16720 } 16721 16722 /** 16723 * Sets the correct background bounds and rebuilds the outline, if needed. 16724 * <p/> 16725 * This is called by LayoutLib. 16726 */ 16727 void setBackgroundBounds() { 16728 if (mBackgroundSizeChanged && mBackground != null) { 16729 mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop); 16730 mBackgroundSizeChanged = false; 16731 rebuildOutline(); 16732 } 16733 } 16734 16735 private void setBackgroundRenderNodeProperties(RenderNode renderNode) { 16736 renderNode.setTranslationX(mScrollX); 16737 renderNode.setTranslationY(mScrollY); 16738 } 16739 16740 /** 16741 * Creates a new display list or updates the existing display list for the 16742 * specified Drawable. 16743 * 16744 * @param drawable Drawable for which to create a display list 16745 * @param renderNode Existing RenderNode, or {@code null} 16746 * @return A valid display list for the specified drawable 16747 */ 16748 private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { 16749 if (renderNode == null) { 16750 renderNode = RenderNode.create(drawable.getClass().getName(), this); 16751 } 16752 16753 final Rect bounds = drawable.getBounds(); 16754 final int width = bounds.width(); 16755 final int height = bounds.height(); 16756 final DisplayListCanvas canvas = renderNode.start(width, height); 16757 16758 // Reverse left/top translation done by drawable canvas, which will 16759 // instead be applied by rendernode's LTRB bounds below. This way, the 16760 // drawable's bounds match with its rendernode bounds and its content 16761 // will lie within those bounds in the rendernode tree. 16762 canvas.translate(-bounds.left, -bounds.top); 16763 16764 try { 16765 drawable.draw(canvas); 16766 } finally { 16767 renderNode.end(canvas); 16768 } 16769 16770 // Set up drawable properties that are view-independent. 16771 renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom); 16772 renderNode.setProjectBackwards(drawable.isProjected()); 16773 renderNode.setProjectionReceiver(true); 16774 renderNode.setClipToBounds(false); 16775 return renderNode; 16776 } 16777 16778 /** 16779 * Returns the overlay for this view, creating it if it does not yet exist. 16780 * Adding drawables to the overlay will cause them to be displayed whenever 16781 * the view itself is redrawn. Objects in the overlay should be actively 16782 * managed: remove them when they should not be displayed anymore. The 16783 * overlay will always have the same size as its host view. 16784 * 16785 * <p>Note: Overlays do not currently work correctly with {@link 16786 * SurfaceView} or {@link TextureView}; contents in overlays for these 16787 * types of views may not display correctly.</p> 16788 * 16789 * @return The ViewOverlay object for this view. 16790 * @see ViewOverlay 16791 */ 16792 public ViewOverlay getOverlay() { 16793 if (mOverlay == null) { 16794 mOverlay = new ViewOverlay(mContext, this); 16795 } 16796 return mOverlay; 16797 } 16798 16799 /** 16800 * Override this if your view is known to always be drawn on top of a solid color background, 16801 * and needs to draw fading edges. Returning a non-zero color enables the view system to 16802 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha 16803 * should be set to 0xFF. 16804 * 16805 * @see #setVerticalFadingEdgeEnabled(boolean) 16806 * @see #setHorizontalFadingEdgeEnabled(boolean) 16807 * 16808 * @return The known solid color background for this view, or 0 if the color may vary 16809 */ 16810 @ViewDebug.ExportedProperty(category = "drawing") 16811 @ColorInt 16812 public int getSolidColor() { 16813 return 0; 16814 } 16815 16816 /** 16817 * Build a human readable string representation of the specified view flags. 16818 * 16819 * @param flags the view flags to convert to a string 16820 * @return a String representing the supplied flags 16821 */ 16822 private static String printFlags(int flags) { 16823 String output = ""; 16824 int numFlags = 0; 16825 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) { 16826 output += "TAKES_FOCUS"; 16827 numFlags++; 16828 } 16829 16830 switch (flags & VISIBILITY_MASK) { 16831 case INVISIBLE: 16832 if (numFlags > 0) { 16833 output += " "; 16834 } 16835 output += "INVISIBLE"; 16836 // USELESS HERE numFlags++; 16837 break; 16838 case GONE: 16839 if (numFlags > 0) { 16840 output += " "; 16841 } 16842 output += "GONE"; 16843 // USELESS HERE numFlags++; 16844 break; 16845 default: 16846 break; 16847 } 16848 return output; 16849 } 16850 16851 /** 16852 * Build a human readable string representation of the specified private 16853 * view flags. 16854 * 16855 * @param privateFlags the private view flags to convert to a string 16856 * @return a String representing the supplied flags 16857 */ 16858 private static String printPrivateFlags(int privateFlags) { 16859 String output = ""; 16860 int numFlags = 0; 16861 16862 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) { 16863 output += "WANTS_FOCUS"; 16864 numFlags++; 16865 } 16866 16867 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) { 16868 if (numFlags > 0) { 16869 output += " "; 16870 } 16871 output += "FOCUSED"; 16872 numFlags++; 16873 } 16874 16875 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) { 16876 if (numFlags > 0) { 16877 output += " "; 16878 } 16879 output += "SELECTED"; 16880 numFlags++; 16881 } 16882 16883 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) { 16884 if (numFlags > 0) { 16885 output += " "; 16886 } 16887 output += "IS_ROOT_NAMESPACE"; 16888 numFlags++; 16889 } 16890 16891 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) { 16892 if (numFlags > 0) { 16893 output += " "; 16894 } 16895 output += "HAS_BOUNDS"; 16896 numFlags++; 16897 } 16898 16899 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) { 16900 if (numFlags > 0) { 16901 output += " "; 16902 } 16903 output += "DRAWN"; 16904 // USELESS HERE numFlags++; 16905 } 16906 return output; 16907 } 16908 16909 /** 16910 * <p>Indicates whether or not this view's layout will be requested during 16911 * the next hierarchy layout pass.</p> 16912 * 16913 * @return true if the layout will be forced during next layout pass 16914 */ 16915 public boolean isLayoutRequested() { 16916 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 16917 } 16918 16919 /** 16920 * Indicates whether or not this view has requested a partial layout that 16921 * may not affect its size or position within its parent. This state will be reset 16922 * the next time this view is laid out. 16923 * 16924 * @return true if partial layout has been requested 16925 */ 16926 public final boolean isPartialLayoutRequested() { 16927 return (mPrivateFlags3 & PFLAG3_PARTIAL_LAYOUT_REQUESTED) 16928 == PFLAG3_PARTIAL_LAYOUT_REQUESTED; 16929 } 16930 16931 /** 16932 * Returns true if this view's {@link ViewGroup.LayoutParams LayoutParams} changed 16933 * since the last time this view was successfully laid out. Typically this happens as a 16934 * result of a call to {@link #setLayoutParams(LayoutParams)}. 16935 * 16936 * @return true if this view's LayoutParams changed since last layout. 16937 */ 16938 public final boolean didLayoutParamsChange() { 16939 if (sLayoutParamsAlwaysChanged) { 16940 return true; 16941 } 16942 return (mPrivateFlags3 & PFLAG3_LAYOUT_PARAMS_CHANGED) == PFLAG3_LAYOUT_PARAMS_CHANGED; 16943 } 16944 16945 /** 16946 * Return true if o is a ViewGroup that is laying out using optical bounds. 16947 * @hide 16948 */ 16949 public static boolean isLayoutModeOptical(Object o) { 16950 return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical(); 16951 } 16952 16953 private boolean setOpticalFrame(int left, int top, int right, int bottom) { 16954 Insets parentInsets = mParent instanceof View ? 16955 ((View) mParent).getOpticalInsets() : Insets.NONE; 16956 Insets childInsets = getOpticalInsets(); 16957 return setFrame( 16958 left + parentInsets.left - childInsets.left, 16959 top + parentInsets.top - childInsets.top, 16960 right + parentInsets.left + childInsets.right, 16961 bottom + parentInsets.top + childInsets.bottom); 16962 } 16963 16964 /** 16965 * Assign a size and position to a view and all of its 16966 * descendants 16967 * 16968 * <p>This is the second phase of the layout mechanism. 16969 * (The first is measuring). In this phase, each parent calls 16970 * layout on all of its children to position them. 16971 * This is typically done using the child measurements 16972 * that were stored in the measure pass().</p> 16973 * 16974 * <p>Derived classes should not override this method. 16975 * Derived classes with children should override 16976 * onLayout. In that method, they should 16977 * call layout on each of their children.</p> 16978 * 16979 * @param l Left position, relative to parent 16980 * @param t Top position, relative to parent 16981 * @param r Right position, relative to parent 16982 * @param b Bottom position, relative to parent 16983 */ 16984 @SuppressWarnings({"unchecked"}) 16985 public void layout(int l, int t, int r, int b) { 16986 if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) { 16987 onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec); 16988 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 16989 } 16990 16991 int oldL = mLeft; 16992 int oldT = mTop; 16993 int oldB = mBottom; 16994 int oldR = mRight; 16995 16996 boolean changed = isLayoutModeOptical(mParent) ? 16997 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b); 16998 16999 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) { 17000 onLayout(changed, l, t, r, b); 17001 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; 17002 mPrivateFlags3 &= ~PFLAG3_LAYOUT_PARAMS_CHANGED; 17003 17004 ListenerInfo li = mListenerInfo; 17005 if (li != null && li.mOnLayoutChangeListeners != null) { 17006 ArrayList<OnLayoutChangeListener> listenersCopy = 17007 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); 17008 int numListeners = listenersCopy.size(); 17009 for (int i = 0; i < numListeners; ++i) { 17010 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); 17011 } 17012 } 17013 } 17014 17015 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; 17016 mPrivateFlags3 &= ~PFLAG3_PARTIAL_LAYOUT_REQUESTED; 17017 mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; 17018 } 17019 17020 /** 17021 * Called from layout when this view should 17022 * assign a size and position to each of its children. 17023 * 17024 * Derived classes with children should override 17025 * this method and call layout on each of 17026 * their children. 17027 * @param changed This is a new size or position for this view 17028 * @param left Left position, relative to parent 17029 * @param top Top position, relative to parent 17030 * @param right Right position, relative to parent 17031 * @param bottom Bottom position, relative to parent 17032 */ 17033 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 17034 } 17035 17036 /** 17037 * Assign a size and position to this view. 17038 * 17039 * This is called from layout. 17040 * 17041 * @param left Left position, relative to parent 17042 * @param top Top position, relative to parent 17043 * @param right Right position, relative to parent 17044 * @param bottom Bottom position, relative to parent 17045 * @return true if the new size and position are different than the 17046 * previous ones 17047 * {@hide} 17048 */ 17049 protected boolean setFrame(int left, int top, int right, int bottom) { 17050 boolean changed = false; 17051 17052 if (DBG) { 17053 Log.d("View", this + " View.setFrame(" + left + "," + top + "," 17054 + right + "," + bottom + ")"); 17055 } 17056 17057 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) { 17058 changed = true; 17059 17060 // Remember our drawn bit 17061 int drawn = mPrivateFlags & PFLAG_DRAWN; 17062 17063 int oldWidth = mRight - mLeft; 17064 int oldHeight = mBottom - mTop; 17065 int newWidth = right - left; 17066 int newHeight = bottom - top; 17067 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); 17068 17069 // Invalidate our old position 17070 invalidate(sizeChanged); 17071 17072 mLeft = left; 17073 mTop = top; 17074 mRight = right; 17075 mBottom = bottom; 17076 mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom); 17077 17078 mPrivateFlags |= PFLAG_HAS_BOUNDS; 17079 17080 17081 if (sizeChanged) { 17082 sizeChange(newWidth, newHeight, oldWidth, oldHeight); 17083 } 17084 17085 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) { 17086 // If we are visible, force the DRAWN bit to on so that 17087 // this invalidate will go through (at least to our parent). 17088 // This is because someone may have invalidated this view 17089 // before this call to setFrame came in, thereby clearing 17090 // the DRAWN bit. 17091 mPrivateFlags |= PFLAG_DRAWN; 17092 invalidate(sizeChanged); 17093 // parent display list may need to be recreated based on a change in the bounds 17094 // of any child 17095 invalidateParentCaches(); 17096 } 17097 17098 // Reset drawn bit to original value (invalidate turns it off) 17099 mPrivateFlags |= drawn; 17100 17101 mBackgroundSizeChanged = true; 17102 if (mForegroundInfo != null) { 17103 mForegroundInfo.mBoundsChanged = true; 17104 } 17105 17106 notifySubtreeAccessibilityStateChangedIfNeeded(); 17107 } 17108 return changed; 17109 } 17110 17111 /** 17112 * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}. 17113 * @hide 17114 */ 17115 public void setLeftTopRightBottom(int left, int top, int right, int bottom) { 17116 setFrame(left, top, right, bottom); 17117 } 17118 17119 private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) { 17120 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight); 17121 if (mOverlay != null) { 17122 mOverlay.getOverlayView().setRight(newWidth); 17123 mOverlay.getOverlayView().setBottom(newHeight); 17124 } 17125 rebuildOutline(); 17126 } 17127 17128 /** 17129 * Finalize inflating a view from XML. This is called as the last phase 17130 * of inflation, after all child views have been added. 17131 * 17132 * <p>Even if the subclass overrides onFinishInflate, they should always be 17133 * sure to call the super method, so that we get called. 17134 */ 17135 @CallSuper 17136 protected void onFinishInflate() { 17137 } 17138 17139 /** 17140 * Returns the resources associated with this view. 17141 * 17142 * @return Resources object. 17143 */ 17144 public Resources getResources() { 17145 return mResources; 17146 } 17147 17148 /** 17149 * Invalidates the specified Drawable. 17150 * 17151 * @param drawable the drawable to invalidate 17152 */ 17153 @Override 17154 public void invalidateDrawable(@NonNull Drawable drawable) { 17155 if (verifyDrawable(drawable)) { 17156 final Rect dirty = drawable.getDirtyBounds(); 17157 final int scrollX = mScrollX; 17158 final int scrollY = mScrollY; 17159 17160 invalidate(dirty.left + scrollX, dirty.top + scrollY, 17161 dirty.right + scrollX, dirty.bottom + scrollY); 17162 rebuildOutline(); 17163 } 17164 } 17165 17166 /** 17167 * Schedules an action on a drawable to occur at a specified time. 17168 * 17169 * @param who the recipient of the action 17170 * @param what the action to run on the drawable 17171 * @param when the time at which the action must occur. Uses the 17172 * {@link SystemClock#uptimeMillis} timebase. 17173 */ 17174 @Override 17175 public void scheduleDrawable(Drawable who, Runnable what, long when) { 17176 if (verifyDrawable(who) && what != null) { 17177 final long delay = when - SystemClock.uptimeMillis(); 17178 if (mAttachInfo != null) { 17179 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed( 17180 Choreographer.CALLBACK_ANIMATION, what, who, 17181 Choreographer.subtractFrameDelay(delay)); 17182 } else { 17183 // Postpone the runnable until we know 17184 // on which thread it needs to run. 17185 getRunQueue().postDelayed(what, delay); 17186 } 17187 } 17188 } 17189 17190 /** 17191 * Cancels a scheduled action on a drawable. 17192 * 17193 * @param who the recipient of the action 17194 * @param what the action to cancel 17195 */ 17196 @Override 17197 public void unscheduleDrawable(Drawable who, Runnable what) { 17198 if (verifyDrawable(who) && what != null) { 17199 if (mAttachInfo != null) { 17200 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17201 Choreographer.CALLBACK_ANIMATION, what, who); 17202 } 17203 getRunQueue().removeCallbacks(what); 17204 } 17205 } 17206 17207 /** 17208 * Unschedule any events associated with the given Drawable. This can be 17209 * used when selecting a new Drawable into a view, so that the previous 17210 * one is completely unscheduled. 17211 * 17212 * @param who The Drawable to unschedule. 17213 * 17214 * @see #drawableStateChanged 17215 */ 17216 public void unscheduleDrawable(Drawable who) { 17217 if (mAttachInfo != null && who != null) { 17218 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks( 17219 Choreographer.CALLBACK_ANIMATION, null, who); 17220 } 17221 } 17222 17223 /** 17224 * Resolve the Drawables depending on the layout direction. This is implicitly supposing 17225 * that the View directionality can and will be resolved before its Drawables. 17226 * 17227 * Will call {@link View#onResolveDrawables} when resolution is done. 17228 * 17229 * @hide 17230 */ 17231 protected void resolveDrawables() { 17232 // Drawables resolution may need to happen before resolving the layout direction (which is 17233 // done only during the measure() call). 17234 // If the layout direction is not resolved yet, we cannot resolve the Drawables except in 17235 // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT. 17236 // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or 17237 // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout 17238 // direction to be resolved as its resolved value will be the same as its raw value. 17239 if (!isLayoutDirectionResolved() && 17240 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) { 17241 return; 17242 } 17243 17244 final int layoutDirection = isLayoutDirectionResolved() ? 17245 getLayoutDirection() : getRawLayoutDirection(); 17246 17247 if (mBackground != null) { 17248 mBackground.setLayoutDirection(layoutDirection); 17249 } 17250 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17251 mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection); 17252 } 17253 mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED; 17254 onResolveDrawables(layoutDirection); 17255 } 17256 17257 boolean areDrawablesResolved() { 17258 return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED; 17259 } 17260 17261 /** 17262 * Called when layout direction has been resolved. 17263 * 17264 * The default implementation does nothing. 17265 * 17266 * @param layoutDirection The resolved layout direction. 17267 * 17268 * @see #LAYOUT_DIRECTION_LTR 17269 * @see #LAYOUT_DIRECTION_RTL 17270 * 17271 * @hide 17272 */ 17273 public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { 17274 } 17275 17276 /** 17277 * @hide 17278 */ 17279 protected void resetResolvedDrawables() { 17280 resetResolvedDrawablesInternal(); 17281 } 17282 17283 void resetResolvedDrawablesInternal() { 17284 mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED; 17285 } 17286 17287 /** 17288 * If your view subclass is displaying its own Drawable objects, it should 17289 * override this function and return true for any Drawable it is 17290 * displaying. This allows animations for those drawables to be 17291 * scheduled. 17292 * 17293 * <p>Be sure to call through to the super class when overriding this 17294 * function. 17295 * 17296 * @param who The Drawable to verify. Return true if it is one you are 17297 * displaying, else return the result of calling through to the 17298 * super class. 17299 * 17300 * @return boolean If true than the Drawable is being displayed in the 17301 * view; else false and it is not allowed to animate. 17302 * 17303 * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 17304 * @see #drawableStateChanged() 17305 */ 17306 @CallSuper 17307 protected boolean verifyDrawable(Drawable who) { 17308 return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who) 17309 || (mForegroundInfo != null && mForegroundInfo.mDrawable == who); 17310 } 17311 17312 /** 17313 * This function is called whenever the state of the view changes in such 17314 * a way that it impacts the state of drawables being shown. 17315 * <p> 17316 * If the View has a StateListAnimator, it will also be called to run necessary state 17317 * change animations. 17318 * <p> 17319 * Be sure to call through to the superclass when overriding this function. 17320 * 17321 * @see Drawable#setState(int[]) 17322 */ 17323 @CallSuper 17324 protected void drawableStateChanged() { 17325 final int[] state = getDrawableState(); 17326 boolean changed = false; 17327 17328 final Drawable bg = mBackground; 17329 if (bg != null && bg.isStateful()) { 17330 changed |= bg.setState(state); 17331 } 17332 17333 final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 17334 if (fg != null && fg.isStateful()) { 17335 changed |= fg.setState(state); 17336 } 17337 17338 if (mScrollCache != null) { 17339 final Drawable scrollBar = mScrollCache.scrollBar; 17340 if (scrollBar != null && scrollBar.isStateful()) { 17341 changed |= scrollBar.setState(state) 17342 && mScrollCache.state != ScrollabilityCache.OFF; 17343 } 17344 } 17345 17346 if (mStateListAnimator != null) { 17347 mStateListAnimator.setState(state); 17348 } 17349 17350 if (changed) { 17351 invalidate(); 17352 } 17353 } 17354 17355 /** 17356 * This function is called whenever the view hotspot changes and needs to 17357 * be propagated to drawables or child views managed by the view. 17358 * <p> 17359 * Dispatching to child views is handled by 17360 * {@link #dispatchDrawableHotspotChanged(float, float)}. 17361 * <p> 17362 * Be sure to call through to the superclass when overriding this function. 17363 * 17364 * @param x hotspot x coordinate 17365 * @param y hotspot y coordinate 17366 */ 17367 @CallSuper 17368 public void drawableHotspotChanged(float x, float y) { 17369 if (mBackground != null) { 17370 mBackground.setHotspot(x, y); 17371 } 17372 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17373 mForegroundInfo.mDrawable.setHotspot(x, y); 17374 } 17375 17376 dispatchDrawableHotspotChanged(x, y); 17377 } 17378 17379 /** 17380 * Dispatches drawableHotspotChanged to all of this View's children. 17381 * 17382 * @param x hotspot x coordinate 17383 * @param y hotspot y coordinate 17384 * @see #drawableHotspotChanged(float, float) 17385 */ 17386 public void dispatchDrawableHotspotChanged(float x, float y) { 17387 } 17388 17389 /** 17390 * Call this to force a view to update its drawable state. This will cause 17391 * drawableStateChanged to be called on this view. Views that are interested 17392 * in the new state should call getDrawableState. 17393 * 17394 * @see #drawableStateChanged 17395 * @see #getDrawableState 17396 */ 17397 public void refreshDrawableState() { 17398 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; 17399 drawableStateChanged(); 17400 17401 ViewParent parent = mParent; 17402 if (parent != null) { 17403 parent.childDrawableStateChanged(this); 17404 } 17405 } 17406 17407 /** 17408 * Return an array of resource IDs of the drawable states representing the 17409 * current state of the view. 17410 * 17411 * @return The current drawable state 17412 * 17413 * @see Drawable#setState(int[]) 17414 * @see #drawableStateChanged() 17415 * @see #onCreateDrawableState(int) 17416 */ 17417 public final int[] getDrawableState() { 17418 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) { 17419 return mDrawableState; 17420 } else { 17421 mDrawableState = onCreateDrawableState(0); 17422 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY; 17423 return mDrawableState; 17424 } 17425 } 17426 17427 /** 17428 * Generate the new {@link android.graphics.drawable.Drawable} state for 17429 * this view. This is called by the view 17430 * system when the cached Drawable state is determined to be invalid. To 17431 * retrieve the current state, you should use {@link #getDrawableState}. 17432 * 17433 * @param extraSpace if non-zero, this is the number of extra entries you 17434 * would like in the returned array in which you can place your own 17435 * states. 17436 * 17437 * @return Returns an array holding the current {@link Drawable} state of 17438 * the view. 17439 * 17440 * @see #mergeDrawableStates(int[], int[]) 17441 */ 17442 protected int[] onCreateDrawableState(int extraSpace) { 17443 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE && 17444 mParent instanceof View) { 17445 return ((View) mParent).onCreateDrawableState(extraSpace); 17446 } 17447 17448 int[] drawableState; 17449 17450 int privateFlags = mPrivateFlags; 17451 17452 int viewStateIndex = 0; 17453 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED; 17454 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED; 17455 if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED; 17456 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED; 17457 if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED; 17458 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED; 17459 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested && 17460 ThreadedRenderer.isAvailable()) { 17461 // This is set if HW acceleration is requested, even if the current 17462 // process doesn't allow it. This is just to allow app preview 17463 // windows to better match their app. 17464 viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED; 17465 } 17466 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED; 17467 17468 final int privateFlags2 = mPrivateFlags2; 17469 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) { 17470 viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT; 17471 } 17472 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) { 17473 viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED; 17474 } 17475 17476 drawableState = StateSet.get(viewStateIndex); 17477 17478 //noinspection ConstantIfStatement 17479 if (false) { 17480 Log.i("View", "drawableStateIndex=" + viewStateIndex); 17481 Log.i("View", toString() 17482 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0) 17483 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED) 17484 + " fo=" + hasFocus() 17485 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0) 17486 + " wf=" + hasWindowFocus() 17487 + ": " + Arrays.toString(drawableState)); 17488 } 17489 17490 if (extraSpace == 0) { 17491 return drawableState; 17492 } 17493 17494 final int[] fullState; 17495 if (drawableState != null) { 17496 fullState = new int[drawableState.length + extraSpace]; 17497 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length); 17498 } else { 17499 fullState = new int[extraSpace]; 17500 } 17501 17502 return fullState; 17503 } 17504 17505 /** 17506 * Merge your own state values in <var>additionalState</var> into the base 17507 * state values <var>baseState</var> that were returned by 17508 * {@link #onCreateDrawableState(int)}. 17509 * 17510 * @param baseState The base state values returned by 17511 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your 17512 * own additional state values. 17513 * 17514 * @param additionalState The additional state values you would like 17515 * added to <var>baseState</var>; this array is not modified. 17516 * 17517 * @return As a convenience, the <var>baseState</var> array you originally 17518 * passed into the function is returned. 17519 * 17520 * @see #onCreateDrawableState(int) 17521 */ 17522 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) { 17523 final int N = baseState.length; 17524 int i = N - 1; 17525 while (i >= 0 && baseState[i] == 0) { 17526 i--; 17527 } 17528 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length); 17529 return baseState; 17530 } 17531 17532 /** 17533 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()} 17534 * on all Drawable objects associated with this view. 17535 * <p> 17536 * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator 17537 * attached to this view. 17538 */ 17539 @CallSuper 17540 public void jumpDrawablesToCurrentState() { 17541 if (mBackground != null) { 17542 mBackground.jumpToCurrentState(); 17543 } 17544 if (mStateListAnimator != null) { 17545 mStateListAnimator.jumpToCurrentState(); 17546 } 17547 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) { 17548 mForegroundInfo.mDrawable.jumpToCurrentState(); 17549 } 17550 } 17551 17552 /** 17553 * Sets the background color for this view. 17554 * @param color the color of the background 17555 */ 17556 @RemotableViewMethod 17557 public void setBackgroundColor(@ColorInt int color) { 17558 if (mBackground instanceof ColorDrawable) { 17559 ((ColorDrawable) mBackground.mutate()).setColor(color); 17560 computeOpaqueFlags(); 17561 mBackgroundResource = 0; 17562 } else { 17563 setBackground(new ColorDrawable(color)); 17564 } 17565 } 17566 17567 /** 17568 * Set the background to a given resource. The resource should refer to 17569 * a Drawable object or 0 to remove the background. 17570 * @param resid The identifier of the resource. 17571 * 17572 * @attr ref android.R.styleable#View_background 17573 */ 17574 @RemotableViewMethod 17575 public void setBackgroundResource(@DrawableRes int resid) { 17576 if (resid != 0 && resid == mBackgroundResource) { 17577 return; 17578 } 17579 17580 Drawable d = null; 17581 if (resid != 0) { 17582 d = mContext.getDrawable(resid); 17583 } 17584 setBackground(d); 17585 17586 mBackgroundResource = resid; 17587 } 17588 17589 /** 17590 * Set the background to a given Drawable, or remove the background. If the 17591 * background has padding, this View's padding is set to the background's 17592 * padding. However, when a background is removed, this View's padding isn't 17593 * touched. If setting the padding is desired, please use 17594 * {@link #setPadding(int, int, int, int)}. 17595 * 17596 * @param background The Drawable to use as the background, or null to remove the 17597 * background 17598 */ 17599 public void setBackground(Drawable background) { 17600 //noinspection deprecation 17601 setBackgroundDrawable(background); 17602 } 17603 17604 /** 17605 * @deprecated use {@link #setBackground(Drawable)} instead 17606 */ 17607 @Deprecated 17608 public void setBackgroundDrawable(Drawable background) { 17609 computeOpaqueFlags(); 17610 17611 if (background == mBackground) { 17612 return; 17613 } 17614 17615 boolean requestLayout = false; 17616 17617 mBackgroundResource = 0; 17618 17619 /* 17620 * Regardless of whether we're setting a new background or not, we want 17621 * to clear the previous drawable. 17622 */ 17623 if (mBackground != null) { 17624 mBackground.setCallback(null); 17625 unscheduleDrawable(mBackground); 17626 } 17627 17628 if (background != null) { 17629 Rect padding = sThreadLocal.get(); 17630 if (padding == null) { 17631 padding = new Rect(); 17632 sThreadLocal.set(padding); 17633 } 17634 resetResolvedDrawablesInternal(); 17635 background.setLayoutDirection(getLayoutDirection()); 17636 if (background.getPadding(padding)) { 17637 resetResolvedPaddingInternal(); 17638 switch (background.getLayoutDirection()) { 17639 case LAYOUT_DIRECTION_RTL: 17640 mUserPaddingLeftInitial = padding.right; 17641 mUserPaddingRightInitial = padding.left; 17642 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom); 17643 break; 17644 case LAYOUT_DIRECTION_LTR: 17645 default: 17646 mUserPaddingLeftInitial = padding.left; 17647 mUserPaddingRightInitial = padding.right; 17648 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); 17649 } 17650 mLeftPaddingDefined = false; 17651 mRightPaddingDefined = false; 17652 } 17653 17654 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or 17655 // if it has a different minimum size, we should layout again 17656 if (mBackground == null 17657 || mBackground.getMinimumHeight() != background.getMinimumHeight() 17658 || mBackground.getMinimumWidth() != background.getMinimumWidth()) { 17659 requestLayout = true; 17660 } 17661 17662 background.setCallback(this); 17663 if (background.isStateful()) { 17664 background.setState(getDrawableState()); 17665 } 17666 background.setVisible(getVisibility() == VISIBLE, false); 17667 mBackground = background; 17668 17669 applyBackgroundTint(); 17670 17671 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 17672 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 17673 requestLayout = true; 17674 } 17675 } else { 17676 /* Remove the background */ 17677 mBackground = null; 17678 if ((mViewFlags & WILL_NOT_DRAW) != 0 17679 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) { 17680 mPrivateFlags |= PFLAG_SKIP_DRAW; 17681 } 17682 17683 /* 17684 * When the background is set, we try to apply its padding to this 17685 * View. When the background is removed, we don't touch this View's 17686 * padding. This is noted in the Javadocs. Hence, we don't need to 17687 * requestLayout(), the invalidate() below is sufficient. 17688 */ 17689 17690 // The old background's minimum size could have affected this 17691 // View's layout, so let's requestLayout 17692 requestLayout = true; 17693 } 17694 17695 computeOpaqueFlags(); 17696 17697 if (requestLayout) { 17698 requestLayout(); 17699 } 17700 17701 mBackgroundSizeChanged = true; 17702 invalidate(true); 17703 } 17704 17705 /** 17706 * Gets the background drawable 17707 * 17708 * @return The drawable used as the background for this view, if any. 17709 * 17710 * @see #setBackground(Drawable) 17711 * 17712 * @attr ref android.R.styleable#View_background 17713 */ 17714 public Drawable getBackground() { 17715 return mBackground; 17716 } 17717 17718 /** 17719 * Applies a tint to the background drawable. Does not modify the current tint 17720 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 17721 * <p> 17722 * Subsequent calls to {@link #setBackground(Drawable)} will automatically 17723 * mutate the drawable and apply the specified tint and tint mode using 17724 * {@link Drawable#setTintList(ColorStateList)}. 17725 * 17726 * @param tint the tint to apply, may be {@code null} to clear tint 17727 * 17728 * @attr ref android.R.styleable#View_backgroundTint 17729 * @see #getBackgroundTintList() 17730 * @see Drawable#setTintList(ColorStateList) 17731 */ 17732 public void setBackgroundTintList(@Nullable ColorStateList tint) { 17733 if (mBackgroundTint == null) { 17734 mBackgroundTint = new TintInfo(); 17735 } 17736 mBackgroundTint.mTintList = tint; 17737 mBackgroundTint.mHasTintList = true; 17738 17739 applyBackgroundTint(); 17740 } 17741 17742 /** 17743 * Return the tint applied to the background drawable, if specified. 17744 * 17745 * @return the tint applied to the background drawable 17746 * @attr ref android.R.styleable#View_backgroundTint 17747 * @see #setBackgroundTintList(ColorStateList) 17748 */ 17749 @Nullable 17750 public ColorStateList getBackgroundTintList() { 17751 return mBackgroundTint != null ? mBackgroundTint.mTintList : null; 17752 } 17753 17754 /** 17755 * Specifies the blending mode used to apply the tint specified by 17756 * {@link #setBackgroundTintList(ColorStateList)}} to the background 17757 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 17758 * 17759 * @param tintMode the blending mode used to apply the tint, may be 17760 * {@code null} to clear tint 17761 * @attr ref android.R.styleable#View_backgroundTintMode 17762 * @see #getBackgroundTintMode() 17763 * @see Drawable#setTintMode(PorterDuff.Mode) 17764 */ 17765 public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) { 17766 if (mBackgroundTint == null) { 17767 mBackgroundTint = new TintInfo(); 17768 } 17769 mBackgroundTint.mTintMode = tintMode; 17770 mBackgroundTint.mHasTintMode = true; 17771 17772 applyBackgroundTint(); 17773 } 17774 17775 /** 17776 * Return the blending mode used to apply the tint to the background 17777 * drawable, if specified. 17778 * 17779 * @return the blending mode used to apply the tint to the background 17780 * drawable 17781 * @attr ref android.R.styleable#View_backgroundTintMode 17782 * @see #setBackgroundTintMode(PorterDuff.Mode) 17783 */ 17784 @Nullable 17785 public PorterDuff.Mode getBackgroundTintMode() { 17786 return mBackgroundTint != null ? mBackgroundTint.mTintMode : null; 17787 } 17788 17789 private void applyBackgroundTint() { 17790 if (mBackground != null && mBackgroundTint != null) { 17791 final TintInfo tintInfo = mBackgroundTint; 17792 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 17793 mBackground = mBackground.mutate(); 17794 17795 if (tintInfo.mHasTintList) { 17796 mBackground.setTintList(tintInfo.mTintList); 17797 } 17798 17799 if (tintInfo.mHasTintMode) { 17800 mBackground.setTintMode(tintInfo.mTintMode); 17801 } 17802 17803 // The drawable (or one of its children) may not have been 17804 // stateful before applying the tint, so let's try again. 17805 if (mBackground.isStateful()) { 17806 mBackground.setState(getDrawableState()); 17807 } 17808 } 17809 } 17810 } 17811 17812 /** 17813 * Returns the drawable used as the foreground of this View. The 17814 * foreground drawable, if non-null, is always drawn on top of the view's content. 17815 * 17816 * @return a Drawable or null if no foreground was set 17817 * 17818 * @see #onDrawForeground(Canvas) 17819 */ 17820 public Drawable getForeground() { 17821 return mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 17822 } 17823 17824 /** 17825 * Supply a Drawable that is to be rendered on top of all of the content in the view. 17826 * 17827 * @param foreground the Drawable to be drawn on top of the children 17828 * 17829 * @attr ref android.R.styleable#View_foreground 17830 */ 17831 public void setForeground(Drawable foreground) { 17832 if (mForegroundInfo == null) { 17833 if (foreground == null) { 17834 // Nothing to do. 17835 return; 17836 } 17837 mForegroundInfo = new ForegroundInfo(); 17838 } 17839 17840 if (foreground == mForegroundInfo.mDrawable) { 17841 // Nothing to do 17842 return; 17843 } 17844 17845 if (mForegroundInfo.mDrawable != null) { 17846 mForegroundInfo.mDrawable.setCallback(null); 17847 unscheduleDrawable(mForegroundInfo.mDrawable); 17848 } 17849 17850 mForegroundInfo.mDrawable = foreground; 17851 mForegroundInfo.mBoundsChanged = true; 17852 if (foreground != null) { 17853 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) { 17854 mPrivateFlags &= ~PFLAG_SKIP_DRAW; 17855 } 17856 foreground.setCallback(this); 17857 foreground.setLayoutDirection(getLayoutDirection()); 17858 if (foreground.isStateful()) { 17859 foreground.setState(getDrawableState()); 17860 } 17861 applyForegroundTint(); 17862 } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) { 17863 mPrivateFlags |= PFLAG_SKIP_DRAW; 17864 } 17865 requestLayout(); 17866 invalidate(); 17867 } 17868 17869 /** 17870 * Magic bit used to support features of framework-internal window decor implementation details. 17871 * This used to live exclusively in FrameLayout. 17872 * 17873 * @return true if the foreground should draw inside the padding region or false 17874 * if it should draw inset by the view's padding 17875 * @hide internal use only; only used by FrameLayout and internal screen layouts. 17876 */ 17877 public boolean isForegroundInsidePadding() { 17878 return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true; 17879 } 17880 17881 /** 17882 * Describes how the foreground is positioned. 17883 * 17884 * @return foreground gravity. 17885 * 17886 * @see #setForegroundGravity(int) 17887 * 17888 * @attr ref android.R.styleable#View_foregroundGravity 17889 */ 17890 public int getForegroundGravity() { 17891 return mForegroundInfo != null ? mForegroundInfo.mGravity 17892 : Gravity.START | Gravity.TOP; 17893 } 17894 17895 /** 17896 * Describes how the foreground is positioned. Defaults to START and TOP. 17897 * 17898 * @param gravity see {@link android.view.Gravity} 17899 * 17900 * @see #getForegroundGravity() 17901 * 17902 * @attr ref android.R.styleable#View_foregroundGravity 17903 */ 17904 public void setForegroundGravity(int gravity) { 17905 if (mForegroundInfo == null) { 17906 mForegroundInfo = new ForegroundInfo(); 17907 } 17908 17909 if (mForegroundInfo.mGravity != gravity) { 17910 if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) { 17911 gravity |= Gravity.START; 17912 } 17913 17914 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) { 17915 gravity |= Gravity.TOP; 17916 } 17917 17918 mForegroundInfo.mGravity = gravity; 17919 requestLayout(); 17920 } 17921 } 17922 17923 /** 17924 * Applies a tint to the foreground drawable. Does not modify the current tint 17925 * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. 17926 * <p> 17927 * Subsequent calls to {@link #setForeground(Drawable)} will automatically 17928 * mutate the drawable and apply the specified tint and tint mode using 17929 * {@link Drawable#setTintList(ColorStateList)}. 17930 * 17931 * @param tint the tint to apply, may be {@code null} to clear tint 17932 * 17933 * @attr ref android.R.styleable#View_foregroundTint 17934 * @see #getForegroundTintList() 17935 * @see Drawable#setTintList(ColorStateList) 17936 */ 17937 public void setForegroundTintList(@Nullable ColorStateList tint) { 17938 if (mForegroundInfo == null) { 17939 mForegroundInfo = new ForegroundInfo(); 17940 } 17941 if (mForegroundInfo.mTintInfo == null) { 17942 mForegroundInfo.mTintInfo = new TintInfo(); 17943 } 17944 mForegroundInfo.mTintInfo.mTintList = tint; 17945 mForegroundInfo.mTintInfo.mHasTintList = true; 17946 17947 applyForegroundTint(); 17948 } 17949 17950 /** 17951 * Return the tint applied to the foreground drawable, if specified. 17952 * 17953 * @return the tint applied to the foreground drawable 17954 * @attr ref android.R.styleable#View_foregroundTint 17955 * @see #setForegroundTintList(ColorStateList) 17956 */ 17957 @Nullable 17958 public ColorStateList getForegroundTintList() { 17959 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 17960 ? mForegroundInfo.mTintInfo.mTintList : null; 17961 } 17962 17963 /** 17964 * Specifies the blending mode used to apply the tint specified by 17965 * {@link #setForegroundTintList(ColorStateList)}} to the background 17966 * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}. 17967 * 17968 * @param tintMode the blending mode used to apply the tint, may be 17969 * {@code null} to clear tint 17970 * @attr ref android.R.styleable#View_foregroundTintMode 17971 * @see #getForegroundTintMode() 17972 * @see Drawable#setTintMode(PorterDuff.Mode) 17973 */ 17974 public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) { 17975 if (mForegroundInfo == null) { 17976 mForegroundInfo = new ForegroundInfo(); 17977 } 17978 if (mForegroundInfo.mTintInfo == null) { 17979 mForegroundInfo.mTintInfo = new TintInfo(); 17980 } 17981 mForegroundInfo.mTintInfo.mTintMode = tintMode; 17982 mForegroundInfo.mTintInfo.mHasTintMode = true; 17983 17984 applyForegroundTint(); 17985 } 17986 17987 /** 17988 * Return the blending mode used to apply the tint to the foreground 17989 * drawable, if specified. 17990 * 17991 * @return the blending mode used to apply the tint to the foreground 17992 * drawable 17993 * @attr ref android.R.styleable#View_foregroundTintMode 17994 * @see #setForegroundTintMode(PorterDuff.Mode) 17995 */ 17996 @Nullable 17997 public PorterDuff.Mode getForegroundTintMode() { 17998 return mForegroundInfo != null && mForegroundInfo.mTintInfo != null 17999 ? mForegroundInfo.mTintInfo.mTintMode : null; 18000 } 18001 18002 private void applyForegroundTint() { 18003 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 18004 && mForegroundInfo.mTintInfo != null) { 18005 final TintInfo tintInfo = mForegroundInfo.mTintInfo; 18006 if (tintInfo.mHasTintList || tintInfo.mHasTintMode) { 18007 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate(); 18008 18009 if (tintInfo.mHasTintList) { 18010 mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList); 18011 } 18012 18013 if (tintInfo.mHasTintMode) { 18014 mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode); 18015 } 18016 18017 // The drawable (or one of its children) may not have been 18018 // stateful before applying the tint, so let's try again. 18019 if (mForegroundInfo.mDrawable.isStateful()) { 18020 mForegroundInfo.mDrawable.setState(getDrawableState()); 18021 } 18022 } 18023 } 18024 } 18025 18026 /** 18027 * Draw any foreground content for this view. 18028 * 18029 * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground} 18030 * drawable or other view-specific decorations. The foreground is drawn on top of the 18031 * primary view content.</p> 18032 * 18033 * @param canvas canvas to draw into 18034 */ 18035 public void onDrawForeground(Canvas canvas) { 18036 onDrawScrollIndicators(canvas); 18037 onDrawScrollBars(canvas); 18038 18039 final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; 18040 if (foreground != null) { 18041 if (mForegroundInfo.mBoundsChanged) { 18042 mForegroundInfo.mBoundsChanged = false; 18043 final Rect selfBounds = mForegroundInfo.mSelfBounds; 18044 final Rect overlayBounds = mForegroundInfo.mOverlayBounds; 18045 18046 if (mForegroundInfo.mInsidePadding) { 18047 selfBounds.set(0, 0, getWidth(), getHeight()); 18048 } else { 18049 selfBounds.set(getPaddingLeft(), getPaddingTop(), 18050 getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); 18051 } 18052 18053 final int ld = getLayoutDirection(); 18054 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), 18055 foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); 18056 foreground.setBounds(overlayBounds); 18057 } 18058 18059 foreground.draw(canvas); 18060 } 18061 } 18062 18063 /** 18064 * Sets the padding. The view may add on the space required to display 18065 * the scrollbars, depending on the style and visibility of the scrollbars. 18066 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop}, 18067 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different 18068 * from the values set in this call. 18069 * 18070 * @attr ref android.R.styleable#View_padding 18071 * @attr ref android.R.styleable#View_paddingBottom 18072 * @attr ref android.R.styleable#View_paddingLeft 18073 * @attr ref android.R.styleable#View_paddingRight 18074 * @attr ref android.R.styleable#View_paddingTop 18075 * @param left the left padding in pixels 18076 * @param top the top padding in pixels 18077 * @param right the right padding in pixels 18078 * @param bottom the bottom padding in pixels 18079 */ 18080 public void setPadding(int left, int top, int right, int bottom) { 18081 resetResolvedPaddingInternal(); 18082 18083 mUserPaddingStart = UNDEFINED_PADDING; 18084 mUserPaddingEnd = UNDEFINED_PADDING; 18085 18086 mUserPaddingLeftInitial = left; 18087 mUserPaddingRightInitial = right; 18088 18089 mLeftPaddingDefined = true; 18090 mRightPaddingDefined = true; 18091 18092 internalSetPadding(left, top, right, bottom); 18093 } 18094 18095 /** 18096 * @hide 18097 */ 18098 protected void internalSetPadding(int left, int top, int right, int bottom) { 18099 mUserPaddingLeft = left; 18100 mUserPaddingRight = right; 18101 mUserPaddingBottom = bottom; 18102 18103 final int viewFlags = mViewFlags; 18104 boolean changed = false; 18105 18106 // Common case is there are no scroll bars. 18107 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { 18108 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { 18109 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0 18110 ? 0 : getVerticalScrollbarWidth(); 18111 switch (mVerticalScrollbarPosition) { 18112 case SCROLLBAR_POSITION_DEFAULT: 18113 if (isLayoutRtl()) { 18114 left += offset; 18115 } else { 18116 right += offset; 18117 } 18118 break; 18119 case SCROLLBAR_POSITION_RIGHT: 18120 right += offset; 18121 break; 18122 case SCROLLBAR_POSITION_LEFT: 18123 left += offset; 18124 break; 18125 } 18126 } 18127 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) { 18128 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 18129 ? 0 : getHorizontalScrollbarHeight(); 18130 } 18131 } 18132 18133 if (mPaddingLeft != left) { 18134 changed = true; 18135 mPaddingLeft = left; 18136 } 18137 if (mPaddingTop != top) { 18138 changed = true; 18139 mPaddingTop = top; 18140 } 18141 if (mPaddingRight != right) { 18142 changed = true; 18143 mPaddingRight = right; 18144 } 18145 if (mPaddingBottom != bottom) { 18146 changed = true; 18147 mPaddingBottom = bottom; 18148 } 18149 18150 if (changed) { 18151 requestLayout(); 18152 invalidateOutline(); 18153 } 18154 } 18155 18156 /** 18157 * Sets the relative padding. The view may add on the space required to display 18158 * the scrollbars, depending on the style and visibility of the scrollbars. 18159 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop}, 18160 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different 18161 * from the values set in this call. 18162 * 18163 * @attr ref android.R.styleable#View_padding 18164 * @attr ref android.R.styleable#View_paddingBottom 18165 * @attr ref android.R.styleable#View_paddingStart 18166 * @attr ref android.R.styleable#View_paddingEnd 18167 * @attr ref android.R.styleable#View_paddingTop 18168 * @param start the start padding in pixels 18169 * @param top the top padding in pixels 18170 * @param end the end padding in pixels 18171 * @param bottom the bottom padding in pixels 18172 */ 18173 public void setPaddingRelative(int start, int top, int end, int bottom) { 18174 resetResolvedPaddingInternal(); 18175 18176 mUserPaddingStart = start; 18177 mUserPaddingEnd = end; 18178 mLeftPaddingDefined = true; 18179 mRightPaddingDefined = true; 18180 18181 switch(getLayoutDirection()) { 18182 case LAYOUT_DIRECTION_RTL: 18183 mUserPaddingLeftInitial = end; 18184 mUserPaddingRightInitial = start; 18185 internalSetPadding(end, top, start, bottom); 18186 break; 18187 case LAYOUT_DIRECTION_LTR: 18188 default: 18189 mUserPaddingLeftInitial = start; 18190 mUserPaddingRightInitial = end; 18191 internalSetPadding(start, top, end, bottom); 18192 } 18193 } 18194 18195 /** 18196 * Returns the top padding of this view. 18197 * 18198 * @return the top padding in pixels 18199 */ 18200 public int getPaddingTop() { 18201 return mPaddingTop; 18202 } 18203 18204 /** 18205 * Returns the bottom padding of this view. If there are inset and enabled 18206 * scrollbars, this value may include the space required to display the 18207 * scrollbars as well. 18208 * 18209 * @return the bottom padding in pixels 18210 */ 18211 public int getPaddingBottom() { 18212 return mPaddingBottom; 18213 } 18214 18215 /** 18216 * Returns the left padding of this view. If there are inset and enabled 18217 * scrollbars, this value may include the space required to display the 18218 * scrollbars as well. 18219 * 18220 * @return the left padding in pixels 18221 */ 18222 public int getPaddingLeft() { 18223 if (!isPaddingResolved()) { 18224 resolvePadding(); 18225 } 18226 return mPaddingLeft; 18227 } 18228 18229 /** 18230 * Returns the start padding of this view depending on its resolved layout direction. 18231 * If there are inset and enabled scrollbars, this value may include the space 18232 * required to display the scrollbars as well. 18233 * 18234 * @return the start padding in pixels 18235 */ 18236 public int getPaddingStart() { 18237 if (!isPaddingResolved()) { 18238 resolvePadding(); 18239 } 18240 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18241 mPaddingRight : mPaddingLeft; 18242 } 18243 18244 /** 18245 * Returns the right padding of this view. If there are inset and enabled 18246 * scrollbars, this value may include the space required to display the 18247 * scrollbars as well. 18248 * 18249 * @return the right padding in pixels 18250 */ 18251 public int getPaddingRight() { 18252 if (!isPaddingResolved()) { 18253 resolvePadding(); 18254 } 18255 return mPaddingRight; 18256 } 18257 18258 /** 18259 * Returns the end padding of this view depending on its resolved layout direction. 18260 * If there are inset and enabled scrollbars, this value may include the space 18261 * required to display the scrollbars as well. 18262 * 18263 * @return the end padding in pixels 18264 */ 18265 public int getPaddingEnd() { 18266 if (!isPaddingResolved()) { 18267 resolvePadding(); 18268 } 18269 return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ? 18270 mPaddingLeft : mPaddingRight; 18271 } 18272 18273 /** 18274 * Return if the padding has been set through relative values 18275 * {@link #setPaddingRelative(int, int, int, int)} or through 18276 * @attr ref android.R.styleable#View_paddingStart or 18277 * @attr ref android.R.styleable#View_paddingEnd 18278 * 18279 * @return true if the padding is relative or false if it is not. 18280 */ 18281 public boolean isPaddingRelative() { 18282 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING); 18283 } 18284 18285 Insets computeOpticalInsets() { 18286 return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets(); 18287 } 18288 18289 /** 18290 * @hide 18291 */ 18292 public void resetPaddingToInitialValues() { 18293 if (isRtlCompatibilityMode()) { 18294 mPaddingLeft = mUserPaddingLeftInitial; 18295 mPaddingRight = mUserPaddingRightInitial; 18296 return; 18297 } 18298 if (isLayoutRtl()) { 18299 mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial; 18300 mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial; 18301 } else { 18302 mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial; 18303 mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial; 18304 } 18305 } 18306 18307 /** 18308 * @hide 18309 */ 18310 public Insets getOpticalInsets() { 18311 if (mLayoutInsets == null) { 18312 mLayoutInsets = computeOpticalInsets(); 18313 } 18314 return mLayoutInsets; 18315 } 18316 18317 /** 18318 * Set this view's optical insets. 18319 * 18320 * <p>This method should be treated similarly to setMeasuredDimension and not as a general 18321 * property. Views that compute their own optical insets should call it as part of measurement. 18322 * This method does not request layout. If you are setting optical insets outside of 18323 * measure/layout itself you will want to call requestLayout() yourself. 18324 * </p> 18325 * @hide 18326 */ 18327 public void setOpticalInsets(Insets insets) { 18328 mLayoutInsets = insets; 18329 } 18330 18331 /** 18332 * Changes the selection state of this view. A view can be selected or not. 18333 * Note that selection is not the same as focus. Views are typically 18334 * selected in the context of an AdapterView like ListView or GridView; 18335 * the selected view is the view that is highlighted. 18336 * 18337 * @param selected true if the view must be selected, false otherwise 18338 */ 18339 public void setSelected(boolean selected) { 18340 //noinspection DoubleNegation 18341 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) { 18342 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0); 18343 if (!selected) resetPressedState(); 18344 invalidate(true); 18345 refreshDrawableState(); 18346 dispatchSetSelected(selected); 18347 if (selected) { 18348 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); 18349 } else { 18350 notifyViewAccessibilityStateChangedIfNeeded( 18351 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); 18352 } 18353 } 18354 } 18355 18356 /** 18357 * Dispatch setSelected to all of this View's children. 18358 * 18359 * @see #setSelected(boolean) 18360 * 18361 * @param selected The new selected state 18362 */ 18363 protected void dispatchSetSelected(boolean selected) { 18364 } 18365 18366 /** 18367 * Indicates the selection state of this view. 18368 * 18369 * @return true if the view is selected, false otherwise 18370 */ 18371 @ViewDebug.ExportedProperty 18372 public boolean isSelected() { 18373 return (mPrivateFlags & PFLAG_SELECTED) != 0; 18374 } 18375 18376 /** 18377 * Changes the activated state of this view. A view can be activated or not. 18378 * Note that activation is not the same as selection. Selection is 18379 * a transient property, representing the view (hierarchy) the user is 18380 * currently interacting with. Activation is a longer-term state that the 18381 * user can move views in and out of. For example, in a list view with 18382 * single or multiple selection enabled, the views in the current selection 18383 * set are activated. (Um, yeah, we are deeply sorry about the terminology 18384 * here.) The activated state is propagated down to children of the view it 18385 * is set on. 18386 * 18387 * @param activated true if the view must be activated, false otherwise 18388 */ 18389 public void setActivated(boolean activated) { 18390 //noinspection DoubleNegation 18391 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) { 18392 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0); 18393 invalidate(true); 18394 refreshDrawableState(); 18395 dispatchSetActivated(activated); 18396 } 18397 } 18398 18399 /** 18400 * Dispatch setActivated to all of this View's children. 18401 * 18402 * @see #setActivated(boolean) 18403 * 18404 * @param activated The new activated state 18405 */ 18406 protected void dispatchSetActivated(boolean activated) { 18407 } 18408 18409 /** 18410 * Indicates the activation state of this view. 18411 * 18412 * @return true if the view is activated, false otherwise 18413 */ 18414 @ViewDebug.ExportedProperty 18415 public boolean isActivated() { 18416 return (mPrivateFlags & PFLAG_ACTIVATED) != 0; 18417 } 18418 18419 /** 18420 * Returns the ViewTreeObserver for this view's hierarchy. The view tree 18421 * observer can be used to get notifications when global events, like 18422 * layout, happen. 18423 * 18424 * The returned ViewTreeObserver observer is not guaranteed to remain 18425 * valid for the lifetime of this View. If the caller of this method keeps 18426 * a long-lived reference to ViewTreeObserver, it should always check for 18427 * the return value of {@link ViewTreeObserver#isAlive()}. 18428 * 18429 * @return The ViewTreeObserver for this view's hierarchy. 18430 */ 18431 public ViewTreeObserver getViewTreeObserver() { 18432 if (mAttachInfo != null) { 18433 return mAttachInfo.mTreeObserver; 18434 } 18435 if (mFloatingTreeObserver == null) { 18436 mFloatingTreeObserver = new ViewTreeObserver(); 18437 } 18438 return mFloatingTreeObserver; 18439 } 18440 18441 /** 18442 * <p>Finds the topmost view in the current view hierarchy.</p> 18443 * 18444 * @return the topmost view containing this view 18445 */ 18446 public View getRootView() { 18447 if (mAttachInfo != null) { 18448 final View v = mAttachInfo.mRootView; 18449 if (v != null) { 18450 return v; 18451 } 18452 } 18453 18454 View parent = this; 18455 18456 while (parent.mParent != null && parent.mParent instanceof View) { 18457 parent = (View) parent.mParent; 18458 } 18459 18460 return parent; 18461 } 18462 18463 /** 18464 * Transforms a motion event from view-local coordinates to on-screen 18465 * coordinates. 18466 * 18467 * @param ev the view-local motion event 18468 * @return false if the transformation could not be applied 18469 * @hide 18470 */ 18471 public boolean toGlobalMotionEvent(MotionEvent ev) { 18472 final AttachInfo info = mAttachInfo; 18473 if (info == null) { 18474 return false; 18475 } 18476 18477 final Matrix m = info.mTmpMatrix; 18478 m.set(Matrix.IDENTITY_MATRIX); 18479 transformMatrixToGlobal(m); 18480 ev.transform(m); 18481 return true; 18482 } 18483 18484 /** 18485 * Transforms a motion event from on-screen coordinates to view-local 18486 * coordinates. 18487 * 18488 * @param ev the on-screen motion event 18489 * @return false if the transformation could not be applied 18490 * @hide 18491 */ 18492 public boolean toLocalMotionEvent(MotionEvent ev) { 18493 final AttachInfo info = mAttachInfo; 18494 if (info == null) { 18495 return false; 18496 } 18497 18498 final Matrix m = info.mTmpMatrix; 18499 m.set(Matrix.IDENTITY_MATRIX); 18500 transformMatrixToLocal(m); 18501 ev.transform(m); 18502 return true; 18503 } 18504 18505 /** 18506 * Modifies the input matrix such that it maps view-local coordinates to 18507 * on-screen coordinates. 18508 * 18509 * @param m input matrix to modify 18510 * @hide 18511 */ 18512 public void transformMatrixToGlobal(Matrix m) { 18513 final ViewParent parent = mParent; 18514 if (parent instanceof View) { 18515 final View vp = (View) parent; 18516 vp.transformMatrixToGlobal(m); 18517 m.preTranslate(-vp.mScrollX, -vp.mScrollY); 18518 } else if (parent instanceof ViewRootImpl) { 18519 final ViewRootImpl vr = (ViewRootImpl) parent; 18520 vr.transformMatrixToGlobal(m); 18521 m.preTranslate(0, -vr.mCurScrollY); 18522 } 18523 18524 m.preTranslate(mLeft, mTop); 18525 18526 if (!hasIdentityMatrix()) { 18527 m.preConcat(getMatrix()); 18528 } 18529 } 18530 18531 /** 18532 * Modifies the input matrix such that it maps on-screen coordinates to 18533 * view-local coordinates. 18534 * 18535 * @param m input matrix to modify 18536 * @hide 18537 */ 18538 public void transformMatrixToLocal(Matrix m) { 18539 final ViewParent parent = mParent; 18540 if (parent instanceof View) { 18541 final View vp = (View) parent; 18542 vp.transformMatrixToLocal(m); 18543 m.postTranslate(vp.mScrollX, vp.mScrollY); 18544 } else if (parent instanceof ViewRootImpl) { 18545 final ViewRootImpl vr = (ViewRootImpl) parent; 18546 vr.transformMatrixToLocal(m); 18547 m.postTranslate(0, vr.mCurScrollY); 18548 } 18549 18550 m.postTranslate(-mLeft, -mTop); 18551 18552 if (!hasIdentityMatrix()) { 18553 m.postConcat(getInverseMatrix()); 18554 } 18555 } 18556 18557 /** 18558 * @hide 18559 */ 18560 @ViewDebug.ExportedProperty(category = "layout", indexMapping = { 18561 @ViewDebug.IntToString(from = 0, to = "x"), 18562 @ViewDebug.IntToString(from = 1, to = "y") 18563 }) 18564 public int[] getLocationOnScreen() { 18565 int[] location = new int[2]; 18566 getLocationOnScreen(location); 18567 return location; 18568 } 18569 18570 /** 18571 * <p>Computes the coordinates of this view on the screen. The argument 18572 * must be an array of two integers. After the method returns, the array 18573 * contains the x and y location in that order.</p> 18574 * 18575 * @param outLocation an array of two integers in which to hold the coordinates 18576 */ 18577 public void getLocationOnScreen(@Size(2) int[] outLocation) { 18578 getLocationInWindow(outLocation); 18579 18580 final AttachInfo info = mAttachInfo; 18581 if (info != null) { 18582 outLocation[0] += info.mWindowLeft; 18583 outLocation[1] += info.mWindowTop; 18584 } 18585 } 18586 18587 /** 18588 * <p>Computes the coordinates of this view in its window. The argument 18589 * must be an array of two integers. After the method returns, the array 18590 * contains the x and y location in that order.</p> 18591 * 18592 * @param outLocation an array of two integers in which to hold the coordinates 18593 */ 18594 public void getLocationInWindow(@Size(2) int[] outLocation) { 18595 if (outLocation == null || outLocation.length < 2) { 18596 throw new IllegalArgumentException("outLocation must be an array of two integers"); 18597 } 18598 18599 outLocation[0] = 0; 18600 outLocation[1] = 0; 18601 18602 transformFromViewToWindowSpace(outLocation); 18603 } 18604 18605 void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) { 18606 if (inOutLocation == null || inOutLocation.length < 2) { 18607 throw new IllegalArgumentException("inOutLocation must be an array of two integers"); 18608 } 18609 18610 if (mAttachInfo == null) { 18611 // When the view is not attached to a window, this method does not make sense 18612 inOutLocation[0] = inOutLocation[1] = 0; 18613 return; 18614 } 18615 18616 float position[] = mAttachInfo.mTmpTransformLocation; 18617 position[0] = inOutLocation[0]; 18618 position[1] = inOutLocation[1]; 18619 18620 if (!hasIdentityMatrix()) { 18621 getMatrix().mapPoints(position); 18622 } 18623 18624 position[0] += mLeft; 18625 position[1] += mTop; 18626 18627 ViewParent viewParent = mParent; 18628 while (viewParent instanceof View) { 18629 final View view = (View) viewParent; 18630 18631 position[0] -= view.mScrollX; 18632 position[1] -= view.mScrollY; 18633 18634 if (!view.hasIdentityMatrix()) { 18635 view.getMatrix().mapPoints(position); 18636 } 18637 18638 position[0] += view.mLeft; 18639 position[1] += view.mTop; 18640 18641 viewParent = view.mParent; 18642 } 18643 18644 if (viewParent instanceof ViewRootImpl) { 18645 // *cough* 18646 final ViewRootImpl vr = (ViewRootImpl) viewParent; 18647 position[1] -= vr.mCurScrollY; 18648 } 18649 18650 inOutLocation[0] = Math.round(position[0]); 18651 inOutLocation[1] = Math.round(position[1]); 18652 } 18653 18654 /** 18655 * {@hide} 18656 * @param id the id of the view to be found 18657 * @return the view of the specified id, null if cannot be found 18658 */ 18659 protected View findViewTraversal(@IdRes int id) { 18660 if (id == mID) { 18661 return this; 18662 } 18663 return null; 18664 } 18665 18666 /** 18667 * {@hide} 18668 * @param tag the tag of the view to be found 18669 * @return the view of specified tag, null if cannot be found 18670 */ 18671 protected View findViewWithTagTraversal(Object tag) { 18672 if (tag != null && tag.equals(mTag)) { 18673 return this; 18674 } 18675 return null; 18676 } 18677 18678 /** 18679 * {@hide} 18680 * @param predicate The predicate to evaluate. 18681 * @param childToSkip If not null, ignores this child during the recursive traversal. 18682 * @return The first view that matches the predicate or null. 18683 */ 18684 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 18685 if (predicate.apply(this)) { 18686 return this; 18687 } 18688 return null; 18689 } 18690 18691 /** 18692 * Look for a child view with the given id. If this view has the given 18693 * id, return this view. 18694 * 18695 * @param id The id to search for. 18696 * @return The view that has the given id in the hierarchy or null 18697 */ 18698 @Nullable 18699 public final View findViewById(@IdRes int id) { 18700 if (id < 0) { 18701 return null; 18702 } 18703 return findViewTraversal(id); 18704 } 18705 18706 /** 18707 * Finds a view by its unuque and stable accessibility id. 18708 * 18709 * @param accessibilityId The searched accessibility id. 18710 * @return The found view. 18711 */ 18712 final View findViewByAccessibilityId(int accessibilityId) { 18713 if (accessibilityId < 0) { 18714 return null; 18715 } 18716 View view = findViewByAccessibilityIdTraversal(accessibilityId); 18717 if (view != null) { 18718 return view.includeForAccessibility() ? view : null; 18719 } 18720 return null; 18721 } 18722 18723 /** 18724 * Performs the traversal to find a view by its unuque and stable accessibility id. 18725 * 18726 * <strong>Note:</strong>This method does not stop at the root namespace 18727 * boundary since the user can touch the screen at an arbitrary location 18728 * potentially crossing the root namespace bounday which will send an 18729 * accessibility event to accessibility services and they should be able 18730 * to obtain the event source. Also accessibility ids are guaranteed to be 18731 * unique in the window. 18732 * 18733 * @param accessibilityId The accessibility id. 18734 * @return The found view. 18735 * 18736 * @hide 18737 */ 18738 public View findViewByAccessibilityIdTraversal(int accessibilityId) { 18739 if (getAccessibilityViewId() == accessibilityId) { 18740 return this; 18741 } 18742 return null; 18743 } 18744 18745 /** 18746 * Look for a child view with the given tag. If this view has the given 18747 * tag, return this view. 18748 * 18749 * @param tag The tag to search for, using "tag.equals(getTag())". 18750 * @return The View that has the given tag in the hierarchy or null 18751 */ 18752 public final View findViewWithTag(Object tag) { 18753 if (tag == null) { 18754 return null; 18755 } 18756 return findViewWithTagTraversal(tag); 18757 } 18758 18759 /** 18760 * {@hide} 18761 * Look for a child view that matches the specified predicate. 18762 * If this view matches the predicate, return this view. 18763 * 18764 * @param predicate The predicate to evaluate. 18765 * @return The first view that matches the predicate or null. 18766 */ 18767 public final View findViewByPredicate(Predicate<View> predicate) { 18768 return findViewByPredicateTraversal(predicate, null); 18769 } 18770 18771 /** 18772 * {@hide} 18773 * Look for a child view that matches the specified predicate, 18774 * starting with the specified view and its descendents and then 18775 * recusively searching the ancestors and siblings of that view 18776 * until this view is reached. 18777 * 18778 * This method is useful in cases where the predicate does not match 18779 * a single unique view (perhaps multiple views use the same id) 18780 * and we are trying to find the view that is "closest" in scope to the 18781 * starting view. 18782 * 18783 * @param start The view to start from. 18784 * @param predicate The predicate to evaluate. 18785 * @return The first view that matches the predicate or null. 18786 */ 18787 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) { 18788 View childToSkip = null; 18789 for (;;) { 18790 View view = start.findViewByPredicateTraversal(predicate, childToSkip); 18791 if (view != null || start == this) { 18792 return view; 18793 } 18794 18795 ViewParent parent = start.getParent(); 18796 if (parent == null || !(parent instanceof View)) { 18797 return null; 18798 } 18799 18800 childToSkip = start; 18801 start = (View) parent; 18802 } 18803 } 18804 18805 /** 18806 * Sets the identifier for this view. The identifier does not have to be 18807 * unique in this view's hierarchy. The identifier should be a positive 18808 * number. 18809 * 18810 * @see #NO_ID 18811 * @see #getId() 18812 * @see #findViewById(int) 18813 * 18814 * @param id a number used to identify the view 18815 * 18816 * @attr ref android.R.styleable#View_id 18817 */ 18818 public void setId(@IdRes int id) { 18819 mID = id; 18820 if (mID == View.NO_ID && mLabelForId != View.NO_ID) { 18821 mID = generateViewId(); 18822 } 18823 } 18824 18825 /** 18826 * {@hide} 18827 * 18828 * @param isRoot true if the view belongs to the root namespace, false 18829 * otherwise 18830 */ 18831 public void setIsRootNamespace(boolean isRoot) { 18832 if (isRoot) { 18833 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE; 18834 } else { 18835 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE; 18836 } 18837 } 18838 18839 /** 18840 * {@hide} 18841 * 18842 * @return true if the view belongs to the root namespace, false otherwise 18843 */ 18844 public boolean isRootNamespace() { 18845 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0; 18846 } 18847 18848 /** 18849 * Returns this view's identifier. 18850 * 18851 * @return a positive integer used to identify the view or {@link #NO_ID} 18852 * if the view has no ID 18853 * 18854 * @see #setId(int) 18855 * @see #findViewById(int) 18856 * @attr ref android.R.styleable#View_id 18857 */ 18858 @IdRes 18859 @ViewDebug.CapturedViewProperty 18860 public int getId() { 18861 return mID; 18862 } 18863 18864 /** 18865 * Returns this view's tag. 18866 * 18867 * @return the Object stored in this view as a tag, or {@code null} if not 18868 * set 18869 * 18870 * @see #setTag(Object) 18871 * @see #getTag(int) 18872 */ 18873 @ViewDebug.ExportedProperty 18874 public Object getTag() { 18875 return mTag; 18876 } 18877 18878 /** 18879 * Sets the tag associated with this view. A tag can be used to mark 18880 * a view in its hierarchy and does not have to be unique within the 18881 * hierarchy. Tags can also be used to store data within a view without 18882 * resorting to another data structure. 18883 * 18884 * @param tag an Object to tag the view with 18885 * 18886 * @see #getTag() 18887 * @see #setTag(int, Object) 18888 */ 18889 public void setTag(final Object tag) { 18890 mTag = tag; 18891 } 18892 18893 /** 18894 * Returns the tag associated with this view and the specified key. 18895 * 18896 * @param key The key identifying the tag 18897 * 18898 * @return the Object stored in this view as a tag, or {@code null} if not 18899 * set 18900 * 18901 * @see #setTag(int, Object) 18902 * @see #getTag() 18903 */ 18904 public Object getTag(int key) { 18905 if (mKeyedTags != null) return mKeyedTags.get(key); 18906 return null; 18907 } 18908 18909 /** 18910 * Sets a tag associated with this view and a key. A tag can be used 18911 * to mark a view in its hierarchy and does not have to be unique within 18912 * the hierarchy. Tags can also be used to store data within a view 18913 * without resorting to another data structure. 18914 * 18915 * The specified key should be an id declared in the resources of the 18916 * application to ensure it is unique (see the <a 18917 * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>). 18918 * Keys identified as belonging to 18919 * the Android framework or not associated with any package will cause 18920 * an {@link IllegalArgumentException} to be thrown. 18921 * 18922 * @param key The key identifying the tag 18923 * @param tag An Object to tag the view with 18924 * 18925 * @throws IllegalArgumentException If they specified key is not valid 18926 * 18927 * @see #setTag(Object) 18928 * @see #getTag(int) 18929 */ 18930 public void setTag(int key, final Object tag) { 18931 // If the package id is 0x00 or 0x01, it's either an undefined package 18932 // or a framework id 18933 if ((key >>> 24) < 2) { 18934 throw new IllegalArgumentException("The key must be an application-specific " 18935 + "resource id."); 18936 } 18937 18938 setKeyedTag(key, tag); 18939 } 18940 18941 /** 18942 * Variation of {@link #setTag(int, Object)} that enforces the key to be a 18943 * framework id. 18944 * 18945 * @hide 18946 */ 18947 public void setTagInternal(int key, Object tag) { 18948 if ((key >>> 24) != 0x1) { 18949 throw new IllegalArgumentException("The key must be a framework-specific " 18950 + "resource id."); 18951 } 18952 18953 setKeyedTag(key, tag); 18954 } 18955 18956 private void setKeyedTag(int key, Object tag) { 18957 if (mKeyedTags == null) { 18958 mKeyedTags = new SparseArray<Object>(2); 18959 } 18960 18961 mKeyedTags.put(key, tag); 18962 } 18963 18964 /** 18965 * Prints information about this view in the log output, with the tag 18966 * {@link #VIEW_LOG_TAG}. 18967 * 18968 * @hide 18969 */ 18970 public void debug() { 18971 debug(0); 18972 } 18973 18974 /** 18975 * Prints information about this view in the log output, with the tag 18976 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an 18977 * indentation defined by the <code>depth</code>. 18978 * 18979 * @param depth the indentation level 18980 * 18981 * @hide 18982 */ 18983 protected void debug(int depth) { 18984 String output = debugIndent(depth - 1); 18985 18986 output += "+ " + this; 18987 int id = getId(); 18988 if (id != -1) { 18989 output += " (id=" + id + ")"; 18990 } 18991 Object tag = getTag(); 18992 if (tag != null) { 18993 output += " (tag=" + tag + ")"; 18994 } 18995 Log.d(VIEW_LOG_TAG, output); 18996 18997 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) { 18998 output = debugIndent(depth) + " FOCUSED"; 18999 Log.d(VIEW_LOG_TAG, output); 19000 } 19001 19002 output = debugIndent(depth); 19003 output += "frame={" + mLeft + ", " + mTop + ", " + mRight 19004 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY 19005 + "} "; 19006 Log.d(VIEW_LOG_TAG, output); 19007 19008 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0 19009 || mPaddingBottom != 0) { 19010 output = debugIndent(depth); 19011 output += "padding={" + mPaddingLeft + ", " + mPaddingTop 19012 + ", " + mPaddingRight + ", " + mPaddingBottom + "}"; 19013 Log.d(VIEW_LOG_TAG, output); 19014 } 19015 19016 output = debugIndent(depth); 19017 output += "mMeasureWidth=" + mMeasuredWidth + 19018 " mMeasureHeight=" + mMeasuredHeight; 19019 Log.d(VIEW_LOG_TAG, output); 19020 19021 output = debugIndent(depth); 19022 if (mLayoutParams == null) { 19023 output += "BAD! no layout params"; 19024 } else { 19025 output = mLayoutParams.debug(output); 19026 } 19027 Log.d(VIEW_LOG_TAG, output); 19028 19029 output = debugIndent(depth); 19030 output += "flags={"; 19031 output += View.printFlags(mViewFlags); 19032 output += "}"; 19033 Log.d(VIEW_LOG_TAG, output); 19034 19035 output = debugIndent(depth); 19036 output += "privateFlags={"; 19037 output += View.printPrivateFlags(mPrivateFlags); 19038 output += "}"; 19039 Log.d(VIEW_LOG_TAG, output); 19040 } 19041 19042 /** 19043 * Creates a string of whitespaces used for indentation. 19044 * 19045 * @param depth the indentation level 19046 * @return a String containing (depth * 2 + 3) * 2 white spaces 19047 * 19048 * @hide 19049 */ 19050 protected static String debugIndent(int depth) { 19051 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2); 19052 for (int i = 0; i < (depth * 2) + 3; i++) { 19053 spaces.append(' ').append(' '); 19054 } 19055 return spaces.toString(); 19056 } 19057 19058 /** 19059 * <p>Return the offset of the widget's text baseline from the widget's top 19060 * boundary. If this widget does not support baseline alignment, this 19061 * method returns -1. </p> 19062 * 19063 * @return the offset of the baseline within the widget's bounds or -1 19064 * if baseline alignment is not supported 19065 */ 19066 @ViewDebug.ExportedProperty(category = "layout") 19067 public int getBaseline() { 19068 return -1; 19069 } 19070 19071 /** 19072 * Returns whether the view hierarchy is currently undergoing a layout pass. This 19073 * information is useful to avoid situations such as calling {@link #requestLayout()} during 19074 * a layout pass. 19075 * 19076 * @return whether the view hierarchy is currently undergoing a layout pass 19077 */ 19078 public boolean isInLayout() { 19079 ViewRootImpl viewRoot = getViewRootImpl(); 19080 return (viewRoot != null && viewRoot.isInLayout()); 19081 } 19082 19083 /** 19084 * Call this when something has changed which has invalidated the 19085 * layout of this view. This will schedule a layout pass of the view 19086 * tree. This should not be called while the view hierarchy is currently in a layout 19087 * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the 19088 * end of the current layout pass (and then layout will run again) or after the current 19089 * frame is drawn and the next layout occurs. 19090 * 19091 * <p>Subclasses which override this method should call the superclass method to 19092 * handle possible request-during-layout errors correctly.</p> 19093 */ 19094 @CallSuper 19095 public void requestLayout() { 19096 if (mMeasureCache != null) mMeasureCache.clear(); 19097 19098 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) { 19099 // Only trigger request-during-layout logic if this is the view requesting it, 19100 // not the views in its parent hierarchy 19101 ViewRootImpl viewRoot = getViewRootImpl(); 19102 if (viewRoot != null && viewRoot.isInLayout()) { 19103 if (!viewRoot.requestLayoutDuringLayout(this)) { 19104 return; 19105 } 19106 } 19107 mAttachInfo.mViewRequestingLayout = this; 19108 } 19109 19110 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19111 mPrivateFlags |= PFLAG_INVALIDATED; 19112 19113 if (mParent != null && !mParent.isLayoutRequested()) { 19114 mParent.requestLayoutForChild(this); 19115 } 19116 if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) { 19117 mAttachInfo.mViewRequestingLayout = null; 19118 } 19119 } 19120 19121 /** 19122 * Forces this view to be laid out during the next layout pass. 19123 * This method does not call requestLayout() or forceLayout() 19124 * on the parent. 19125 */ 19126 public void forceLayout() { 19127 if (mMeasureCache != null) mMeasureCache.clear(); 19128 19129 mPrivateFlags |= PFLAG_FORCE_LAYOUT; 19130 mPrivateFlags |= PFLAG_INVALIDATED; 19131 } 19132 19133 void forcePartialLayout() { 19134 forceLayout(); 19135 mPrivateFlags3 |= PFLAG3_PARTIAL_LAYOUT_REQUESTED; 19136 } 19137 19138 /** 19139 * <p> 19140 * This is called to find out how big a view should be. The parent 19141 * supplies constraint information in the width and height parameters. 19142 * </p> 19143 * 19144 * <p> 19145 * The actual measurement work of a view is performed in 19146 * {@link #onMeasure(int, int)}, called by this method. Therefore, only 19147 * {@link #onMeasure(int, int)} can and must be overridden by subclasses. 19148 * </p> 19149 * 19150 * 19151 * @param widthMeasureSpec Horizontal space requirements as imposed by the 19152 * parent 19153 * @param heightMeasureSpec Vertical space requirements as imposed by the 19154 * parent 19155 * 19156 * @see #onMeasure(int, int) 19157 */ 19158 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 19159 boolean optical = isLayoutModeOptical(this); 19160 if (optical != isLayoutModeOptical(mParent)) { 19161 Insets insets = getOpticalInsets(); 19162 int oWidth = insets.left + insets.right; 19163 int oHeight = insets.top + insets.bottom; 19164 widthMeasureSpec = MeasureSpec.adjust(widthMeasureSpec, optical ? -oWidth : oWidth); 19165 heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight); 19166 } 19167 19168 // Suppress sign extension for the low bytes 19169 long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; 19170 if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); 19171 19172 final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; 19173 19174 // Optimize layout by avoiding an extra EXACTLY pass when the view is 19175 // already measured as the correct size. In API 23 and below, this 19176 // extra pass is required to make LinearLayout re-distribute weight. 19177 final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec 19178 || heightMeasureSpec != mOldHeightMeasureSpec; 19179 final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY 19180 && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; 19181 final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) 19182 && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); 19183 final boolean needsLayout = specChanged 19184 && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize); 19185 19186 if (forceLayout || needsLayout) { 19187 // first clears the measured dimension flag 19188 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; 19189 19190 resolveRtlPropertiesIfNeeded(); 19191 19192 int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); 19193 if (cacheIndex < 0 || sIgnoreMeasureCache) { 19194 // measure ourselves, this should set the measured dimension flag back 19195 onMeasure(widthMeasureSpec, heightMeasureSpec); 19196 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19197 } else { 19198 long value = mMeasureCache.valueAt(cacheIndex); 19199 // Casting a long to int drops the high 32 bits, no mask needed 19200 setMeasuredDimensionRaw((int) (value >> 32), (int) value); 19201 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; 19202 } 19203 19204 // flag not set, setMeasuredDimension() was not invoked, we raise 19205 // an exception to warn the developer 19206 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) { 19207 throw new IllegalStateException("View with id " + getId() + ": " 19208 + getClass().getName() + "#onMeasure() did not set the" 19209 + " measured dimension by calling" 19210 + " setMeasuredDimension()"); 19211 } 19212 19213 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED; 19214 } 19215 19216 mOldWidthMeasureSpec = widthMeasureSpec; 19217 mOldHeightMeasureSpec = heightMeasureSpec; 19218 19219 mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 | 19220 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension 19221 } 19222 19223 /** 19224 * <p> 19225 * Measure the view and its content to determine the measured width and the 19226 * measured height. This method is invoked by {@link #measure(int, int)} and 19227 * should be overridden by subclasses to provide accurate and efficient 19228 * measurement of their contents. 19229 * </p> 19230 * 19231 * <p> 19232 * <strong>CONTRACT:</strong> When overriding this method, you 19233 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the 19234 * measured width and height of this view. Failure to do so will trigger an 19235 * <code>IllegalStateException</code>, thrown by 19236 * {@link #measure(int, int)}. Calling the superclass' 19237 * {@link #onMeasure(int, int)} is a valid use. 19238 * </p> 19239 * 19240 * <p> 19241 * The base class implementation of measure defaults to the background size, 19242 * unless a larger size is allowed by the MeasureSpec. Subclasses should 19243 * override {@link #onMeasure(int, int)} to provide better measurements of 19244 * their content. 19245 * </p> 19246 * 19247 * <p> 19248 * If this method is overridden, it is the subclass's responsibility to make 19249 * sure the measured height and width are at least the view's minimum height 19250 * and width ({@link #getSuggestedMinimumHeight()} and 19251 * {@link #getSuggestedMinimumWidth()}). 19252 * </p> 19253 * 19254 * @param widthMeasureSpec horizontal space requirements as imposed by the parent. 19255 * The requirements are encoded with 19256 * {@link android.view.View.MeasureSpec}. 19257 * @param heightMeasureSpec vertical space requirements as imposed by the parent. 19258 * The requirements are encoded with 19259 * {@link android.view.View.MeasureSpec}. 19260 * 19261 * @see #getMeasuredWidth() 19262 * @see #getMeasuredHeight() 19263 * @see #setMeasuredDimension(int, int) 19264 * @see #getSuggestedMinimumHeight() 19265 * @see #getSuggestedMinimumWidth() 19266 * @see android.view.View.MeasureSpec#getMode(int) 19267 * @see android.view.View.MeasureSpec#getSize(int) 19268 */ 19269 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 19270 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), 19271 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); 19272 } 19273 19274 /** 19275 * <p>This method must be called by {@link #onMeasure(int, int)} to store the 19276 * measured width and measured height. Failing to do so will trigger an 19277 * exception at measurement time.</p> 19278 * 19279 * @param measuredWidth The measured width of this view. May be a complex 19280 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19281 * {@link #MEASURED_STATE_TOO_SMALL}. 19282 * @param measuredHeight The measured height of this view. May be a complex 19283 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19284 * {@link #MEASURED_STATE_TOO_SMALL}. 19285 */ 19286 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { 19287 boolean optical = isLayoutModeOptical(this); 19288 if (optical != isLayoutModeOptical(mParent)) { 19289 Insets insets = getOpticalInsets(); 19290 int opticalWidth = insets.left + insets.right; 19291 int opticalHeight = insets.top + insets.bottom; 19292 19293 measuredWidth += optical ? opticalWidth : -opticalWidth; 19294 measuredHeight += optical ? opticalHeight : -opticalHeight; 19295 } 19296 setMeasuredDimensionRaw(measuredWidth, measuredHeight); 19297 } 19298 19299 /** 19300 * Sets the measured dimension without extra processing for things like optical bounds. 19301 * Useful for reapplying consistent values that have already been cooked with adjustments 19302 * for optical bounds, etc. such as those from the measurement cache. 19303 * 19304 * @param measuredWidth The measured width of this view. May be a complex 19305 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19306 * {@link #MEASURED_STATE_TOO_SMALL}. 19307 * @param measuredHeight The measured height of this view. May be a complex 19308 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and 19309 * {@link #MEASURED_STATE_TOO_SMALL}. 19310 */ 19311 private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { 19312 mMeasuredWidth = measuredWidth; 19313 mMeasuredHeight = measuredHeight; 19314 19315 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; 19316 } 19317 19318 /** 19319 * Merge two states as returned by {@link #getMeasuredState()}. 19320 * @param curState The current state as returned from a view or the result 19321 * of combining multiple views. 19322 * @param newState The new view state to combine. 19323 * @return Returns a new integer reflecting the combination of the two 19324 * states. 19325 */ 19326 public static int combineMeasuredStates(int curState, int newState) { 19327 return curState | newState; 19328 } 19329 19330 /** 19331 * Version of {@link #resolveSizeAndState(int, int, int)} 19332 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result. 19333 */ 19334 public static int resolveSize(int size, int measureSpec) { 19335 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK; 19336 } 19337 19338 /** 19339 * Utility to reconcile a desired size and state, with constraints imposed 19340 * by a MeasureSpec. Will take the desired size, unless a different size 19341 * is imposed by the constraints. The returned value is a compound integer, 19342 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and 19343 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the 19344 * resulting size is smaller than the size the view wants to be. 19345 * 19346 * @param size How big the view wants to be. 19347 * @param measureSpec Constraints imposed by the parent. 19348 * @param childMeasuredState Size information bit mask for the view's 19349 * children. 19350 * @return Size information bit mask as defined by 19351 * {@link #MEASURED_SIZE_MASK} and 19352 * {@link #MEASURED_STATE_TOO_SMALL}. 19353 */ 19354 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { 19355 final int specMode = MeasureSpec.getMode(measureSpec); 19356 final int specSize = MeasureSpec.getSize(measureSpec); 19357 final int result; 19358 switch (specMode) { 19359 case MeasureSpec.AT_MOST: 19360 if (specSize < size) { 19361 result = specSize | MEASURED_STATE_TOO_SMALL; 19362 } else { 19363 result = size; 19364 } 19365 break; 19366 case MeasureSpec.EXACTLY: 19367 result = specSize; 19368 break; 19369 case MeasureSpec.UNSPECIFIED: 19370 default: 19371 result = size; 19372 } 19373 return result | (childMeasuredState & MEASURED_STATE_MASK); 19374 } 19375 19376 /** 19377 * Utility to return a default size. Uses the supplied size if the 19378 * MeasureSpec imposed no constraints. Will get larger if allowed 19379 * by the MeasureSpec. 19380 * 19381 * @param size Default size for this view 19382 * @param measureSpec Constraints imposed by the parent 19383 * @return The size this view should be. 19384 */ 19385 public static int getDefaultSize(int size, int measureSpec) { 19386 int result = size; 19387 int specMode = MeasureSpec.getMode(measureSpec); 19388 int specSize = MeasureSpec.getSize(measureSpec); 19389 19390 switch (specMode) { 19391 case MeasureSpec.UNSPECIFIED: 19392 result = size; 19393 break; 19394 case MeasureSpec.AT_MOST: 19395 case MeasureSpec.EXACTLY: 19396 result = specSize; 19397 break; 19398 } 19399 return result; 19400 } 19401 19402 /** 19403 * Returns the suggested minimum height that the view should use. This 19404 * returns the maximum of the view's minimum height 19405 * and the background's minimum height 19406 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}). 19407 * <p> 19408 * When being used in {@link #onMeasure(int, int)}, the caller should still 19409 * ensure the returned height is within the requirements of the parent. 19410 * 19411 * @return The suggested minimum height of the view. 19412 */ 19413 protected int getSuggestedMinimumHeight() { 19414 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); 19415 19416 } 19417 19418 /** 19419 * Returns the suggested minimum width that the view should use. This 19420 * returns the maximum of the view's minimum width 19421 * and the background's minimum width 19422 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}). 19423 * <p> 19424 * When being used in {@link #onMeasure(int, int)}, the caller should still 19425 * ensure the returned width is within the requirements of the parent. 19426 * 19427 * @return The suggested minimum width of the view. 19428 */ 19429 protected int getSuggestedMinimumWidth() { 19430 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth()); 19431 } 19432 19433 /** 19434 * Returns the minimum height of the view. 19435 * 19436 * @return the minimum height the view will try to be. 19437 * 19438 * @see #setMinimumHeight(int) 19439 * 19440 * @attr ref android.R.styleable#View_minHeight 19441 */ 19442 public int getMinimumHeight() { 19443 return mMinHeight; 19444 } 19445 19446 /** 19447 * Sets the minimum height of the view. It is not guaranteed the view will 19448 * be able to achieve this minimum height (for example, if its parent layout 19449 * constrains it with less available height). 19450 * 19451 * @param minHeight The minimum height the view will try to be. 19452 * 19453 * @see #getMinimumHeight() 19454 * 19455 * @attr ref android.R.styleable#View_minHeight 19456 */ 19457 @RemotableViewMethod 19458 public void setMinimumHeight(int minHeight) { 19459 mMinHeight = minHeight; 19460 requestLayout(); 19461 } 19462 19463 /** 19464 * Returns the minimum width of the view. 19465 * 19466 * @return the minimum width the view will try to be. 19467 * 19468 * @see #setMinimumWidth(int) 19469 * 19470 * @attr ref android.R.styleable#View_minWidth 19471 */ 19472 public int getMinimumWidth() { 19473 return mMinWidth; 19474 } 19475 19476 /** 19477 * Sets the minimum width of the view. It is not guaranteed the view will 19478 * be able to achieve this minimum width (for example, if its parent layout 19479 * constrains it with less available width). 19480 * 19481 * @param minWidth The minimum width the view will try to be. 19482 * 19483 * @see #getMinimumWidth() 19484 * 19485 * @attr ref android.R.styleable#View_minWidth 19486 */ 19487 public void setMinimumWidth(int minWidth) { 19488 mMinWidth = minWidth; 19489 requestLayout(); 19490 19491 } 19492 19493 /** 19494 * Get the animation currently associated with this view. 19495 * 19496 * @return The animation that is currently playing or 19497 * scheduled to play for this view. 19498 */ 19499 public Animation getAnimation() { 19500 return mCurrentAnimation; 19501 } 19502 19503 /** 19504 * Start the specified animation now. 19505 * 19506 * @param animation the animation to start now 19507 */ 19508 public void startAnimation(Animation animation) { 19509 animation.setStartTime(Animation.START_ON_FIRST_FRAME); 19510 setAnimation(animation); 19511 invalidateParentCaches(); 19512 invalidate(true); 19513 } 19514 19515 /** 19516 * Cancels any animations for this view. 19517 */ 19518 public void clearAnimation() { 19519 if (mCurrentAnimation != null) { 19520 mCurrentAnimation.detach(); 19521 } 19522 mCurrentAnimation = null; 19523 invalidateParentIfNeeded(); 19524 } 19525 19526 /** 19527 * Sets the next animation to play for this view. 19528 * If you want the animation to play immediately, use 19529 * {@link #startAnimation(android.view.animation.Animation)} instead. 19530 * This method provides allows fine-grained 19531 * control over the start time and invalidation, but you 19532 * must make sure that 1) the animation has a start time set, and 19533 * 2) the view's parent (which controls animations on its children) 19534 * will be invalidated when the animation is supposed to 19535 * start. 19536 * 19537 * @param animation The next animation, or null. 19538 */ 19539 public void setAnimation(Animation animation) { 19540 mCurrentAnimation = animation; 19541 19542 if (animation != null) { 19543 // If the screen is off assume the animation start time is now instead of 19544 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time 19545 // would cause the animation to start when the screen turns back on 19546 if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF 19547 && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { 19548 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); 19549 } 19550 animation.reset(); 19551 } 19552 } 19553 19554 /** 19555 * Invoked by a parent ViewGroup to notify the start of the animation 19556 * currently associated with this view. If you override this method, 19557 * always call super.onAnimationStart(); 19558 * 19559 * @see #setAnimation(android.view.animation.Animation) 19560 * @see #getAnimation() 19561 */ 19562 @CallSuper 19563 protected void onAnimationStart() { 19564 mPrivateFlags |= PFLAG_ANIMATION_STARTED; 19565 } 19566 19567 /** 19568 * Invoked by a parent ViewGroup to notify the end of the animation 19569 * currently associated with this view. If you override this method, 19570 * always call super.onAnimationEnd(); 19571 * 19572 * @see #setAnimation(android.view.animation.Animation) 19573 * @see #getAnimation() 19574 */ 19575 @CallSuper 19576 protected void onAnimationEnd() { 19577 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED; 19578 } 19579 19580 /** 19581 * Invoked if there is a Transform that involves alpha. Subclass that can 19582 * draw themselves with the specified alpha should return true, and then 19583 * respect that alpha when their onDraw() is called. If this returns false 19584 * then the view may be redirected to draw into an offscreen buffer to 19585 * fulfill the request, which will look fine, but may be slower than if the 19586 * subclass handles it internally. The default implementation returns false. 19587 * 19588 * @param alpha The alpha (0..255) to apply to the view's drawing 19589 * @return true if the view can draw with the specified alpha. 19590 */ 19591 protected boolean onSetAlpha(int alpha) { 19592 return false; 19593 } 19594 19595 /** 19596 * This is used by the RootView to perform an optimization when 19597 * the view hierarchy contains one or several SurfaceView. 19598 * SurfaceView is always considered transparent, but its children are not, 19599 * therefore all View objects remove themselves from the global transparent 19600 * region (passed as a parameter to this function). 19601 * 19602 * @param region The transparent region for this ViewAncestor (window). 19603 * 19604 * @return Returns true if the effective visibility of the view at this 19605 * point is opaque, regardless of the transparent region; returns false 19606 * if it is possible for underlying windows to be seen behind the view. 19607 * 19608 * {@hide} 19609 */ 19610 public boolean gatherTransparentRegion(Region region) { 19611 final AttachInfo attachInfo = mAttachInfo; 19612 if (region != null && attachInfo != null) { 19613 final int pflags = mPrivateFlags; 19614 if ((pflags & PFLAG_SKIP_DRAW) == 0) { 19615 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to 19616 // remove it from the transparent region. 19617 final int[] location = attachInfo.mTransparentLocation; 19618 getLocationInWindow(location); 19619 region.op(location[0], location[1], location[0] + mRight - mLeft, 19620 location[1] + mBottom - mTop, Region.Op.DIFFERENCE); 19621 } else { 19622 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) { 19623 // The SKIP_DRAW flag IS set and the background drawable exists, we remove 19624 // the background drawable's non-transparent parts from this transparent region. 19625 applyDrawableToTransparentRegion(mBackground, region); 19626 } 19627 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null 19628 && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) { 19629 // Similarly, we remove the foreground drawable's non-transparent parts. 19630 applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region); 19631 } 19632 } 19633 } 19634 return true; 19635 } 19636 19637 /** 19638 * Play a sound effect for this view. 19639 * 19640 * <p>The framework will play sound effects for some built in actions, such as 19641 * clicking, but you may wish to play these effects in your widget, 19642 * for instance, for internal navigation. 19643 * 19644 * <p>The sound effect will only be played if sound effects are enabled by the user, and 19645 * {@link #isSoundEffectsEnabled()} is true. 19646 * 19647 * @param soundConstant One of the constants defined in {@link SoundEffectConstants} 19648 */ 19649 public void playSoundEffect(int soundConstant) { 19650 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) { 19651 return; 19652 } 19653 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant); 19654 } 19655 19656 /** 19657 * BZZZTT!!1! 19658 * 19659 * <p>Provide haptic feedback to the user for this view. 19660 * 19661 * <p>The framework will provide haptic feedback for some built in actions, 19662 * such as long presses, but you may wish to provide feedback for your 19663 * own widget. 19664 * 19665 * <p>The feedback will only be performed if 19666 * {@link #isHapticFeedbackEnabled()} is true. 19667 * 19668 * @param feedbackConstant One of the constants defined in 19669 * {@link HapticFeedbackConstants} 19670 */ 19671 public boolean performHapticFeedback(int feedbackConstant) { 19672 return performHapticFeedback(feedbackConstant, 0); 19673 } 19674 19675 /** 19676 * BZZZTT!!1! 19677 * 19678 * <p>Like {@link #performHapticFeedback(int)}, with additional options. 19679 * 19680 * @param feedbackConstant One of the constants defined in 19681 * {@link HapticFeedbackConstants} 19682 * @param flags Additional flags as per {@link HapticFeedbackConstants}. 19683 */ 19684 public boolean performHapticFeedback(int feedbackConstant, int flags) { 19685 if (mAttachInfo == null) { 19686 return false; 19687 } 19688 //noinspection SimplifiableIfStatement 19689 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0 19690 && !isHapticFeedbackEnabled()) { 19691 return false; 19692 } 19693 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant, 19694 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0); 19695 } 19696 19697 /** 19698 * Request that the visibility of the status bar or other screen/window 19699 * decorations be changed. 19700 * 19701 * <p>This method is used to put the over device UI into temporary modes 19702 * where the user's attention is focused more on the application content, 19703 * by dimming or hiding surrounding system affordances. This is typically 19704 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY 19705 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content 19706 * to be placed behind the action bar (and with these flags other system 19707 * affordances) so that smooth transitions between hiding and showing them 19708 * can be done. 19709 * 19710 * <p>Two representative examples of the use of system UI visibility is 19711 * implementing a content browsing application (like a magazine reader) 19712 * and a video playing application. 19713 * 19714 * <p>The first code shows a typical implementation of a View in a content 19715 * browsing application. In this implementation, the application goes 19716 * into a content-oriented mode by hiding the status bar and action bar, 19717 * and putting the navigation elements into lights out mode. The user can 19718 * then interact with content while in this mode. Such an application should 19719 * provide an easy way for the user to toggle out of the mode (such as to 19720 * check information in the status bar or access notifications). In the 19721 * implementation here, this is done simply by tapping on the content. 19722 * 19723 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java 19724 * content} 19725 * 19726 * <p>This second code sample shows a typical implementation of a View 19727 * in a video playing application. In this situation, while the video is 19728 * playing the application would like to go into a complete full-screen mode, 19729 * to use as much of the display as possible for the video. When in this state 19730 * the user can not interact with the application; the system intercepts 19731 * touching on the screen to pop the UI out of full screen mode. See 19732 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code. 19733 * 19734 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java 19735 * content} 19736 * 19737 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 19738 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 19739 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 19740 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 19741 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 19742 */ 19743 public void setSystemUiVisibility(int visibility) { 19744 if (visibility != mSystemUiVisibility) { 19745 mSystemUiVisibility = visibility; 19746 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 19747 mParent.recomputeViewAttributes(this); 19748 } 19749 } 19750 } 19751 19752 /** 19753 * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested. 19754 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 19755 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN}, 19756 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, 19757 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE}, 19758 * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}. 19759 */ 19760 public int getSystemUiVisibility() { 19761 return mSystemUiVisibility; 19762 } 19763 19764 /** 19765 * Returns the current system UI visibility that is currently set for 19766 * the entire window. This is the combination of the 19767 * {@link #setSystemUiVisibility(int)} values supplied by all of the 19768 * views in the window. 19769 */ 19770 public int getWindowSystemUiVisibility() { 19771 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0; 19772 } 19773 19774 /** 19775 * Override to find out when the window's requested system UI visibility 19776 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}. 19777 * This is different from the callbacks received through 19778 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)} 19779 * in that this is only telling you about the local request of the window, 19780 * not the actual values applied by the system. 19781 */ 19782 public void onWindowSystemUiVisibilityChanged(int visible) { 19783 } 19784 19785 /** 19786 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down 19787 * the view hierarchy. 19788 */ 19789 public void dispatchWindowSystemUiVisiblityChanged(int visible) { 19790 onWindowSystemUiVisibilityChanged(visible); 19791 } 19792 19793 /** 19794 * Set a listener to receive callbacks when the visibility of the system bar changes. 19795 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. 19796 */ 19797 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { 19798 getListenerInfo().mOnSystemUiVisibilityChangeListener = l; 19799 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { 19800 mParent.recomputeViewAttributes(this); 19801 } 19802 } 19803 19804 /** 19805 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down 19806 * the view hierarchy. 19807 */ 19808 public void dispatchSystemUiVisibilityChanged(int visibility) { 19809 ListenerInfo li = mListenerInfo; 19810 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) { 19811 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange( 19812 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK); 19813 } 19814 } 19815 19816 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) { 19817 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges); 19818 if (val != mSystemUiVisibility) { 19819 setSystemUiVisibility(val); 19820 return true; 19821 } 19822 return false; 19823 } 19824 19825 /** @hide */ 19826 public void setDisabledSystemUiVisibility(int flags) { 19827 if (mAttachInfo != null) { 19828 if (mAttachInfo.mDisabledSystemUiVisibility != flags) { 19829 mAttachInfo.mDisabledSystemUiVisibility = flags; 19830 if (mParent != null) { 19831 mParent.recomputeViewAttributes(this); 19832 } 19833 } 19834 } 19835 } 19836 19837 /** 19838 * Creates an image that the system displays during the drag and drop 19839 * operation. This is called a "drag shadow". The default implementation 19840 * for a DragShadowBuilder based on a View returns an image that has exactly the same 19841 * appearance as the given View. The default also positions the center of the drag shadow 19842 * directly under the touch point. If no View is provided (the constructor with no parameters 19843 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and 19844 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the 19845 * default is an invisible drag shadow. 19846 * <p> 19847 * You are not required to use the View you provide to the constructor as the basis of the 19848 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw 19849 * anything you want as the drag shadow. 19850 * </p> 19851 * <p> 19852 * You pass a DragShadowBuilder object to the system when you start the drag. The system 19853 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the 19854 * size and position of the drag shadow. It uses this data to construct a 19855 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()} 19856 * so that your application can draw the shadow image in the Canvas. 19857 * </p> 19858 * 19859 * <div class="special reference"> 19860 * <h3>Developer Guides</h3> 19861 * <p>For a guide to implementing drag and drop features, read the 19862 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 19863 * </div> 19864 */ 19865 public static class DragShadowBuilder { 19866 private final WeakReference<View> mView; 19867 19868 /** 19869 * Constructs a shadow image builder based on a View. By default, the resulting drag 19870 * shadow will have the same appearance and dimensions as the View, with the touch point 19871 * over the center of the View. 19872 * @param view A View. Any View in scope can be used. 19873 */ 19874 public DragShadowBuilder(View view) { 19875 mView = new WeakReference<View>(view); 19876 } 19877 19878 /** 19879 * Construct a shadow builder object with no associated View. This 19880 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)} 19881 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order 19882 * to supply the drag shadow's dimensions and appearance without 19883 * reference to any View object. If they are not overridden, then the result is an 19884 * invisible drag shadow. 19885 */ 19886 public DragShadowBuilder() { 19887 mView = new WeakReference<View>(null); 19888 } 19889 19890 /** 19891 * Returns the View object that had been passed to the 19892 * {@link #View.DragShadowBuilder(View)} 19893 * constructor. If that View parameter was {@code null} or if the 19894 * {@link #View.DragShadowBuilder()} 19895 * constructor was used to instantiate the builder object, this method will return 19896 * null. 19897 * 19898 * @return The View object associate with this builder object. 19899 */ 19900 @SuppressWarnings({"JavadocReference"}) 19901 final public View getView() { 19902 return mView.get(); 19903 } 19904 19905 /** 19906 * Provides the metrics for the shadow image. These include the dimensions of 19907 * the shadow image, and the point within that shadow that should 19908 * be centered under the touch location while dragging. 19909 * <p> 19910 * The default implementation sets the dimensions of the shadow to be the 19911 * same as the dimensions of the View itself and centers the shadow under 19912 * the touch point. 19913 * </p> 19914 * 19915 * @param shadowSize A {@link android.graphics.Point} containing the width and height 19916 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the 19917 * desired width and must set {@link android.graphics.Point#y} to the desired height of the 19918 * image. 19919 * 19920 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the 19921 * shadow image that should be underneath the touch point during the drag and drop 19922 * operation. Your application must set {@link android.graphics.Point#x} to the 19923 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position. 19924 */ 19925 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { 19926 final View view = mView.get(); 19927 if (view != null) { 19928 shadowSize.set(view.getWidth(), view.getHeight()); 19929 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); 19930 } else { 19931 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); 19932 } 19933 } 19934 19935 /** 19936 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object 19937 * based on the dimensions it received from the 19938 * {@link #onProvideShadowMetrics(Point, Point)} callback. 19939 * 19940 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image. 19941 */ 19942 public void onDrawShadow(Canvas canvas) { 19943 final View view = mView.get(); 19944 if (view != null) { 19945 view.draw(canvas); 19946 } else { 19947 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view"); 19948 } 19949 } 19950 } 19951 19952 /** 19953 * @deprecated Use {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) 19954 * startDragAndDrop()} for newer platform versions. 19955 */ 19956 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder, 19957 Object myLocalState, int flags) { 19958 return startDragAndDrop(data, shadowBuilder, myLocalState, flags); 19959 } 19960 19961 /** 19962 * Starts a drag and drop operation. When your application calls this method, it passes a 19963 * {@link android.view.View.DragShadowBuilder} object to the system. The 19964 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)} 19965 * to get metrics for the drag shadow, and then calls the object's 19966 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself. 19967 * <p> 19968 * Once the system has the drag shadow, it begins the drag and drop operation by sending 19969 * drag events to all the View objects in your application that are currently visible. It does 19970 * this either by calling the View object's drag listener (an implementation of 19971 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the 19972 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method. 19973 * Both are passed a {@link android.view.DragEvent} object that has a 19974 * {@link android.view.DragEvent#getAction()} value of 19975 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}. 19976 * </p> 19977 * <p> 19978 * Your application can invoke {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, 19979 * int) startDragAndDrop()} on any attached View object. The View object does not need to be 19980 * the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to be related 19981 * to the View the user selected for dragging. 19982 * </p> 19983 * @param data A {@link android.content.ClipData} object pointing to the data to be 19984 * transferred by the drag and drop operation. 19985 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the 19986 * drag shadow. 19987 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and 19988 * drop operation. This Object is put into every DragEvent object sent by the system during the 19989 * current drag. 19990 * <p> 19991 * myLocalState is a lightweight mechanism for the sending information from the dragged View 19992 * to the target Views. For example, it can contain flags that differentiate between a 19993 * a copy operation and a move operation. 19994 * </p> 19995 * @param flags Flags that control the drag and drop operation. No flags are currently defined, 19996 * so the parameter should be set to 0. 19997 * @return {@code true} if the method completes successfully, or 19998 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to 19999 * do a drag, and so no drag operation is in progress. 20000 */ 20001 public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder, 20002 Object myLocalState, int flags) { 20003 if (ViewDebug.DEBUG_DRAG) { 20004 Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags); 20005 } 20006 boolean okay = false; 20007 20008 Point shadowSize = new Point(); 20009 Point shadowTouchPoint = new Point(); 20010 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); 20011 20012 if ((shadowSize.x < 0) || (shadowSize.y < 0) || 20013 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { 20014 throw new IllegalStateException("Drag shadow dimensions must not be negative"); 20015 } 20016 20017 if (ViewDebug.DEBUG_DRAG) { 20018 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y 20019 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y); 20020 } 20021 if (mAttachInfo.mDragSurface != null) { 20022 mAttachInfo.mDragSurface.release(); 20023 } 20024 mAttachInfo.mDragSurface = new Surface(); 20025 try { 20026 mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, 20027 flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface); 20028 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" 20029 + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface); 20030 if (mAttachInfo.mDragToken != null) { 20031 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20032 try { 20033 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20034 shadowBuilder.onDrawShadow(canvas); 20035 } finally { 20036 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20037 } 20038 20039 final ViewRootImpl root = getViewRootImpl(); 20040 20041 // Cache the local state object for delivery with DragEvents 20042 root.setLocalDragState(myLocalState); 20043 20044 // repurpose 'shadowSize' for the last touch point 20045 root.getLastTouchPoint(shadowSize); 20046 20047 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken, 20048 shadowSize.x, shadowSize.y, 20049 shadowTouchPoint.x, shadowTouchPoint.y, data); 20050 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); 20051 } 20052 } catch (Exception e) { 20053 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); 20054 mAttachInfo.mDragSurface.destroy(); 20055 mAttachInfo.mDragSurface = null; 20056 } 20057 20058 return okay; 20059 } 20060 20061 /** 20062 * Cancels an ongoing drag and drop operation. 20063 * <p> 20064 * A {@link android.view.DragEvent} object with 20065 * {@link android.view.DragEvent#getAction()} value of 20066 * {@link android.view.DragEvent#ACTION_DRAG_ENDED} and 20067 * {@link android.view.DragEvent#getResult()} value of {@code false} 20068 * will be sent to every 20069 * View that received {@link android.view.DragEvent#ACTION_DRAG_STARTED} 20070 * even if they are not currently visible. 20071 * </p> 20072 * <p> 20073 * This method can be called on any View in the same window as the View on which 20074 * {@link #startDragAndDrop(ClipData, DragShadowBuilder, Object, int) startDragAndDrop} 20075 * was called. 20076 * </p> 20077 */ 20078 public final void cancelDragAndDrop() { 20079 if (ViewDebug.DEBUG_DRAG) { 20080 Log.d(VIEW_LOG_TAG, "cancelDragAndDrop"); 20081 } 20082 if (mAttachInfo.mDragToken != null) { 20083 try { 20084 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken); 20085 } catch (Exception e) { 20086 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e); 20087 } 20088 mAttachInfo.mDragToken = null; 20089 } else { 20090 Log.e(VIEW_LOG_TAG, "No active drag to cancel"); 20091 } 20092 } 20093 20094 public final void updateDragShadow(DragShadowBuilder shadowBuilder) { 20095 if (ViewDebug.DEBUG_DRAG) { 20096 Log.d(VIEW_LOG_TAG, "updateDragShadow"); 20097 } 20098 if (mAttachInfo.mDragToken != null) { 20099 try { 20100 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); 20101 try { 20102 canvas.drawColor(0, PorterDuff.Mode.CLEAR); 20103 shadowBuilder.onDrawShadow(canvas); 20104 } finally { 20105 mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); 20106 } 20107 } catch (Exception e) { 20108 Log.e(VIEW_LOG_TAG, "Unable to update drag shadow", e); 20109 } 20110 } else { 20111 Log.e(VIEW_LOG_TAG, "No active drag"); 20112 } 20113 } 20114 20115 /** 20116 * Starts a move from {startX, startY}, the amount of the movement will be the offset 20117 * between {startX, startY} and the new cursor positon. 20118 * @param startX horizontal coordinate where the move started. 20119 * @param startY vertical coordinate where the move started. 20120 * @return whether moving was started successfully. 20121 * @hide 20122 */ 20123 public final boolean startMovingTask(float startX, float startY) { 20124 if (ViewDebug.DEBUG_POSITIONING) { 20125 Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}"); 20126 } 20127 try { 20128 return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY); 20129 } catch (RemoteException e) { 20130 Log.e(VIEW_LOG_TAG, "Unable to start moving", e); 20131 } 20132 return false; 20133 } 20134 20135 /** 20136 * Handles drag events sent by the system following a call to 20137 * {@link android.view.View#startDragAndDrop(ClipData,DragShadowBuilder,Object,int) 20138 * startDragAndDrop()}. 20139 *<p> 20140 * When the system calls this method, it passes a 20141 * {@link android.view.DragEvent} object. A call to 20142 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined 20143 * in DragEvent. The method uses these to determine what is happening in the drag and drop 20144 * operation. 20145 * @param event The {@link android.view.DragEvent} sent by the system. 20146 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined 20147 * in DragEvent, indicating the type of drag event represented by this object. 20148 * @return {@code true} if the method was successful, otherwise {@code false}. 20149 * <p> 20150 * The method should return {@code true} in response to an action type of 20151 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current 20152 * operation. 20153 * </p> 20154 * <p> 20155 * The method should also return {@code true} in response to an action type of 20156 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or 20157 * {@code false} if it didn't. 20158 * </p> 20159 */ 20160 public boolean onDragEvent(DragEvent event) { 20161 return false; 20162 } 20163 20164 /** 20165 * Detects if this View is enabled and has a drag event listener. 20166 * If both are true, then it calls the drag event listener with the 20167 * {@link android.view.DragEvent} it received. If the drag event listener returns 20168 * {@code true}, then dispatchDragEvent() returns {@code true}. 20169 * <p> 20170 * For all other cases, the method calls the 20171 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler 20172 * method and returns its result. 20173 * </p> 20174 * <p> 20175 * This ensures that a drag event is always consumed, even if the View does not have a drag 20176 * event listener. However, if the View has a listener and the listener returns true, then 20177 * onDragEvent() is not called. 20178 * </p> 20179 */ 20180 public boolean dispatchDragEvent(DragEvent event) { 20181 ListenerInfo li = mListenerInfo; 20182 //noinspection SimplifiableIfStatement 20183 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED 20184 && li.mOnDragListener.onDrag(this, event)) { 20185 return true; 20186 } 20187 return onDragEvent(event); 20188 } 20189 20190 boolean canAcceptDrag() { 20191 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0; 20192 } 20193 20194 /** 20195 * This needs to be a better API (NOT ON VIEW) before it is exposed. If 20196 * it is ever exposed at all. 20197 * @hide 20198 */ 20199 public void onCloseSystemDialogs(String reason) { 20200 } 20201 20202 /** 20203 * Given a Drawable whose bounds have been set to draw into this view, 20204 * update a Region being computed for 20205 * {@link #gatherTransparentRegion(android.graphics.Region)} so 20206 * that any non-transparent parts of the Drawable are removed from the 20207 * given transparent region. 20208 * 20209 * @param dr The Drawable whose transparency is to be applied to the region. 20210 * @param region A Region holding the current transparency information, 20211 * where any parts of the region that are set are considered to be 20212 * transparent. On return, this region will be modified to have the 20213 * transparency information reduced by the corresponding parts of the 20214 * Drawable that are not transparent. 20215 * {@hide} 20216 */ 20217 public void applyDrawableToTransparentRegion(Drawable dr, Region region) { 20218 if (DBG) { 20219 Log.i("View", "Getting transparent region for: " + this); 20220 } 20221 final Region r = dr.getTransparentRegion(); 20222 final Rect db = dr.getBounds(); 20223 final AttachInfo attachInfo = mAttachInfo; 20224 if (r != null && attachInfo != null) { 20225 final int w = getRight()-getLeft(); 20226 final int h = getBottom()-getTop(); 20227 if (db.left > 0) { 20228 //Log.i("VIEW", "Drawable left " + db.left + " > view 0"); 20229 r.op(0, 0, db.left, h, Region.Op.UNION); 20230 } 20231 if (db.right < w) { 20232 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w); 20233 r.op(db.right, 0, w, h, Region.Op.UNION); 20234 } 20235 if (db.top > 0) { 20236 //Log.i("VIEW", "Drawable top " + db.top + " > view 0"); 20237 r.op(0, 0, w, db.top, Region.Op.UNION); 20238 } 20239 if (db.bottom < h) { 20240 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h); 20241 r.op(0, db.bottom, w, h, Region.Op.UNION); 20242 } 20243 final int[] location = attachInfo.mTransparentLocation; 20244 getLocationInWindow(location); 20245 r.translate(location[0], location[1]); 20246 region.op(r, Region.Op.INTERSECT); 20247 } else { 20248 region.op(db, Region.Op.DIFFERENCE); 20249 } 20250 } 20251 20252 private void checkForLongClick(int delayOffset, float x, float y) { 20253 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 20254 mHasPerformedLongPress = false; 20255 20256 if (mPendingCheckForLongPress == null) { 20257 mPendingCheckForLongPress = new CheckForLongPress(); 20258 } 20259 mPendingCheckForLongPress.setAnchor(x, y); 20260 mPendingCheckForLongPress.rememberWindowAttachCount(); 20261 postDelayed(mPendingCheckForLongPress, 20262 ViewConfiguration.getLongPressTimeout() - delayOffset); 20263 } 20264 } 20265 20266 /** 20267 * Inflate a view from an XML resource. This convenience method wraps the {@link 20268 * LayoutInflater} class, which provides a full range of options for view inflation. 20269 * 20270 * @param context The Context object for your activity or application. 20271 * @param resource The resource ID to inflate 20272 * @param root A view group that will be the parent. Used to properly inflate the 20273 * layout_* parameters. 20274 * @see LayoutInflater 20275 */ 20276 public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { 20277 LayoutInflater factory = LayoutInflater.from(context); 20278 return factory.inflate(resource, root); 20279 } 20280 20281 /** 20282 * Scroll the view with standard behavior for scrolling beyond the normal 20283 * content boundaries. Views that call this method should override 20284 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the 20285 * results of an over-scroll operation. 20286 * 20287 * Views can use this method to handle any touch or fling-based scrolling. 20288 * 20289 * @param deltaX Change in X in pixels 20290 * @param deltaY Change in Y in pixels 20291 * @param scrollX Current X scroll value in pixels before applying deltaX 20292 * @param scrollY Current Y scroll value in pixels before applying deltaY 20293 * @param scrollRangeX Maximum content scroll range along the X axis 20294 * @param scrollRangeY Maximum content scroll range along the Y axis 20295 * @param maxOverScrollX Number of pixels to overscroll by in either direction 20296 * along the X axis. 20297 * @param maxOverScrollY Number of pixels to overscroll by in either direction 20298 * along the Y axis. 20299 * @param isTouchEvent true if this scroll operation is the result of a touch event. 20300 * @return true if scrolling was clamped to an over-scroll boundary along either 20301 * axis, false otherwise. 20302 */ 20303 @SuppressWarnings({"UnusedParameters"}) 20304 protected boolean overScrollBy(int deltaX, int deltaY, 20305 int scrollX, int scrollY, 20306 int scrollRangeX, int scrollRangeY, 20307 int maxOverScrollX, int maxOverScrollY, 20308 boolean isTouchEvent) { 20309 final int overScrollMode = mOverScrollMode; 20310 final boolean canScrollHorizontal = 20311 computeHorizontalScrollRange() > computeHorizontalScrollExtent(); 20312 final boolean canScrollVertical = 20313 computeVerticalScrollRange() > computeVerticalScrollExtent(); 20314 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS || 20315 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal); 20316 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS || 20317 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical); 20318 20319 int newScrollX = scrollX + deltaX; 20320 if (!overScrollHorizontal) { 20321 maxOverScrollX = 0; 20322 } 20323 20324 int newScrollY = scrollY + deltaY; 20325 if (!overScrollVertical) { 20326 maxOverScrollY = 0; 20327 } 20328 20329 // Clamp values if at the limits and record 20330 final int left = -maxOverScrollX; 20331 final int right = maxOverScrollX + scrollRangeX; 20332 final int top = -maxOverScrollY; 20333 final int bottom = maxOverScrollY + scrollRangeY; 20334 20335 boolean clampedX = false; 20336 if (newScrollX > right) { 20337 newScrollX = right; 20338 clampedX = true; 20339 } else if (newScrollX < left) { 20340 newScrollX = left; 20341 clampedX = true; 20342 } 20343 20344 boolean clampedY = false; 20345 if (newScrollY > bottom) { 20346 newScrollY = bottom; 20347 clampedY = true; 20348 } else if (newScrollY < top) { 20349 newScrollY = top; 20350 clampedY = true; 20351 } 20352 20353 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY); 20354 20355 return clampedX || clampedY; 20356 } 20357 20358 /** 20359 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to 20360 * respond to the results of an over-scroll operation. 20361 * 20362 * @param scrollX New X scroll value in pixels 20363 * @param scrollY New Y scroll value in pixels 20364 * @param clampedX True if scrollX was clamped to an over-scroll boundary 20365 * @param clampedY True if scrollY was clamped to an over-scroll boundary 20366 */ 20367 protected void onOverScrolled(int scrollX, int scrollY, 20368 boolean clampedX, boolean clampedY) { 20369 // Intentionally empty. 20370 } 20371 20372 /** 20373 * Returns the over-scroll mode for this view. The result will be 20374 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 20375 * (allow over-scrolling only if the view content is larger than the container), 20376 * or {@link #OVER_SCROLL_NEVER}. 20377 * 20378 * @return This view's over-scroll mode. 20379 */ 20380 public int getOverScrollMode() { 20381 return mOverScrollMode; 20382 } 20383 20384 /** 20385 * Set the over-scroll mode for this view. Valid over-scroll modes are 20386 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} 20387 * (allow over-scrolling only if the view content is larger than the container), 20388 * or {@link #OVER_SCROLL_NEVER}. 20389 * 20390 * Setting the over-scroll mode of a view will have an effect only if the 20391 * view is capable of scrolling. 20392 * 20393 * @param overScrollMode The new over-scroll mode for this view. 20394 */ 20395 public void setOverScrollMode(int overScrollMode) { 20396 if (overScrollMode != OVER_SCROLL_ALWAYS && 20397 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS && 20398 overScrollMode != OVER_SCROLL_NEVER) { 20399 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode); 20400 } 20401 mOverScrollMode = overScrollMode; 20402 } 20403 20404 /** 20405 * Enable or disable nested scrolling for this view. 20406 * 20407 * <p>If this property is set to true the view will be permitted to initiate nested 20408 * scrolling operations with a compatible parent view in the current hierarchy. If this 20409 * view does not implement nested scrolling this will have no effect. Disabling nested scrolling 20410 * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping} 20411 * the nested scroll.</p> 20412 * 20413 * @param enabled true to enable nested scrolling, false to disable 20414 * 20415 * @see #isNestedScrollingEnabled() 20416 */ 20417 public void setNestedScrollingEnabled(boolean enabled) { 20418 if (enabled) { 20419 mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED; 20420 } else { 20421 stopNestedScroll(); 20422 mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED; 20423 } 20424 } 20425 20426 /** 20427 * Returns true if nested scrolling is enabled for this view. 20428 * 20429 * <p>If nested scrolling is enabled and this View class implementation supports it, 20430 * this view will act as a nested scrolling child view when applicable, forwarding data 20431 * about the scroll operation in progress to a compatible and cooperating nested scrolling 20432 * parent.</p> 20433 * 20434 * @return true if nested scrolling is enabled 20435 * 20436 * @see #setNestedScrollingEnabled(boolean) 20437 */ 20438 public boolean isNestedScrollingEnabled() { 20439 return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) == 20440 PFLAG3_NESTED_SCROLLING_ENABLED; 20441 } 20442 20443 /** 20444 * Begin a nestable scroll operation along the given axes. 20445 * 20446 * <p>A view starting a nested scroll promises to abide by the following contract:</p> 20447 * 20448 * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case 20449 * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}. 20450 * In the case of touch scrolling the nested scroll will be terminated automatically in 20451 * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}. 20452 * In the event of programmatic scrolling the caller must explicitly call 20453 * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p> 20454 * 20455 * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found. 20456 * If it returns false the caller may ignore the rest of this contract until the next scroll. 20457 * Calling startNestedScroll while a nested scroll is already in progress will return true.</p> 20458 * 20459 * <p>At each incremental step of the scroll the caller should invoke 20460 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} 20461 * once it has calculated the requested scrolling delta. If it returns true the nested scrolling 20462 * parent at least partially consumed the scroll and the caller should adjust the amount it 20463 * scrolls by.</p> 20464 * 20465 * <p>After applying the remainder of the scroll delta the caller should invoke 20466 * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing 20467 * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat 20468 * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}. 20469 * </p> 20470 * 20471 * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or 20472 * {@link #SCROLL_AXIS_VERTICAL}. 20473 * @return true if a cooperative parent was found and nested scrolling has been enabled for 20474 * the current gesture. 20475 * 20476 * @see #stopNestedScroll() 20477 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 20478 * @see #dispatchNestedScroll(int, int, int, int, int[]) 20479 */ 20480 public boolean startNestedScroll(int axes) { 20481 if (hasNestedScrollingParent()) { 20482 // Already in progress 20483 return true; 20484 } 20485 if (isNestedScrollingEnabled()) { 20486 ViewParent p = getParent(); 20487 View child = this; 20488 while (p != null) { 20489 try { 20490 if (p.onStartNestedScroll(child, this, axes)) { 20491 mNestedScrollingParent = p; 20492 p.onNestedScrollAccepted(child, this, axes); 20493 return true; 20494 } 20495 } catch (AbstractMethodError e) { 20496 Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " + 20497 "method onStartNestedScroll", e); 20498 // Allow the search upward to continue 20499 } 20500 if (p instanceof View) { 20501 child = (View) p; 20502 } 20503 p = p.getParent(); 20504 } 20505 } 20506 return false; 20507 } 20508 20509 /** 20510 * Stop a nested scroll in progress. 20511 * 20512 * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p> 20513 * 20514 * @see #startNestedScroll(int) 20515 */ 20516 public void stopNestedScroll() { 20517 if (mNestedScrollingParent != null) { 20518 mNestedScrollingParent.onStopNestedScroll(this); 20519 mNestedScrollingParent = null; 20520 } 20521 } 20522 20523 /** 20524 * Returns true if this view has a nested scrolling parent. 20525 * 20526 * <p>The presence of a nested scrolling parent indicates that this view has initiated 20527 * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p> 20528 * 20529 * @return whether this view has a nested scrolling parent 20530 */ 20531 public boolean hasNestedScrollingParent() { 20532 return mNestedScrollingParent != null; 20533 } 20534 20535 /** 20536 * Dispatch one step of a nested scroll in progress. 20537 * 20538 * <p>Implementations of views that support nested scrolling should call this to report 20539 * info about a scroll in progress to the current nested scrolling parent. If a nested scroll 20540 * is not currently in progress or nested scrolling is not 20541 * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p> 20542 * 20543 * <p>Compatible View implementations should also call 20544 * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before 20545 * consuming a component of the scroll event themselves.</p> 20546 * 20547 * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step 20548 * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step 20549 * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view 20550 * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view 20551 * @param offsetInWindow Optional. If not null, on return this will contain the offset 20552 * in local view coordinates of this view from before this operation 20553 * to after it completes. View implementations may use this to adjust 20554 * expected input coordinate tracking. 20555 * @return true if the event was dispatched, false if it could not be dispatched. 20556 * @see #dispatchNestedPreScroll(int, int, int[], int[]) 20557 */ 20558 public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, 20559 int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) { 20560 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 20561 if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) { 20562 int startX = 0; 20563 int startY = 0; 20564 if (offsetInWindow != null) { 20565 getLocationInWindow(offsetInWindow); 20566 startX = offsetInWindow[0]; 20567 startY = offsetInWindow[1]; 20568 } 20569 20570 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed, 20571 dxUnconsumed, dyUnconsumed); 20572 20573 if (offsetInWindow != null) { 20574 getLocationInWindow(offsetInWindow); 20575 offsetInWindow[0] -= startX; 20576 offsetInWindow[1] -= startY; 20577 } 20578 return true; 20579 } else if (offsetInWindow != null) { 20580 // No motion, no dispatch. Keep offsetInWindow up to date. 20581 offsetInWindow[0] = 0; 20582 offsetInWindow[1] = 0; 20583 } 20584 } 20585 return false; 20586 } 20587 20588 /** 20589 * Dispatch one step of a nested scroll in progress before this view consumes any portion of it. 20590 * 20591 * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch. 20592 * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested 20593 * scrolling operation to consume some or all of the scroll operation before the child view 20594 * consumes it.</p> 20595 * 20596 * @param dx Horizontal scroll distance in pixels 20597 * @param dy Vertical scroll distance in pixels 20598 * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx 20599 * and consumed[1] the consumed dy. 20600 * @param offsetInWindow Optional. If not null, on return this will contain the offset 20601 * in local view coordinates of this view from before this operation 20602 * to after it completes. View implementations may use this to adjust 20603 * expected input coordinate tracking. 20604 * @return true if the parent consumed some or all of the scroll delta 20605 * @see #dispatchNestedScroll(int, int, int, int, int[]) 20606 */ 20607 public boolean dispatchNestedPreScroll(int dx, int dy, 20608 @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) { 20609 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 20610 if (dx != 0 || dy != 0) { 20611 int startX = 0; 20612 int startY = 0; 20613 if (offsetInWindow != null) { 20614 getLocationInWindow(offsetInWindow); 20615 startX = offsetInWindow[0]; 20616 startY = offsetInWindow[1]; 20617 } 20618 20619 if (consumed == null) { 20620 if (mTempNestedScrollConsumed == null) { 20621 mTempNestedScrollConsumed = new int[2]; 20622 } 20623 consumed = mTempNestedScrollConsumed; 20624 } 20625 consumed[0] = 0; 20626 consumed[1] = 0; 20627 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed); 20628 20629 if (offsetInWindow != null) { 20630 getLocationInWindow(offsetInWindow); 20631 offsetInWindow[0] -= startX; 20632 offsetInWindow[1] -= startY; 20633 } 20634 return consumed[0] != 0 || consumed[1] != 0; 20635 } else if (offsetInWindow != null) { 20636 offsetInWindow[0] = 0; 20637 offsetInWindow[1] = 0; 20638 } 20639 } 20640 return false; 20641 } 20642 20643 /** 20644 * Dispatch a fling to a nested scrolling parent. 20645 * 20646 * <p>This method should be used to indicate that a nested scrolling child has detected 20647 * suitable conditions for a fling. Generally this means that a touch scroll has ended with a 20648 * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds 20649 * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity} 20650 * along a scrollable axis.</p> 20651 * 20652 * <p>If a nested scrolling child view would normally fling but it is at the edge of 20653 * its own content, it can use this method to delegate the fling to its nested scrolling 20654 * parent instead. The parent may optionally consume the fling or observe a child fling.</p> 20655 * 20656 * @param velocityX Horizontal fling velocity in pixels per second 20657 * @param velocityY Vertical fling velocity in pixels per second 20658 * @param consumed true if the child consumed the fling, false otherwise 20659 * @return true if the nested scrolling parent consumed or otherwise reacted to the fling 20660 */ 20661 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 20662 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 20663 return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed); 20664 } 20665 return false; 20666 } 20667 20668 /** 20669 * Dispatch a fling to a nested scrolling parent before it is processed by this view. 20670 * 20671 * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch 20672 * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code> 20673 * offsets an opportunity for the parent view in a nested fling to fully consume the fling 20674 * before the child view consumes it. If this method returns <code>true</code>, a nested 20675 * parent view consumed the fling and this view should not scroll as a result.</p> 20676 * 20677 * <p>For a better user experience, only one view in a nested scrolling chain should consume 20678 * the fling at a time. If a parent view consumed the fling this method will return false. 20679 * Custom view implementations should account for this in two ways:</p> 20680 * 20681 * <ul> 20682 * <li>If a custom view is paged and needs to settle to a fixed page-point, do not 20683 * call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid 20684 * position regardless.</li> 20685 * <li>If a nested parent does consume the fling, this view should not scroll at all, 20686 * even to settle back to a valid idle position.</li> 20687 * </ul> 20688 * 20689 * <p>Views should also not offer fling velocities to nested parent views along an axis 20690 * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView} 20691 * should not offer a horizontal fling velocity to its parents since scrolling along that 20692 * axis is not permitted and carrying velocity along that motion does not make sense.</p> 20693 * 20694 * @param velocityX Horizontal fling velocity in pixels per second 20695 * @param velocityY Vertical fling velocity in pixels per second 20696 * @return true if a nested scrolling parent consumed the fling 20697 */ 20698 public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 20699 if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { 20700 return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY); 20701 } 20702 return false; 20703 } 20704 20705 /** 20706 * Gets a scale factor that determines the distance the view should scroll 20707 * vertically in response to {@link MotionEvent#ACTION_SCROLL}. 20708 * @return The vertical scroll scale factor. 20709 * @hide 20710 */ 20711 protected float getVerticalScrollFactor() { 20712 if (mVerticalScrollFactor == 0) { 20713 TypedValue outValue = new TypedValue(); 20714 if (!mContext.getTheme().resolveAttribute( 20715 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) { 20716 throw new IllegalStateException( 20717 "Expected theme to define listPreferredItemHeight."); 20718 } 20719 mVerticalScrollFactor = outValue.getDimension( 20720 mContext.getResources().getDisplayMetrics()); 20721 } 20722 return mVerticalScrollFactor; 20723 } 20724 20725 /** 20726 * Gets a scale factor that determines the distance the view should scroll 20727 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}. 20728 * @return The horizontal scroll scale factor. 20729 * @hide 20730 */ 20731 protected float getHorizontalScrollFactor() { 20732 // TODO: Should use something else. 20733 return getVerticalScrollFactor(); 20734 } 20735 20736 /** 20737 * Return the value specifying the text direction or policy that was set with 20738 * {@link #setTextDirection(int)}. 20739 * 20740 * @return the defined text direction. It can be one of: 20741 * 20742 * {@link #TEXT_DIRECTION_INHERIT}, 20743 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 20744 * {@link #TEXT_DIRECTION_ANY_RTL}, 20745 * {@link #TEXT_DIRECTION_LTR}, 20746 * {@link #TEXT_DIRECTION_RTL}, 20747 * {@link #TEXT_DIRECTION_LOCALE}, 20748 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 20749 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 20750 * 20751 * @attr ref android.R.styleable#View_textDirection 20752 * 20753 * @hide 20754 */ 20755 @ViewDebug.ExportedProperty(category = "text", mapping = { 20756 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 20757 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 20758 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 20759 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 20760 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 20761 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 20762 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 20763 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 20764 }) 20765 public int getRawTextDirection() { 20766 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT; 20767 } 20768 20769 /** 20770 * Set the text direction. 20771 * 20772 * @param textDirection the direction to set. Should be one of: 20773 * 20774 * {@link #TEXT_DIRECTION_INHERIT}, 20775 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 20776 * {@link #TEXT_DIRECTION_ANY_RTL}, 20777 * {@link #TEXT_DIRECTION_LTR}, 20778 * {@link #TEXT_DIRECTION_RTL}, 20779 * {@link #TEXT_DIRECTION_LOCALE} 20780 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 20781 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}, 20782 * 20783 * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution 20784 * proceeds up the parent chain of the view to get the value. If there is no parent, then it will 20785 * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. 20786 * 20787 * @attr ref android.R.styleable#View_textDirection 20788 */ 20789 public void setTextDirection(int textDirection) { 20790 if (getRawTextDirection() != textDirection) { 20791 // Reset the current text direction and the resolved one 20792 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK; 20793 resetResolvedTextDirection(); 20794 // Set the new text direction 20795 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK); 20796 // Do resolution 20797 resolveTextDirection(); 20798 // Notify change 20799 onRtlPropertiesChanged(getLayoutDirection()); 20800 // Refresh 20801 requestLayout(); 20802 invalidate(true); 20803 } 20804 } 20805 20806 /** 20807 * Return the resolved text direction. 20808 * 20809 * @return the resolved text direction. Returns one of: 20810 * 20811 * {@link #TEXT_DIRECTION_FIRST_STRONG}, 20812 * {@link #TEXT_DIRECTION_ANY_RTL}, 20813 * {@link #TEXT_DIRECTION_LTR}, 20814 * {@link #TEXT_DIRECTION_RTL}, 20815 * {@link #TEXT_DIRECTION_LOCALE}, 20816 * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR}, 20817 * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL} 20818 * 20819 * @attr ref android.R.styleable#View_textDirection 20820 */ 20821 @ViewDebug.ExportedProperty(category = "text", mapping = { 20822 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"), 20823 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"), 20824 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"), 20825 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"), 20826 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"), 20827 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"), 20828 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"), 20829 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL") 20830 }) 20831 public int getTextDirection() { 20832 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; 20833 } 20834 20835 /** 20836 * Resolve the text direction. 20837 * 20838 * @return true if resolution has been done, false otherwise. 20839 * 20840 * @hide 20841 */ 20842 public boolean resolveTextDirection() { 20843 // Reset any previous text direction resolution 20844 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 20845 20846 if (hasRtlSupport()) { 20847 // Set resolved text direction flag depending on text direction flag 20848 final int textDirection = getRawTextDirection(); 20849 switch(textDirection) { 20850 case TEXT_DIRECTION_INHERIT: 20851 if (!canResolveTextDirection()) { 20852 // We cannot do the resolution if there is no parent, so use the default one 20853 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20854 // Resolution will need to happen again later 20855 return false; 20856 } 20857 20858 // Parent has not yet resolved, so we still return the default 20859 try { 20860 if (!mParent.isTextDirectionResolved()) { 20861 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20862 // Resolution will need to happen again later 20863 return false; 20864 } 20865 } catch (AbstractMethodError e) { 20866 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 20867 " does not fully implement ViewParent", e); 20868 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED | 20869 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20870 return true; 20871 } 20872 20873 // Set current resolved direction to the same value as the parent's one 20874 int parentResolvedDirection; 20875 try { 20876 parentResolvedDirection = mParent.getTextDirection(); 20877 } catch (AbstractMethodError e) { 20878 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 20879 " does not fully implement ViewParent", e); 20880 parentResolvedDirection = TEXT_DIRECTION_LTR; 20881 } 20882 switch (parentResolvedDirection) { 20883 case TEXT_DIRECTION_FIRST_STRONG: 20884 case TEXT_DIRECTION_ANY_RTL: 20885 case TEXT_DIRECTION_LTR: 20886 case TEXT_DIRECTION_RTL: 20887 case TEXT_DIRECTION_LOCALE: 20888 case TEXT_DIRECTION_FIRST_STRONG_LTR: 20889 case TEXT_DIRECTION_FIRST_STRONG_RTL: 20890 mPrivateFlags2 |= 20891 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 20892 break; 20893 default: 20894 // Default resolved direction is "first strong" heuristic 20895 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20896 } 20897 break; 20898 case TEXT_DIRECTION_FIRST_STRONG: 20899 case TEXT_DIRECTION_ANY_RTL: 20900 case TEXT_DIRECTION_LTR: 20901 case TEXT_DIRECTION_RTL: 20902 case TEXT_DIRECTION_LOCALE: 20903 case TEXT_DIRECTION_FIRST_STRONG_LTR: 20904 case TEXT_DIRECTION_FIRST_STRONG_RTL: 20905 // Resolved direction is the same as text direction 20906 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT); 20907 break; 20908 default: 20909 // Default resolved direction is "first strong" heuristic 20910 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20911 } 20912 } else { 20913 // Default resolved direction is "first strong" heuristic 20914 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20915 } 20916 20917 // Set to resolved 20918 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED; 20919 return true; 20920 } 20921 20922 /** 20923 * Check if text direction resolution can be done. 20924 * 20925 * @return true if text direction resolution can be done otherwise return false. 20926 */ 20927 public boolean canResolveTextDirection() { 20928 switch (getRawTextDirection()) { 20929 case TEXT_DIRECTION_INHERIT: 20930 if (mParent != null) { 20931 try { 20932 return mParent.canResolveTextDirection(); 20933 } catch (AbstractMethodError e) { 20934 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 20935 " does not fully implement ViewParent", e); 20936 } 20937 } 20938 return false; 20939 20940 default: 20941 return true; 20942 } 20943 } 20944 20945 /** 20946 * Reset resolved text direction. Text direction will be resolved during a call to 20947 * {@link #onMeasure(int, int)}. 20948 * 20949 * @hide 20950 */ 20951 public void resetResolvedTextDirection() { 20952 // Reset any previous text direction resolution 20953 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK); 20954 // Set to default value 20955 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT; 20956 } 20957 20958 /** 20959 * @return true if text direction is inherited. 20960 * 20961 * @hide 20962 */ 20963 public boolean isTextDirectionInherited() { 20964 return (getRawTextDirection() == TEXT_DIRECTION_INHERIT); 20965 } 20966 20967 /** 20968 * @return true if text direction is resolved. 20969 */ 20970 public boolean isTextDirectionResolved() { 20971 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED; 20972 } 20973 20974 /** 20975 * Return the value specifying the text alignment or policy that was set with 20976 * {@link #setTextAlignment(int)}. 20977 * 20978 * @return the defined text alignment. It can be one of: 20979 * 20980 * {@link #TEXT_ALIGNMENT_INHERIT}, 20981 * {@link #TEXT_ALIGNMENT_GRAVITY}, 20982 * {@link #TEXT_ALIGNMENT_CENTER}, 20983 * {@link #TEXT_ALIGNMENT_TEXT_START}, 20984 * {@link #TEXT_ALIGNMENT_TEXT_END}, 20985 * {@link #TEXT_ALIGNMENT_VIEW_START}, 20986 * {@link #TEXT_ALIGNMENT_VIEW_END} 20987 * 20988 * @attr ref android.R.styleable#View_textAlignment 20989 * 20990 * @hide 20991 */ 20992 @ViewDebug.ExportedProperty(category = "text", mapping = { 20993 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 20994 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 20995 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 20996 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 20997 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 20998 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 20999 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21000 }) 21001 @TextAlignment 21002 public int getRawTextAlignment() { 21003 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT; 21004 } 21005 21006 /** 21007 * Set the text alignment. 21008 * 21009 * @param textAlignment The text alignment to set. Should be one of 21010 * 21011 * {@link #TEXT_ALIGNMENT_INHERIT}, 21012 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21013 * {@link #TEXT_ALIGNMENT_CENTER}, 21014 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21015 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21016 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21017 * {@link #TEXT_ALIGNMENT_VIEW_END} 21018 * 21019 * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution 21020 * proceeds up the parent chain of the view to get the value. If there is no parent, then it 21021 * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}. 21022 * 21023 * @attr ref android.R.styleable#View_textAlignment 21024 */ 21025 public void setTextAlignment(@TextAlignment int textAlignment) { 21026 if (textAlignment != getRawTextAlignment()) { 21027 // Reset the current and resolved text alignment 21028 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK; 21029 resetResolvedTextAlignment(); 21030 // Set the new text alignment 21031 mPrivateFlags2 |= 21032 ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK); 21033 // Do resolution 21034 resolveTextAlignment(); 21035 // Notify change 21036 onRtlPropertiesChanged(getLayoutDirection()); 21037 // Refresh 21038 requestLayout(); 21039 invalidate(true); 21040 } 21041 } 21042 21043 /** 21044 * Return the resolved text alignment. 21045 * 21046 * @return the resolved text alignment. Returns one of: 21047 * 21048 * {@link #TEXT_ALIGNMENT_GRAVITY}, 21049 * {@link #TEXT_ALIGNMENT_CENTER}, 21050 * {@link #TEXT_ALIGNMENT_TEXT_START}, 21051 * {@link #TEXT_ALIGNMENT_TEXT_END}, 21052 * {@link #TEXT_ALIGNMENT_VIEW_START}, 21053 * {@link #TEXT_ALIGNMENT_VIEW_END} 21054 * 21055 * @attr ref android.R.styleable#View_textAlignment 21056 */ 21057 @ViewDebug.ExportedProperty(category = "text", mapping = { 21058 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 21059 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"), 21060 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"), 21061 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"), 21062 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"), 21063 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"), 21064 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END") 21065 }) 21066 @TextAlignment 21067 public int getTextAlignment() { 21068 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> 21069 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT; 21070 } 21071 21072 /** 21073 * Resolve the text alignment. 21074 * 21075 * @return true if resolution has been done, false otherwise. 21076 * 21077 * @hide 21078 */ 21079 public boolean resolveTextAlignment() { 21080 // Reset any previous text alignment resolution 21081 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21082 21083 if (hasRtlSupport()) { 21084 // Set resolved text alignment flag depending on text alignment flag 21085 final int textAlignment = getRawTextAlignment(); 21086 switch (textAlignment) { 21087 case TEXT_ALIGNMENT_INHERIT: 21088 // Check if we can resolve the text alignment 21089 if (!canResolveTextAlignment()) { 21090 // We cannot do the resolution if there is no parent so use the default 21091 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21092 // Resolution will need to happen again later 21093 return false; 21094 } 21095 21096 // Parent has not yet resolved, so we still return the default 21097 try { 21098 if (!mParent.isTextAlignmentResolved()) { 21099 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21100 // Resolution will need to happen again later 21101 return false; 21102 } 21103 } catch (AbstractMethodError e) { 21104 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21105 " does not fully implement ViewParent", e); 21106 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED | 21107 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21108 return true; 21109 } 21110 21111 int parentResolvedTextAlignment; 21112 try { 21113 parentResolvedTextAlignment = mParent.getTextAlignment(); 21114 } catch (AbstractMethodError e) { 21115 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21116 " does not fully implement ViewParent", e); 21117 parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY; 21118 } 21119 switch (parentResolvedTextAlignment) { 21120 case TEXT_ALIGNMENT_GRAVITY: 21121 case TEXT_ALIGNMENT_TEXT_START: 21122 case TEXT_ALIGNMENT_TEXT_END: 21123 case TEXT_ALIGNMENT_CENTER: 21124 case TEXT_ALIGNMENT_VIEW_START: 21125 case TEXT_ALIGNMENT_VIEW_END: 21126 // Resolved text alignment is the same as the parent resolved 21127 // text alignment 21128 mPrivateFlags2 |= 21129 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21130 break; 21131 default: 21132 // Use default resolved text alignment 21133 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21134 } 21135 break; 21136 case TEXT_ALIGNMENT_GRAVITY: 21137 case TEXT_ALIGNMENT_TEXT_START: 21138 case TEXT_ALIGNMENT_TEXT_END: 21139 case TEXT_ALIGNMENT_CENTER: 21140 case TEXT_ALIGNMENT_VIEW_START: 21141 case TEXT_ALIGNMENT_VIEW_END: 21142 // Resolved text alignment is the same as text alignment 21143 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT); 21144 break; 21145 default: 21146 // Use default resolved text alignment 21147 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21148 } 21149 } else { 21150 // Use default resolved text alignment 21151 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21152 } 21153 21154 // Set the resolved 21155 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21156 return true; 21157 } 21158 21159 /** 21160 * Check if text alignment resolution can be done. 21161 * 21162 * @return true if text alignment resolution can be done otherwise return false. 21163 */ 21164 public boolean canResolveTextAlignment() { 21165 switch (getRawTextAlignment()) { 21166 case TEXT_DIRECTION_INHERIT: 21167 if (mParent != null) { 21168 try { 21169 return mParent.canResolveTextAlignment(); 21170 } catch (AbstractMethodError e) { 21171 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() + 21172 " does not fully implement ViewParent", e); 21173 } 21174 } 21175 return false; 21176 21177 default: 21178 return true; 21179 } 21180 } 21181 21182 /** 21183 * Reset resolved text alignment. Text alignment will be resolved during a call to 21184 * {@link #onMeasure(int, int)}. 21185 * 21186 * @hide 21187 */ 21188 public void resetResolvedTextAlignment() { 21189 // Reset any previous text alignment resolution 21190 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK); 21191 // Set to default 21192 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT; 21193 } 21194 21195 /** 21196 * @return true if text alignment is inherited. 21197 * 21198 * @hide 21199 */ 21200 public boolean isTextAlignmentInherited() { 21201 return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT); 21202 } 21203 21204 /** 21205 * @return true if text alignment is resolved. 21206 */ 21207 public boolean isTextAlignmentResolved() { 21208 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED; 21209 } 21210 21211 /** 21212 * Generate a value suitable for use in {@link #setId(int)}. 21213 * This value will not collide with ID values generated at build time by aapt for R.id. 21214 * 21215 * @return a generated ID value 21216 */ 21217 public static int generateViewId() { 21218 for (;;) { 21219 final int result = sNextGeneratedId.get(); 21220 // aapt-generated IDs have the high byte nonzero; clamp to the range under that. 21221 int newValue = result + 1; 21222 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0. 21223 if (sNextGeneratedId.compareAndSet(result, newValue)) { 21224 return result; 21225 } 21226 } 21227 } 21228 21229 /** 21230 * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions. 21231 * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and 21232 * a normal View or a ViewGroup with 21233 * {@link android.view.ViewGroup#isTransitionGroup()} true. 21234 * @hide 21235 */ 21236 public void captureTransitioningViews(List<View> transitioningViews) { 21237 if (getVisibility() == View.VISIBLE) { 21238 transitioningViews.add(this); 21239 } 21240 } 21241 21242 /** 21243 * Adds all Views that have {@link #getTransitionName()} non-null to namedElements. 21244 * @param namedElements Will contain all Views in the hierarchy having a transitionName. 21245 * @hide 21246 */ 21247 public void findNamedViews(Map<String, View> namedElements) { 21248 if (getVisibility() == VISIBLE || mGhostView != null) { 21249 String transitionName = getTransitionName(); 21250 if (transitionName != null) { 21251 namedElements.put(transitionName, this); 21252 } 21253 } 21254 } 21255 21256 /** @hide */ 21257 public int getPointerShape(MotionEvent event, float x, float y) { 21258 final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK); 21259 switch (value) { 21260 case PFLAG3_POINTER_ICON_NOT_SPECIFIED: 21261 return PointerIcon.STYLE_NOT_SPECIFIED; 21262 case PFLAG3_POINTER_ICON_NULL: 21263 return PointerIcon.STYLE_NULL; 21264 case PFLAG3_POINTER_ICON_CUSTOM: 21265 return PointerIcon.STYLE_CUSTOM; 21266 default: 21267 return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT) 21268 + PointerIcon.STYLE_ARROW; 21269 } 21270 } 21271 21272 /** @hide */ 21273 public void setPointerShape(int pointerShape) { 21274 int newValue; 21275 if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) { 21276 newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED; 21277 } else if (pointerShape == PointerIcon.STYLE_NULL) { 21278 newValue = PFLAG3_POINTER_ICON_NULL; 21279 } else if (pointerShape == PointerIcon.STYLE_CUSTOM) { 21280 newValue = PFLAG3_POINTER_ICON_CUSTOM; 21281 } else if (pointerShape >= PointerIcon.STYLE_ARROW 21282 && pointerShape <= PointerIcon.STYLE_GRABBING) { 21283 newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT) 21284 + PFLAG3_POINTER_ICON_VALUE_START; 21285 } else { 21286 Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified."); 21287 return; 21288 } 21289 if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) { 21290 mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue; 21291 } 21292 } 21293 21294 // 21295 // Properties 21296 // 21297 /** 21298 * A Property wrapper around the <code>alpha</code> functionality handled by the 21299 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods. 21300 */ 21301 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") { 21302 @Override 21303 public void setValue(View object, float value) { 21304 object.setAlpha(value); 21305 } 21306 21307 @Override 21308 public Float get(View object) { 21309 return object.getAlpha(); 21310 } 21311 }; 21312 21313 /** 21314 * A Property wrapper around the <code>translationX</code> functionality handled by the 21315 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods. 21316 */ 21317 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") { 21318 @Override 21319 public void setValue(View object, float value) { 21320 object.setTranslationX(value); 21321 } 21322 21323 @Override 21324 public Float get(View object) { 21325 return object.getTranslationX(); 21326 } 21327 }; 21328 21329 /** 21330 * A Property wrapper around the <code>translationY</code> functionality handled by the 21331 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods. 21332 */ 21333 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") { 21334 @Override 21335 public void setValue(View object, float value) { 21336 object.setTranslationY(value); 21337 } 21338 21339 @Override 21340 public Float get(View object) { 21341 return object.getTranslationY(); 21342 } 21343 }; 21344 21345 /** 21346 * A Property wrapper around the <code>translationZ</code> functionality handled by the 21347 * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods. 21348 */ 21349 public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") { 21350 @Override 21351 public void setValue(View object, float value) { 21352 object.setTranslationZ(value); 21353 } 21354 21355 @Override 21356 public Float get(View object) { 21357 return object.getTranslationZ(); 21358 } 21359 }; 21360 21361 /** 21362 * A Property wrapper around the <code>x</code> functionality handled by the 21363 * {@link View#setX(float)} and {@link View#getX()} methods. 21364 */ 21365 public static final Property<View, Float> X = new FloatProperty<View>("x") { 21366 @Override 21367 public void setValue(View object, float value) { 21368 object.setX(value); 21369 } 21370 21371 @Override 21372 public Float get(View object) { 21373 return object.getX(); 21374 } 21375 }; 21376 21377 /** 21378 * A Property wrapper around the <code>y</code> functionality handled by the 21379 * {@link View#setY(float)} and {@link View#getY()} methods. 21380 */ 21381 public static final Property<View, Float> Y = new FloatProperty<View>("y") { 21382 @Override 21383 public void setValue(View object, float value) { 21384 object.setY(value); 21385 } 21386 21387 @Override 21388 public Float get(View object) { 21389 return object.getY(); 21390 } 21391 }; 21392 21393 /** 21394 * A Property wrapper around the <code>z</code> functionality handled by the 21395 * {@link View#setZ(float)} and {@link View#getZ()} methods. 21396 */ 21397 public static final Property<View, Float> Z = new FloatProperty<View>("z") { 21398 @Override 21399 public void setValue(View object, float value) { 21400 object.setZ(value); 21401 } 21402 21403 @Override 21404 public Float get(View object) { 21405 return object.getZ(); 21406 } 21407 }; 21408 21409 /** 21410 * A Property wrapper around the <code>rotation</code> functionality handled by the 21411 * {@link View#setRotation(float)} and {@link View#getRotation()} methods. 21412 */ 21413 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") { 21414 @Override 21415 public void setValue(View object, float value) { 21416 object.setRotation(value); 21417 } 21418 21419 @Override 21420 public Float get(View object) { 21421 return object.getRotation(); 21422 } 21423 }; 21424 21425 /** 21426 * A Property wrapper around the <code>rotationX</code> functionality handled by the 21427 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods. 21428 */ 21429 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") { 21430 @Override 21431 public void setValue(View object, float value) { 21432 object.setRotationX(value); 21433 } 21434 21435 @Override 21436 public Float get(View object) { 21437 return object.getRotationX(); 21438 } 21439 }; 21440 21441 /** 21442 * A Property wrapper around the <code>rotationY</code> functionality handled by the 21443 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods. 21444 */ 21445 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") { 21446 @Override 21447 public void setValue(View object, float value) { 21448 object.setRotationY(value); 21449 } 21450 21451 @Override 21452 public Float get(View object) { 21453 return object.getRotationY(); 21454 } 21455 }; 21456 21457 /** 21458 * A Property wrapper around the <code>scaleX</code> functionality handled by the 21459 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods. 21460 */ 21461 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") { 21462 @Override 21463 public void setValue(View object, float value) { 21464 object.setScaleX(value); 21465 } 21466 21467 @Override 21468 public Float get(View object) { 21469 return object.getScaleX(); 21470 } 21471 }; 21472 21473 /** 21474 * A Property wrapper around the <code>scaleY</code> functionality handled by the 21475 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods. 21476 */ 21477 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") { 21478 @Override 21479 public void setValue(View object, float value) { 21480 object.setScaleY(value); 21481 } 21482 21483 @Override 21484 public Float get(View object) { 21485 return object.getScaleY(); 21486 } 21487 }; 21488 21489 /** 21490 * A MeasureSpec encapsulates the layout requirements passed from parent to child. 21491 * Each MeasureSpec represents a requirement for either the width or the height. 21492 * A MeasureSpec is comprised of a size and a mode. There are three possible 21493 * modes: 21494 * <dl> 21495 * <dt>UNSPECIFIED</dt> 21496 * <dd> 21497 * The parent has not imposed any constraint on the child. It can be whatever size 21498 * it wants. 21499 * </dd> 21500 * 21501 * <dt>EXACTLY</dt> 21502 * <dd> 21503 * The parent has determined an exact size for the child. The child is going to be 21504 * given those bounds regardless of how big it wants to be. 21505 * </dd> 21506 * 21507 * <dt>AT_MOST</dt> 21508 * <dd> 21509 * The child can be as large as it wants up to the specified size. 21510 * </dd> 21511 * </dl> 21512 * 21513 * MeasureSpecs are implemented as ints to reduce object allocation. This class 21514 * is provided to pack and unpack the <size, mode> tuple into the int. 21515 */ 21516 public static class MeasureSpec { 21517 private static final int MODE_SHIFT = 30; 21518 private static final int MODE_MASK = 0x3 << MODE_SHIFT; 21519 21520 /** 21521 * Measure specification mode: The parent has not imposed any constraint 21522 * on the child. It can be whatever size it wants. 21523 */ 21524 public static final int UNSPECIFIED = 0 << MODE_SHIFT; 21525 21526 /** 21527 * Measure specification mode: The parent has determined an exact size 21528 * for the child. The child is going to be given those bounds regardless 21529 * of how big it wants to be. 21530 */ 21531 public static final int EXACTLY = 1 << MODE_SHIFT; 21532 21533 /** 21534 * Measure specification mode: The child can be as large as it wants up 21535 * to the specified size. 21536 */ 21537 public static final int AT_MOST = 2 << MODE_SHIFT; 21538 21539 /** 21540 * Creates a measure specification based on the supplied size and mode. 21541 * 21542 * The mode must always be one of the following: 21543 * <ul> 21544 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> 21545 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> 21546 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> 21547 * </ul> 21548 * 21549 * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's 21550 * implementation was such that the order of arguments did not matter 21551 * and overflow in either value could impact the resulting MeasureSpec. 21552 * {@link android.widget.RelativeLayout} was affected by this bug. 21553 * Apps targeting API levels greater than 17 will get the fixed, more strict 21554 * behavior.</p> 21555 * 21556 * @param size the size of the measure specification 21557 * @param mode the mode of the measure specification 21558 * @return the measure specification based on size and mode 21559 */ 21560 public static int makeMeasureSpec(int size, int mode) { 21561 if (sUseBrokenMakeMeasureSpec) { 21562 return size + mode; 21563 } else { 21564 return (size & ~MODE_MASK) | (mode & MODE_MASK); 21565 } 21566 } 21567 21568 /** 21569 * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED 21570 * will automatically get a size of 0. Older apps expect this. 21571 * 21572 * @hide internal use only for compatibility with system widgets and older apps 21573 */ 21574 public static int makeSafeMeasureSpec(int size, int mode) { 21575 if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) { 21576 return 0; 21577 } 21578 return makeMeasureSpec(size, mode); 21579 } 21580 21581 /** 21582 * Extracts the mode from the supplied measure specification. 21583 * 21584 * @param measureSpec the measure specification to extract the mode from 21585 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED}, 21586 * {@link android.view.View.MeasureSpec#AT_MOST} or 21587 * {@link android.view.View.MeasureSpec#EXACTLY} 21588 */ 21589 public static int getMode(int measureSpec) { 21590 return (measureSpec & MODE_MASK); 21591 } 21592 21593 /** 21594 * Extracts the size from the supplied measure specification. 21595 * 21596 * @param measureSpec the measure specification to extract the size from 21597 * @return the size in pixels defined in the supplied measure specification 21598 */ 21599 public static int getSize(int measureSpec) { 21600 return (measureSpec & ~MODE_MASK); 21601 } 21602 21603 static int adjust(int measureSpec, int delta) { 21604 final int mode = getMode(measureSpec); 21605 int size = getSize(measureSpec); 21606 if (mode == UNSPECIFIED) { 21607 // No need to adjust size for UNSPECIFIED mode. 21608 return makeMeasureSpec(size, UNSPECIFIED); 21609 } 21610 size += delta; 21611 if (size < 0) { 21612 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + 21613 ") spec: " + toString(measureSpec) + " delta: " + delta); 21614 size = 0; 21615 } 21616 return makeMeasureSpec(size, mode); 21617 } 21618 21619 /** 21620 * Returns a String representation of the specified measure 21621 * specification. 21622 * 21623 * @param measureSpec the measure specification to convert to a String 21624 * @return a String with the following format: "MeasureSpec: MODE SIZE" 21625 */ 21626 public static String toString(int measureSpec) { 21627 int mode = getMode(measureSpec); 21628 int size = getSize(measureSpec); 21629 21630 StringBuilder sb = new StringBuilder("MeasureSpec: "); 21631 21632 if (mode == UNSPECIFIED) 21633 sb.append("UNSPECIFIED "); 21634 else if (mode == EXACTLY) 21635 sb.append("EXACTLY "); 21636 else if (mode == AT_MOST) 21637 sb.append("AT_MOST "); 21638 else 21639 sb.append(mode).append(" "); 21640 21641 sb.append(size); 21642 return sb.toString(); 21643 } 21644 } 21645 21646 private final class CheckForLongPress implements Runnable { 21647 private int mOriginalWindowAttachCount; 21648 private float mX; 21649 private float mY; 21650 21651 @Override 21652 public void run() { 21653 if (isPressed() && (mParent != null) 21654 && mOriginalWindowAttachCount == mWindowAttachCount) { 21655 if (performLongClick(mX, mY)) { 21656 mHasPerformedLongPress = true; 21657 } 21658 } 21659 } 21660 21661 public void setAnchor(float x, float y) { 21662 mX = x; 21663 mY = y; 21664 } 21665 21666 public void rememberWindowAttachCount() { 21667 mOriginalWindowAttachCount = mWindowAttachCount; 21668 } 21669 } 21670 21671 private final class CheckForTap implements Runnable { 21672 public float x; 21673 public float y; 21674 21675 @Override 21676 public void run() { 21677 mPrivateFlags &= ~PFLAG_PREPRESSED; 21678 setPressed(true, x, y); 21679 checkForLongClick(ViewConfiguration.getTapTimeout(), x, y); 21680 } 21681 } 21682 21683 private final class PerformClick implements Runnable { 21684 @Override 21685 public void run() { 21686 performClick(); 21687 } 21688 } 21689 21690 /** 21691 * This method returns a ViewPropertyAnimator object, which can be used to animate 21692 * specific properties on this View. 21693 * 21694 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View. 21695 */ 21696 public ViewPropertyAnimator animate() { 21697 if (mAnimator == null) { 21698 mAnimator = new ViewPropertyAnimator(this); 21699 } 21700 return mAnimator; 21701 } 21702 21703 /** 21704 * Sets the name of the View to be used to identify Views in Transitions. 21705 * Names should be unique in the View hierarchy. 21706 * 21707 * @param transitionName The name of the View to uniquely identify it for Transitions. 21708 */ 21709 public final void setTransitionName(String transitionName) { 21710 mTransitionName = transitionName; 21711 } 21712 21713 /** 21714 * Returns the name of the View to be used to identify Views in Transitions. 21715 * Names should be unique in the View hierarchy. 21716 * 21717 * <p>This returns null if the View has not been given a name.</p> 21718 * 21719 * @return The name used of the View to be used to identify Views in Transitions or null 21720 * if no name has been given. 21721 */ 21722 @ViewDebug.ExportedProperty 21723 public String getTransitionName() { 21724 return mTransitionName; 21725 } 21726 21727 /** 21728 * Interface definition for a callback to be invoked when a hardware key event is 21729 * dispatched to this view. The callback will be invoked before the key event is 21730 * given to the view. This is only useful for hardware keyboards; a software input 21731 * method has no obligation to trigger this listener. 21732 */ 21733 public interface OnKeyListener { 21734 /** 21735 * Called when a hardware key is dispatched to a view. This allows listeners to 21736 * get a chance to respond before the target view. 21737 * <p>Key presses in software keyboards will generally NOT trigger this method, 21738 * although some may elect to do so in some situations. Do not assume a 21739 * software input method has to be key-based; even if it is, it may use key presses 21740 * in a different way than you expect, so there is no way to reliably catch soft 21741 * input key presses. 21742 * 21743 * @param v The view the key has been dispatched to. 21744 * @param keyCode The code for the physical key that was pressed 21745 * @param event The KeyEvent object containing full information about 21746 * the event. 21747 * @return True if the listener has consumed the event, false otherwise. 21748 */ 21749 boolean onKey(View v, int keyCode, KeyEvent event); 21750 } 21751 21752 /** 21753 * Interface definition for a callback to be invoked when a touch event is 21754 * dispatched to this view. The callback will be invoked before the touch 21755 * event is given to the view. 21756 */ 21757 public interface OnTouchListener { 21758 /** 21759 * Called when a touch event is dispatched to a view. This allows listeners to 21760 * get a chance to respond before the target view. 21761 * 21762 * @param v The view the touch event has been dispatched to. 21763 * @param event The MotionEvent object containing full information about 21764 * the event. 21765 * @return True if the listener has consumed the event, false otherwise. 21766 */ 21767 boolean onTouch(View v, MotionEvent event); 21768 } 21769 21770 /** 21771 * Interface definition for a callback to be invoked when a hover event is 21772 * dispatched to this view. The callback will be invoked before the hover 21773 * event is given to the view. 21774 */ 21775 public interface OnHoverListener { 21776 /** 21777 * Called when a hover event is dispatched to a view. This allows listeners to 21778 * get a chance to respond before the target view. 21779 * 21780 * @param v The view the hover event has been dispatched to. 21781 * @param event The MotionEvent object containing full information about 21782 * the event. 21783 * @return True if the listener has consumed the event, false otherwise. 21784 */ 21785 boolean onHover(View v, MotionEvent event); 21786 } 21787 21788 /** 21789 * Interface definition for a callback to be invoked when a generic motion event is 21790 * dispatched to this view. The callback will be invoked before the generic motion 21791 * event is given to the view. 21792 */ 21793 public interface OnGenericMotionListener { 21794 /** 21795 * Called when a generic motion event is dispatched to a view. This allows listeners to 21796 * get a chance to respond before the target view. 21797 * 21798 * @param v The view the generic motion event has been dispatched to. 21799 * @param event The MotionEvent object containing full information about 21800 * the event. 21801 * @return True if the listener has consumed the event, false otherwise. 21802 */ 21803 boolean onGenericMotion(View v, MotionEvent event); 21804 } 21805 21806 /** 21807 * Interface definition for a callback to be invoked when a view has been clicked and held. 21808 */ 21809 public interface OnLongClickListener { 21810 /** 21811 * Called when a view has been clicked and held. 21812 * 21813 * @param v The view that was clicked and held. 21814 * 21815 * @return true if the callback consumed the long click, false otherwise. 21816 */ 21817 boolean onLongClick(View v); 21818 } 21819 21820 /** 21821 * Interface definition for a callback to be invoked when a drag is being dispatched 21822 * to this view. The callback will be invoked before the hosting view's own 21823 * onDrag(event) method. If the listener wants to fall back to the hosting view's 21824 * onDrag(event) behavior, it should return 'false' from this callback. 21825 * 21826 * <div class="special reference"> 21827 * <h3>Developer Guides</h3> 21828 * <p>For a guide to implementing drag and drop features, read the 21829 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p> 21830 * </div> 21831 */ 21832 public interface OnDragListener { 21833 /** 21834 * Called when a drag event is dispatched to a view. This allows listeners 21835 * to get a chance to override base View behavior. 21836 * 21837 * @param v The View that received the drag event. 21838 * @param event The {@link android.view.DragEvent} object for the drag event. 21839 * @return {@code true} if the drag event was handled successfully, or {@code false} 21840 * if the drag event was not handled. Note that {@code false} will trigger the View 21841 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler. 21842 */ 21843 boolean onDrag(View v, DragEvent event); 21844 } 21845 21846 /** 21847 * Interface definition for a callback to be invoked when the focus state of 21848 * a view changed. 21849 */ 21850 public interface OnFocusChangeListener { 21851 /** 21852 * Called when the focus state of a view has changed. 21853 * 21854 * @param v The view whose state has changed. 21855 * @param hasFocus The new focus state of v. 21856 */ 21857 void onFocusChange(View v, boolean hasFocus); 21858 } 21859 21860 /** 21861 * Interface definition for a callback to be invoked when a view is clicked. 21862 */ 21863 public interface OnClickListener { 21864 /** 21865 * Called when a view has been clicked. 21866 * 21867 * @param v The view that was clicked. 21868 */ 21869 void onClick(View v); 21870 } 21871 21872 /** 21873 * Interface definition for a callback to be invoked when a view is context clicked. 21874 */ 21875 public interface OnContextClickListener { 21876 /** 21877 * Called when a view is context clicked. 21878 * 21879 * @param v The view that has been context clicked. 21880 * @return true if the callback consumed the context click, false otherwise. 21881 */ 21882 boolean onContextClick(View v); 21883 } 21884 21885 /** 21886 * Interface definition for a callback to be invoked when the context menu 21887 * for this view is being built. 21888 */ 21889 public interface OnCreateContextMenuListener { 21890 /** 21891 * Called when the context menu for this view is being built. It is not 21892 * safe to hold onto the menu after this method returns. 21893 * 21894 * @param menu The context menu that is being built 21895 * @param v The view for which the context menu is being built 21896 * @param menuInfo Extra information about the item for which the 21897 * context menu should be shown. This information will vary 21898 * depending on the class of v. 21899 */ 21900 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo); 21901 } 21902 21903 /** 21904 * Interface definition for a callback to be invoked when the status bar changes 21905 * visibility. This reports <strong>global</strong> changes to the system UI 21906 * state, not what the application is requesting. 21907 * 21908 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 21909 */ 21910 public interface OnSystemUiVisibilityChangeListener { 21911 /** 21912 * Called when the status bar changes visibility because of a call to 21913 * {@link View#setSystemUiVisibility(int)}. 21914 * 21915 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE}, 21916 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}. 21917 * This tells you the <strong>global</strong> state of these UI visibility 21918 * flags, not what your app is currently applying. 21919 */ 21920 public void onSystemUiVisibilityChange(int visibility); 21921 } 21922 21923 /** 21924 * Interface definition for a callback to be invoked when this view is attached 21925 * or detached from its window. 21926 */ 21927 public interface OnAttachStateChangeListener { 21928 /** 21929 * Called when the view is attached to a window. 21930 * @param v The view that was attached 21931 */ 21932 public void onViewAttachedToWindow(View v); 21933 /** 21934 * Called when the view is detached from a window. 21935 * @param v The view that was detached 21936 */ 21937 public void onViewDetachedFromWindow(View v); 21938 } 21939 21940 /** 21941 * Listener for applying window insets on a view in a custom way. 21942 * 21943 * <p>Apps may choose to implement this interface if they want to apply custom policy 21944 * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener 21945 * is set, its 21946 * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets} 21947 * method will be called instead of the View's own 21948 * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener 21949 * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply 21950 * the View's normal behavior as part of its own.</p> 21951 */ 21952 public interface OnApplyWindowInsetsListener { 21953 /** 21954 * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set} 21955 * on a View, this listener method will be called instead of the view's own 21956 * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. 21957 * 21958 * @param v The view applying window insets 21959 * @param insets The insets to apply 21960 * @return The insets supplied, minus any insets that were consumed 21961 */ 21962 public WindowInsets onApplyWindowInsets(View v, WindowInsets insets); 21963 } 21964 21965 private final class UnsetPressedState implements Runnable { 21966 @Override 21967 public void run() { 21968 setPressed(false); 21969 } 21970 } 21971 21972 /** 21973 * Base class for derived classes that want to save and restore their own 21974 * state in {@link android.view.View#onSaveInstanceState()}. 21975 */ 21976 public static class BaseSavedState extends AbsSavedState { 21977 String mStartActivityRequestWhoSaved; 21978 21979 /** 21980 * Constructor used when reading from a parcel. Reads the state of the superclass. 21981 * 21982 * @param source 21983 */ 21984 public BaseSavedState(Parcel source) { 21985 super(source); 21986 mStartActivityRequestWhoSaved = source.readString(); 21987 } 21988 21989 /** 21990 * Constructor called by derived classes when creating their SavedState objects 21991 * 21992 * @param superState The state of the superclass of this view 21993 */ 21994 public BaseSavedState(Parcelable superState) { 21995 super(superState); 21996 } 21997 21998 @Override 21999 public void writeToParcel(Parcel out, int flags) { 22000 super.writeToParcel(out, flags); 22001 out.writeString(mStartActivityRequestWhoSaved); 22002 } 22003 22004 public static final Parcelable.Creator<BaseSavedState> CREATOR = 22005 new Parcelable.Creator<BaseSavedState>() { 22006 public BaseSavedState createFromParcel(Parcel in) { 22007 return new BaseSavedState(in); 22008 } 22009 22010 public BaseSavedState[] newArray(int size) { 22011 return new BaseSavedState[size]; 22012 } 22013 }; 22014 } 22015 22016 /** 22017 * A set of information given to a view when it is attached to its parent 22018 * window. 22019 */ 22020 final static class AttachInfo { 22021 interface Callbacks { 22022 void playSoundEffect(int effectId); 22023 boolean performHapticFeedback(int effectId, boolean always); 22024 void schedulePartialLayout(); 22025 } 22026 22027 /** 22028 * InvalidateInfo is used to post invalidate(int, int, int, int) messages 22029 * to a Handler. This class contains the target (View) to invalidate and 22030 * the coordinates of the dirty rectangle. 22031 * 22032 * For performance purposes, this class also implements a pool of up to 22033 * POOL_LIMIT objects that get reused. This reduces memory allocations 22034 * whenever possible. 22035 */ 22036 static class InvalidateInfo { 22037 private static final int POOL_LIMIT = 10; 22038 22039 private static final SynchronizedPool<InvalidateInfo> sPool = 22040 new SynchronizedPool<InvalidateInfo>(POOL_LIMIT); 22041 22042 View target; 22043 22044 int left; 22045 int top; 22046 int right; 22047 int bottom; 22048 22049 public static InvalidateInfo obtain() { 22050 InvalidateInfo instance = sPool.acquire(); 22051 return (instance != null) ? instance : new InvalidateInfo(); 22052 } 22053 22054 public void recycle() { 22055 target = null; 22056 sPool.release(this); 22057 } 22058 } 22059 22060 final IWindowSession mSession; 22061 22062 final IWindow mWindow; 22063 22064 final IBinder mWindowToken; 22065 22066 final Display mDisplay; 22067 22068 final Callbacks mRootCallbacks; 22069 22070 IWindowId mIWindowId; 22071 WindowId mWindowId; 22072 22073 /** 22074 * The top view of the hierarchy. 22075 */ 22076 View mRootView; 22077 22078 IBinder mPanelParentWindowToken; 22079 22080 boolean mHardwareAccelerated; 22081 boolean mHardwareAccelerationRequested; 22082 ThreadedRenderer mHardwareRenderer; 22083 List<RenderNode> mPendingAnimatingRenderNodes; 22084 22085 /** 22086 * The state of the display to which the window is attached, as reported 22087 * by {@link Display#getState()}. Note that the display state constants 22088 * declared by {@link Display} do not exactly line up with the screen state 22089 * constants declared by {@link View} (there are more display states than 22090 * screen states). 22091 */ 22092 int mDisplayState = Display.STATE_UNKNOWN; 22093 22094 /** 22095 * Scale factor used by the compatibility mode 22096 */ 22097 float mApplicationScale; 22098 22099 /** 22100 * Indicates whether the application is in compatibility mode 22101 */ 22102 boolean mScalingRequired; 22103 22104 /** 22105 * Left position of this view's window 22106 */ 22107 int mWindowLeft; 22108 22109 /** 22110 * Top position of this view's window 22111 */ 22112 int mWindowTop; 22113 22114 /** 22115 * Indicates whether views need to use 32-bit drawing caches 22116 */ 22117 boolean mUse32BitDrawingCache; 22118 22119 /** 22120 * For windows that are full-screen but using insets to layout inside 22121 * of the screen areas, these are the current insets to appear inside 22122 * the overscan area of the display. 22123 */ 22124 final Rect mOverscanInsets = new Rect(); 22125 22126 /** 22127 * For windows that are full-screen but using insets to layout inside 22128 * of the screen decorations, these are the current insets for the 22129 * content of the window. 22130 */ 22131 final Rect mContentInsets = new Rect(); 22132 22133 /** 22134 * For windows that are full-screen but using insets to layout inside 22135 * of the screen decorations, these are the current insets for the 22136 * actual visible parts of the window. 22137 */ 22138 final Rect mVisibleInsets = new Rect(); 22139 22140 /** 22141 * For windows that are full-screen but using insets to layout inside 22142 * of the screen decorations, these are the current insets for the 22143 * stable system windows. 22144 */ 22145 final Rect mStableInsets = new Rect(); 22146 22147 /** 22148 * For windows that include areas that are not covered by real surface these are the outsets 22149 * for real surface. 22150 */ 22151 final Rect mOutsets = new Rect(); 22152 22153 /** 22154 * The internal insets given by this window. This value is 22155 * supplied by the client (through 22156 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will 22157 * be given to the window manager when changed to be used in laying 22158 * out windows behind it. 22159 */ 22160 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets 22161 = new ViewTreeObserver.InternalInsetsInfo(); 22162 22163 /** 22164 * Set to true when mGivenInternalInsets is non-empty. 22165 */ 22166 boolean mHasNonEmptyGivenInternalInsets; 22167 22168 /** 22169 * All views in the window's hierarchy that serve as scroll containers, 22170 * used to determine if the window can be resized or must be panned 22171 * to adjust for a soft input area. 22172 */ 22173 final ArrayList<View> mScrollContainers = new ArrayList<View>(); 22174 22175 final KeyEvent.DispatcherState mKeyDispatchState 22176 = new KeyEvent.DispatcherState(); 22177 22178 /** 22179 * Indicates whether the view's window currently has the focus. 22180 */ 22181 boolean mHasWindowFocus; 22182 22183 /** 22184 * The current visibility of the window. 22185 */ 22186 int mWindowVisibility; 22187 22188 /** 22189 * Indicates the time at which drawing started to occur. 22190 */ 22191 long mDrawingTime; 22192 22193 /** 22194 * Indicates whether or not ignoring the DIRTY_MASK flags. 22195 */ 22196 boolean mIgnoreDirtyState; 22197 22198 /** 22199 * This flag tracks when the mIgnoreDirtyState flag is set during draw(), 22200 * to avoid clearing that flag prematurely. 22201 */ 22202 boolean mSetIgnoreDirtyState = false; 22203 22204 /** 22205 * Indicates whether the view's window is currently in touch mode. 22206 */ 22207 boolean mInTouchMode; 22208 22209 /** 22210 * Indicates whether the view has requested unbuffered input dispatching for the current 22211 * event stream. 22212 */ 22213 boolean mUnbufferedDispatchRequested; 22214 22215 /** 22216 * Indicates that ViewAncestor should trigger a global layout change 22217 * the next time it performs a traversal 22218 */ 22219 boolean mRecomputeGlobalAttributes; 22220 22221 /** 22222 * Always report new attributes at next traversal. 22223 */ 22224 boolean mForceReportNewAttributes; 22225 22226 /** 22227 * Set during a traveral if any views want to keep the screen on. 22228 */ 22229 boolean mKeepScreenOn; 22230 22231 /** 22232 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility(). 22233 */ 22234 int mSystemUiVisibility; 22235 22236 /** 22237 * Hack to force certain system UI visibility flags to be cleared. 22238 */ 22239 int mDisabledSystemUiVisibility; 22240 22241 /** 22242 * Last global system UI visibility reported by the window manager. 22243 */ 22244 int mGlobalSystemUiVisibility; 22245 22246 /** 22247 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener 22248 * attached. 22249 */ 22250 boolean mHasSystemUiListeners; 22251 22252 /** 22253 * Set if the window has requested to extend into the overscan region 22254 * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN. 22255 */ 22256 boolean mOverscanRequested; 22257 22258 /** 22259 * Set if the visibility of any views has changed. 22260 */ 22261 boolean mViewVisibilityChanged; 22262 22263 /** 22264 * Set to true if a view has been scrolled. 22265 */ 22266 boolean mViewScrollChanged; 22267 22268 /** 22269 * Set to true if high contrast mode enabled 22270 */ 22271 boolean mHighContrastText; 22272 22273 /** 22274 * Global to the view hierarchy used as a temporary for dealing with 22275 * x/y points in the transparent region computations. 22276 */ 22277 final int[] mTransparentLocation = new int[2]; 22278 22279 /** 22280 * Global to the view hierarchy used as a temporary for dealing with 22281 * x/y points in the ViewGroup.invalidateChild implementation. 22282 */ 22283 final int[] mInvalidateChildLocation = new int[2]; 22284 22285 /** 22286 * Global to the view hierarchy used as a temporary for dealng with 22287 * computing absolute on-screen location. 22288 */ 22289 final int[] mTmpLocation = new int[2]; 22290 22291 /** 22292 * Global to the view hierarchy used as a temporary for dealing with 22293 * x/y location when view is transformed. 22294 */ 22295 final float[] mTmpTransformLocation = new float[2]; 22296 22297 /** 22298 * The view tree observer used to dispatch global events like 22299 * layout, pre-draw, touch mode change, etc. 22300 */ 22301 final ViewTreeObserver mTreeObserver = new ViewTreeObserver(); 22302 22303 /** 22304 * A Canvas used by the view hierarchy to perform bitmap caching. 22305 */ 22306 Canvas mCanvas; 22307 22308 /** 22309 * The view root impl. 22310 */ 22311 final ViewRootImpl mViewRootImpl; 22312 22313 /** 22314 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This 22315 * handler can be used to pump events in the UI events queue. 22316 */ 22317 final Handler mHandler; 22318 22319 /** 22320 * Temporary for use in computing invalidate rectangles while 22321 * calling up the hierarchy. 22322 */ 22323 final Rect mTmpInvalRect = new Rect(); 22324 22325 /** 22326 * Temporary for use in computing hit areas with transformed views 22327 */ 22328 final RectF mTmpTransformRect = new RectF(); 22329 22330 /** 22331 * Temporary for use in computing hit areas with transformed views 22332 */ 22333 final RectF mTmpTransformRect1 = new RectF(); 22334 22335 /** 22336 * Temporary list of rectanges. 22337 */ 22338 final List<RectF> mTmpRectList = new ArrayList<>(); 22339 22340 /** 22341 * Temporary for use in transforming invalidation rect 22342 */ 22343 final Matrix mTmpMatrix = new Matrix(); 22344 22345 /** 22346 * Temporary for use in transforming invalidation rect 22347 */ 22348 final Transformation mTmpTransformation = new Transformation(); 22349 22350 /** 22351 * Temporary for use in querying outlines from OutlineProviders 22352 */ 22353 final Outline mTmpOutline = new Outline(); 22354 22355 /** 22356 * Temporary list for use in collecting focusable descendents of a view. 22357 */ 22358 final ArrayList<View> mTempArrayList = new ArrayList<View>(24); 22359 22360 /** 22361 * The id of the window for accessibility purposes. 22362 */ 22363 int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID; 22364 22365 /** 22366 * Flags related to accessibility processing. 22367 * 22368 * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS 22369 * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS 22370 */ 22371 int mAccessibilityFetchFlags; 22372 22373 /** 22374 * The drawable for highlighting accessibility focus. 22375 */ 22376 Drawable mAccessibilityFocusDrawable; 22377 22378 /** 22379 * Show where the margins, bounds and layout bounds are for each view. 22380 */ 22381 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false); 22382 22383 /** 22384 * Point used to compute visible regions. 22385 */ 22386 final Point mPoint = new Point(); 22387 22388 /** 22389 * Used to track which View originated a requestLayout() call, used when 22390 * requestLayout() is called during layout. 22391 */ 22392 View mViewRequestingLayout; 22393 22394 /** 22395 * Used to track views that need (at least) a partial relayout at their current size 22396 * during the next traversal. 22397 */ 22398 List<View> mPartialLayoutViews = new ArrayList<>(); 22399 22400 /** 22401 * Swapped with mPartialLayoutViews during layout to avoid concurrent 22402 * modification. Lazily assigned during ViewRootImpl layout. 22403 */ 22404 List<View> mEmptyPartialLayoutViews; 22405 22406 /** 22407 * Used to track the identity of the current drag operation. 22408 */ 22409 IBinder mDragToken; 22410 22411 /** 22412 * The drag shadow surface for the current drag operation. 22413 */ 22414 public Surface mDragSurface; 22415 22416 /** 22417 * Creates a new set of attachment information with the specified 22418 * events handler and thread. 22419 * 22420 * @param handler the events handler the view must use 22421 */ 22422 AttachInfo(IWindowSession session, IWindow window, Display display, 22423 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) { 22424 mSession = session; 22425 mWindow = window; 22426 mWindowToken = window.asBinder(); 22427 mDisplay = display; 22428 mViewRootImpl = viewRootImpl; 22429 mHandler = handler; 22430 mRootCallbacks = effectPlayer; 22431 } 22432 } 22433 22434 /** 22435 * <p>ScrollabilityCache holds various fields used by a View when scrolling 22436 * is supported. This avoids keeping too many unused fields in most 22437 * instances of View.</p> 22438 */ 22439 private static class ScrollabilityCache implements Runnable { 22440 22441 /** 22442 * Scrollbars are not visible 22443 */ 22444 public static final int OFF = 0; 22445 22446 /** 22447 * Scrollbars are visible 22448 */ 22449 public static final int ON = 1; 22450 22451 /** 22452 * Scrollbars are fading away 22453 */ 22454 public static final int FADING = 2; 22455 22456 public boolean fadeScrollBars; 22457 22458 public int fadingEdgeLength; 22459 public int scrollBarDefaultDelayBeforeFade; 22460 public int scrollBarFadeDuration; 22461 22462 public int scrollBarSize; 22463 public ScrollBarDrawable scrollBar; 22464 public float[] interpolatorValues; 22465 public View host; 22466 22467 public final Paint paint; 22468 public final Matrix matrix; 22469 public Shader shader; 22470 22471 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2); 22472 22473 private static final float[] OPAQUE = { 255 }; 22474 private static final float[] TRANSPARENT = { 0.0f }; 22475 22476 /** 22477 * When fading should start. This time moves into the future every time 22478 * a new scroll happens. Measured based on SystemClock.uptimeMillis() 22479 */ 22480 public long fadeStartTime; 22481 22482 22483 /** 22484 * The current state of the scrollbars: ON, OFF, or FADING 22485 */ 22486 public int state = OFF; 22487 22488 private int mLastColor; 22489 22490 public ScrollabilityCache(ViewConfiguration configuration, View host) { 22491 fadingEdgeLength = configuration.getScaledFadingEdgeLength(); 22492 scrollBarSize = configuration.getScaledScrollBarSize(); 22493 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay(); 22494 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); 22495 22496 paint = new Paint(); 22497 matrix = new Matrix(); 22498 // use use a height of 1, and then wack the matrix each time we 22499 // actually use it. 22500 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 22501 paint.setShader(shader); 22502 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 22503 22504 this.host = host; 22505 } 22506 22507 public void setFadeColor(int color) { 22508 if (color != mLastColor) { 22509 mLastColor = color; 22510 22511 if (color != 0) { 22512 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, 22513 color & 0x00FFFFFF, Shader.TileMode.CLAMP); 22514 paint.setShader(shader); 22515 // Restore the default transfer mode (src_over) 22516 paint.setXfermode(null); 22517 } else { 22518 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP); 22519 paint.setShader(shader); 22520 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 22521 } 22522 } 22523 } 22524 22525 public void run() { 22526 long now = AnimationUtils.currentAnimationTimeMillis(); 22527 if (now >= fadeStartTime) { 22528 22529 // the animation fades the scrollbars out by changing 22530 // the opacity (alpha) from fully opaque to fully 22531 // transparent 22532 int nextFrame = (int) now; 22533 int framesCount = 0; 22534 22535 Interpolator interpolator = scrollBarInterpolator; 22536 22537 // Start opaque 22538 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE); 22539 22540 // End transparent 22541 nextFrame += scrollBarFadeDuration; 22542 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT); 22543 22544 state = FADING; 22545 22546 // Kick off the fade animation 22547 host.invalidate(true); 22548 } 22549 } 22550 } 22551 22552 /** 22553 * Resuable callback for sending 22554 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event. 22555 */ 22556 private class SendViewScrolledAccessibilityEvent implements Runnable { 22557 public volatile boolean mIsPending; 22558 22559 public void run() { 22560 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED); 22561 mIsPending = false; 22562 } 22563 } 22564 22565 /** 22566 * <p> 22567 * This class represents a delegate that can be registered in a {@link View} 22568 * to enhance accessibility support via composition rather via inheritance. 22569 * It is specifically targeted to widget developers that extend basic View 22570 * classes i.e. classes in package android.view, that would like their 22571 * applications to be backwards compatible. 22572 * </p> 22573 * <div class="special reference"> 22574 * <h3>Developer Guides</h3> 22575 * <p>For more information about making applications accessible, read the 22576 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a> 22577 * developer guide.</p> 22578 * </div> 22579 * <p> 22580 * A scenario in which a developer would like to use an accessibility delegate 22581 * is overriding a method introduced in a later API version then the minimal API 22582 * version supported by the application. For example, the method 22583 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available 22584 * in API version 4 when the accessibility APIs were first introduced. If a 22585 * developer would like his application to run on API version 4 devices (assuming 22586 * all other APIs used by the application are version 4 or lower) and take advantage 22587 * of this method, instead of overriding the method which would break the application's 22588 * backwards compatibility, he can override the corresponding method in this 22589 * delegate and register the delegate in the target View if the API version of 22590 * the system is high enough i.e. the API version is same or higher to the API 22591 * version that introduced 22592 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}. 22593 * </p> 22594 * <p> 22595 * Here is an example implementation: 22596 * </p> 22597 * <code><pre><p> 22598 * if (Build.VERSION.SDK_INT >= 14) { 22599 * // If the API version is equal of higher than the version in 22600 * // which onInitializeAccessibilityNodeInfo was introduced we 22601 * // register a delegate with a customized implementation. 22602 * View view = findViewById(R.id.view_id); 22603 * view.setAccessibilityDelegate(new AccessibilityDelegate() { 22604 * public void onInitializeAccessibilityNodeInfo(View host, 22605 * AccessibilityNodeInfo info) { 22606 * // Let the default implementation populate the info. 22607 * super.onInitializeAccessibilityNodeInfo(host, info); 22608 * // Set some other information. 22609 * info.setEnabled(host.isEnabled()); 22610 * } 22611 * }); 22612 * } 22613 * </code></pre></p> 22614 * <p> 22615 * This delegate contains methods that correspond to the accessibility methods 22616 * in View. If a delegate has been specified the implementation in View hands 22617 * off handling to the corresponding method in this delegate. The default 22618 * implementation the delegate methods behaves exactly as the corresponding 22619 * method in View for the case of no accessibility delegate been set. Hence, 22620 * to customize the behavior of a View method, clients can override only the 22621 * corresponding delegate method without altering the behavior of the rest 22622 * accessibility related methods of the host view. 22623 * </p> 22624 * <p> 22625 * <strong>Note:</strong> On platform versions prior to 22626 * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on 22627 * views in the {@code android.widget.*} package are called <i>before</i> 22628 * host methods. This prevents certain properties such as class name from 22629 * being modified by overriding 22630 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}, 22631 * as any changes will be overwritten by the host class. 22632 * <p> 22633 * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate 22634 * methods are called <i>after</i> host methods, which all properties to be 22635 * modified without being overwritten by the host class. 22636 */ 22637 public static class AccessibilityDelegate { 22638 22639 /** 22640 * Sends an accessibility event of the given type. If accessibility is not 22641 * enabled this method has no effect. 22642 * <p> 22643 * The default implementation behaves as {@link View#sendAccessibilityEvent(int) 22644 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate 22645 * been set. 22646 * </p> 22647 * 22648 * @param host The View hosting the delegate. 22649 * @param eventType The type of the event to send. 22650 * 22651 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int) 22652 */ 22653 public void sendAccessibilityEvent(View host, int eventType) { 22654 host.sendAccessibilityEventInternal(eventType); 22655 } 22656 22657 /** 22658 * Performs the specified accessibility action on the view. For 22659 * possible accessibility actions look at {@link AccessibilityNodeInfo}. 22660 * <p> 22661 * The default implementation behaves as 22662 * {@link View#performAccessibilityAction(int, Bundle) 22663 * View#performAccessibilityAction(int, Bundle)} for the case of 22664 * no accessibility delegate been set. 22665 * </p> 22666 * 22667 * @param action The action to perform. 22668 * @return Whether the action was performed. 22669 * 22670 * @see View#performAccessibilityAction(int, Bundle) 22671 * View#performAccessibilityAction(int, Bundle) 22672 */ 22673 public boolean performAccessibilityAction(View host, int action, Bundle args) { 22674 return host.performAccessibilityActionInternal(action, args); 22675 } 22676 22677 /** 22678 * Sends an accessibility event. This method behaves exactly as 22679 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an 22680 * empty {@link AccessibilityEvent} and does not perform a check whether 22681 * accessibility is enabled. 22682 * <p> 22683 * The default implementation behaves as 22684 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent) 22685 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for 22686 * the case of no accessibility delegate been set. 22687 * </p> 22688 * 22689 * @param host The View hosting the delegate. 22690 * @param event The event to send. 22691 * 22692 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent) 22693 * View#sendAccessibilityEventUnchecked(AccessibilityEvent) 22694 */ 22695 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) { 22696 host.sendAccessibilityEventUncheckedInternal(event); 22697 } 22698 22699 /** 22700 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then 22701 * to its children for adding their text content to the event. 22702 * <p> 22703 * The default implementation behaves as 22704 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 22705 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for 22706 * the case of no accessibility delegate been set. 22707 * </p> 22708 * 22709 * @param host The View hosting the delegate. 22710 * @param event The event. 22711 * @return True if the event population was completed. 22712 * 22713 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 22714 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent) 22715 */ 22716 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 22717 return host.dispatchPopulateAccessibilityEventInternal(event); 22718 } 22719 22720 /** 22721 * Gives a chance to the host View to populate the accessibility event with its 22722 * text content. 22723 * <p> 22724 * The default implementation behaves as 22725 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent) 22726 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for 22727 * the case of no accessibility delegate been set. 22728 * </p> 22729 * 22730 * @param host The View hosting the delegate. 22731 * @param event The accessibility event which to populate. 22732 * 22733 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent) 22734 * View#onPopulateAccessibilityEvent(AccessibilityEvent) 22735 */ 22736 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) { 22737 host.onPopulateAccessibilityEventInternal(event); 22738 } 22739 22740 /** 22741 * Initializes an {@link AccessibilityEvent} with information about the 22742 * the host View which is the event source. 22743 * <p> 22744 * The default implementation behaves as 22745 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent) 22746 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for 22747 * the case of no accessibility delegate been set. 22748 * </p> 22749 * 22750 * @param host The View hosting the delegate. 22751 * @param event The event to initialize. 22752 * 22753 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) 22754 * View#onInitializeAccessibilityEvent(AccessibilityEvent) 22755 */ 22756 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) { 22757 host.onInitializeAccessibilityEventInternal(event); 22758 } 22759 22760 /** 22761 * Initializes an {@link AccessibilityNodeInfo} with information about the host view. 22762 * <p> 22763 * The default implementation behaves as 22764 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 22765 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for 22766 * the case of no accessibility delegate been set. 22767 * </p> 22768 * 22769 * @param host The View hosting the delegate. 22770 * @param info The instance to initialize. 22771 * 22772 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 22773 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) 22774 */ 22775 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { 22776 host.onInitializeAccessibilityNodeInfoInternal(info); 22777 } 22778 22779 /** 22780 * Called when a child of the host View has requested sending an 22781 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host) 22782 * to augment the event. 22783 * <p> 22784 * The default implementation behaves as 22785 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 22786 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for 22787 * the case of no accessibility delegate been set. 22788 * </p> 22789 * 22790 * @param host The View hosting the delegate. 22791 * @param child The child which requests sending the event. 22792 * @param event The event to be sent. 22793 * @return True if the event should be sent 22794 * 22795 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 22796 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent) 22797 */ 22798 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, 22799 AccessibilityEvent event) { 22800 return host.onRequestSendAccessibilityEventInternal(child, event); 22801 } 22802 22803 /** 22804 * Gets the provider for managing a virtual view hierarchy rooted at this View 22805 * and reported to {@link android.accessibilityservice.AccessibilityService}s 22806 * that explore the window content. 22807 * <p> 22808 * The default implementation behaves as 22809 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for 22810 * the case of no accessibility delegate been set. 22811 * </p> 22812 * 22813 * @return The provider. 22814 * 22815 * @see AccessibilityNodeProvider 22816 */ 22817 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) { 22818 return null; 22819 } 22820 22821 /** 22822 * Returns an {@link AccessibilityNodeInfo} representing the host view from the 22823 * point of view of an {@link android.accessibilityservice.AccessibilityService}. 22824 * This method is responsible for obtaining an accessibility node info from a 22825 * pool of reusable instances and calling 22826 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host 22827 * view to initialize the former. 22828 * <p> 22829 * <strong>Note:</strong> The client is responsible for recycling the obtained 22830 * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object 22831 * creation. 22832 * </p> 22833 * <p> 22834 * The default implementation behaves as 22835 * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for 22836 * the case of no accessibility delegate been set. 22837 * </p> 22838 * @return A populated {@link AccessibilityNodeInfo}. 22839 * 22840 * @see AccessibilityNodeInfo 22841 * 22842 * @hide 22843 */ 22844 public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) { 22845 return host.createAccessibilityNodeInfoInternal(); 22846 } 22847 } 22848 22849 private class MatchIdPredicate implements Predicate<View> { 22850 public int mId; 22851 22852 @Override 22853 public boolean apply(View view) { 22854 return (view.mID == mId); 22855 } 22856 } 22857 22858 private class MatchLabelForPredicate implements Predicate<View> { 22859 private int mLabeledId; 22860 22861 @Override 22862 public boolean apply(View view) { 22863 return (view.mLabelForId == mLabeledId); 22864 } 22865 } 22866 22867 private class SendViewStateChangedAccessibilityEvent implements Runnable { 22868 private int mChangeTypes = 0; 22869 private boolean mPosted; 22870 private boolean mPostedWithDelay; 22871 private long mLastEventTimeMillis; 22872 22873 @Override 22874 public void run() { 22875 mPosted = false; 22876 mPostedWithDelay = false; 22877 mLastEventTimeMillis = SystemClock.uptimeMillis(); 22878 if (AccessibilityManager.getInstance(mContext).isEnabled()) { 22879 final AccessibilityEvent event = AccessibilityEvent.obtain(); 22880 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); 22881 event.setContentChangeTypes(mChangeTypes); 22882 sendAccessibilityEventUnchecked(event); 22883 } 22884 mChangeTypes = 0; 22885 } 22886 22887 public void runOrPost(int changeType) { 22888 mChangeTypes |= changeType; 22889 22890 // If this is a live region or the child of a live region, collect 22891 // all events from this frame and send them on the next frame. 22892 if (inLiveRegion()) { 22893 // If we're already posted with a delay, remove that. 22894 if (mPostedWithDelay) { 22895 removeCallbacks(this); 22896 mPostedWithDelay = false; 22897 } 22898 // Only post if we're not already posted. 22899 if (!mPosted) { 22900 post(this); 22901 mPosted = true; 22902 } 22903 return; 22904 } 22905 22906 if (mPosted) { 22907 return; 22908 } 22909 22910 final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis; 22911 final long minEventIntevalMillis = 22912 ViewConfiguration.getSendRecurringAccessibilityEventsInterval(); 22913 if (timeSinceLastMillis >= minEventIntevalMillis) { 22914 removeCallbacks(this); 22915 run(); 22916 } else { 22917 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis); 22918 mPostedWithDelay = true; 22919 } 22920 } 22921 } 22922 22923 private boolean inLiveRegion() { 22924 if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) { 22925 return true; 22926 } 22927 22928 ViewParent parent = getParent(); 22929 while (parent instanceof View) { 22930 if (((View) parent).getAccessibilityLiveRegion() 22931 != View.ACCESSIBILITY_LIVE_REGION_NONE) { 22932 return true; 22933 } 22934 parent = parent.getParent(); 22935 } 22936 22937 return false; 22938 } 22939 22940 /** 22941 * Dump all private flags in readable format, useful for documentation and 22942 * sanity checking. 22943 */ 22944 private static void dumpFlags() { 22945 final HashMap<String, String> found = Maps.newHashMap(); 22946 try { 22947 for (Field field : View.class.getDeclaredFields()) { 22948 final int modifiers = field.getModifiers(); 22949 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { 22950 if (field.getType().equals(int.class)) { 22951 final int value = field.getInt(null); 22952 dumpFlag(found, field.getName(), value); 22953 } else if (field.getType().equals(int[].class)) { 22954 final int[] values = (int[]) field.get(null); 22955 for (int i = 0; i < values.length; i++) { 22956 dumpFlag(found, field.getName() + "[" + i + "]", values[i]); 22957 } 22958 } 22959 } 22960 } 22961 } catch (IllegalAccessException e) { 22962 throw new RuntimeException(e); 22963 } 22964 22965 final ArrayList<String> keys = Lists.newArrayList(); 22966 keys.addAll(found.keySet()); 22967 Collections.sort(keys); 22968 for (String key : keys) { 22969 Log.d(VIEW_LOG_TAG, found.get(key)); 22970 } 22971 } 22972 22973 private static void dumpFlag(HashMap<String, String> found, String name, int value) { 22974 // Sort flags by prefix, then by bits, always keeping unique keys 22975 final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); 22976 final int prefix = name.indexOf('_'); 22977 final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; 22978 final String output = bits + " " + name; 22979 found.put(key, output); 22980 } 22981 22982 /** {@hide} */ 22983 public void encode(@NonNull ViewHierarchyEncoder stream) { 22984 stream.beginObject(this); 22985 encodeProperties(stream); 22986 stream.endObject(); 22987 } 22988 22989 /** {@hide} */ 22990 @CallSuper 22991 protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) { 22992 Object resolveId = ViewDebug.resolveId(getContext(), mID); 22993 if (resolveId instanceof String) { 22994 stream.addProperty("id", (String) resolveId); 22995 } else { 22996 stream.addProperty("id", mID); 22997 } 22998 22999 stream.addProperty("misc:transformation.alpha", 23000 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0); 23001 stream.addProperty("misc:transitionName", getTransitionName()); 23002 23003 // layout 23004 stream.addProperty("layout:left", mLeft); 23005 stream.addProperty("layout:right", mRight); 23006 stream.addProperty("layout:top", mTop); 23007 stream.addProperty("layout:bottom", mBottom); 23008 stream.addProperty("layout:width", getWidth()); 23009 stream.addProperty("layout:height", getHeight()); 23010 stream.addProperty("layout:layoutDirection", getLayoutDirection()); 23011 stream.addProperty("layout:layoutRtl", isLayoutRtl()); 23012 stream.addProperty("layout:hasTransientState", hasTransientState()); 23013 stream.addProperty("layout:baseline", getBaseline()); 23014 23015 // layout params 23016 ViewGroup.LayoutParams layoutParams = getLayoutParams(); 23017 if (layoutParams != null) { 23018 stream.addPropertyKey("layoutParams"); 23019 layoutParams.encode(stream); 23020 } 23021 23022 // scrolling 23023 stream.addProperty("scrolling:scrollX", mScrollX); 23024 stream.addProperty("scrolling:scrollY", mScrollY); 23025 23026 // padding 23027 stream.addProperty("padding:paddingLeft", mPaddingLeft); 23028 stream.addProperty("padding:paddingRight", mPaddingRight); 23029 stream.addProperty("padding:paddingTop", mPaddingTop); 23030 stream.addProperty("padding:paddingBottom", mPaddingBottom); 23031 stream.addProperty("padding:userPaddingRight", mUserPaddingRight); 23032 stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft); 23033 stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom); 23034 stream.addProperty("padding:userPaddingStart", mUserPaddingStart); 23035 stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd); 23036 23037 // measurement 23038 stream.addProperty("measurement:minHeight", mMinHeight); 23039 stream.addProperty("measurement:minWidth", mMinWidth); 23040 stream.addProperty("measurement:measuredWidth", mMeasuredWidth); 23041 stream.addProperty("measurement:measuredHeight", mMeasuredHeight); 23042 23043 // drawing 23044 stream.addProperty("drawing:elevation", getElevation()); 23045 stream.addProperty("drawing:translationX", getTranslationX()); 23046 stream.addProperty("drawing:translationY", getTranslationY()); 23047 stream.addProperty("drawing:translationZ", getTranslationZ()); 23048 stream.addProperty("drawing:rotation", getRotation()); 23049 stream.addProperty("drawing:rotationX", getRotationX()); 23050 stream.addProperty("drawing:rotationY", getRotationY()); 23051 stream.addProperty("drawing:scaleX", getScaleX()); 23052 stream.addProperty("drawing:scaleY", getScaleY()); 23053 stream.addProperty("drawing:pivotX", getPivotX()); 23054 stream.addProperty("drawing:pivotY", getPivotY()); 23055 stream.addProperty("drawing:opaque", isOpaque()); 23056 stream.addProperty("drawing:alpha", getAlpha()); 23057 stream.addProperty("drawing:transitionAlpha", getTransitionAlpha()); 23058 stream.addProperty("drawing:shadow", hasShadow()); 23059 stream.addProperty("drawing:solidColor", getSolidColor()); 23060 stream.addProperty("drawing:layerType", mLayerType); 23061 stream.addProperty("drawing:willNotDraw", willNotDraw()); 23062 stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated()); 23063 stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing()); 23064 stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled()); 23065 stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering()); 23066 23067 // focus 23068 stream.addProperty("focus:hasFocus", hasFocus()); 23069 stream.addProperty("focus:isFocused", isFocused()); 23070 stream.addProperty("focus:isFocusable", isFocusable()); 23071 stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode()); 23072 23073 stream.addProperty("misc:clickable", isClickable()); 23074 stream.addProperty("misc:pressed", isPressed()); 23075 stream.addProperty("misc:selected", isSelected()); 23076 stream.addProperty("misc:touchMode", isInTouchMode()); 23077 stream.addProperty("misc:hovered", isHovered()); 23078 stream.addProperty("misc:activated", isActivated()); 23079 23080 stream.addProperty("misc:visibility", getVisibility()); 23081 stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows()); 23082 stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured()); 23083 23084 stream.addProperty("misc:enabled", isEnabled()); 23085 stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled()); 23086 stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled()); 23087 23088 // theme attributes 23089 Resources.Theme theme = getContext().getTheme(); 23090 if (theme != null) { 23091 stream.addPropertyKey("theme"); 23092 theme.encode(stream); 23093 } 23094 23095 // view attribute information 23096 int n = mAttributes != null ? mAttributes.length : 0; 23097 stream.addProperty("meta:__attrCount__", n/2); 23098 for (int i = 0; i < n; i += 2) { 23099 stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]); 23100 } 23101 23102 stream.addProperty("misc:scrollBarStyle", getScrollBarStyle()); 23103 23104 // text 23105 stream.addProperty("text:textDirection", getTextDirection()); 23106 stream.addProperty("text:textAlignment", getTextAlignment()); 23107 23108 // accessibility 23109 CharSequence contentDescription = getContentDescription(); 23110 stream.addProperty("accessibility:contentDescription", 23111 contentDescription == null ? "" : contentDescription.toString()); 23112 stream.addProperty("accessibility:labelFor", getLabelFor()); 23113 stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility()); 23114 } 23115} 23116