1 page.title=Hardware Acceleration 2 parent.title=Graphics 3 parent.link=index.html 4 @jd:body 5 6 7 <div id="qv-wrapper"> 8 <div id="qv"> 9 <h2>In this document</h2> 10 11 <ol> 12 <li><a href="#controlling">Controlling Hardware Acceleration</a></li> 13 <li><a href="#determining">Determining if a View is Hardware Accelerated</a></li> 14 <li><a href="#model">Android Drawing Models</a> 15 16 <ol> 17 <li><a href="#software-model">Software-based drawing model</a></li> 18 <li><a href="#hardware-model">Hardware accelerated drawing model</a></li> 19 </ol> 20 </li> 21 22 <li> 23 <a href="#unsupported">Unsupported Drawing Operations</a> 24 </li> 25 26 27 28 <li> 29 <a href="#layers">View Layers</a> 30 31 <ol> 32 <li><a href="#layers-anims">View Layers and Animations</a></li> 33 </ol> 34 </li> 35 36 <li><a href="#tips">Tips and Tricks</a></li> 37 </ol> 38 39 <h2>See also</h2> 40 41 <ol> 42 <li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL with the Framework 43 APIs</a></li> 44 45 <li><a href="{@docRoot}guide/topics/renderscript/index.html">Renderscript</a></li> 46 </ol> 47 </div> 48 </div> 49 50 <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline supports hardware 51 acceleration, meaning that all drawing operations that are performed on a {@link 52 android.view.View}'s canvas use the GPU. Because of the increased resources required to enable 53 hardware acceleration, your app will consume more RAM.</p> 54 55 <p>Hardware acceleration is enabled by default if your Target API level is >=14, but can also 56 be explicitly enabled. If your application uses only standard views and {@link 57 android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse drawing 58 effects. However, because hardware acceleration is not supported for all of the 2D drawing 59 operations, turning it on might affect some of your custom views or drawing calls. Problems 60 usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels. To 61 remedy this, Android gives you the option to enable or disable hardware acceleration at multiple 62 levels. See <a href="#controlling">Controlling Hardware Acceleration</a>.</p> 63 64 <p>If your application performs custom drawing, test your application on actual hardware devices 65 with hardware acceleration turned on to find any problems. The <a 66 href="#drawing-support">Unsupported drawing operations</a> section describes known issues with 67 hardware acceleration and how to work around them.</p> 68 69 <h2 id="controlling">Controlling Hardware Acceleration</h2> 70 <p>You can control hardware acceleration at the following levels:</p> 71 <ul> 72 <li>Application</li> 73 74 <li>Activity</li> 75 76 <li>Window</li> 77 78 <li>View</li> 79 </ul> 80 81 <h4>Application level</h4> 82 <p>In your Android manifest file, add the following attribute to the 83 <a href="{@docRoot}guide/topics/manifest/application-element.html"> 84 <code><application></code></a> tag to enable hardware acceleration for your entire 85 application:</p> 86 87 <pre> 88 <application android:hardwareAccelerated="true" ...> 89 </pre> 90 91 <h4>Activity level</h4> 92 <p>If your application does not behave properly with hardware acceleration turned on globally, you 93 can control it for individual activities as well. To enable or disable hardware acceleration at 94 the activity level, you can use the <code>android:hardwareAccelerated</code> attribute for 95 the <a href="{@docRoot}guide/topics/manifest/activity-element.html"> 96 <code><activity></code></a> element. The following example enables hardware acceleration for 97 the entire application but disables it for one activity:</p> 98 99 <pre> 100 <application android:hardwareAccelerated="true"> 101 <activity ... /> 102 <activity android:hardwareAccelerated="false" /> 103 </application> 104 </pre> 105 106 <h4>Window level</h4> 107 <p>If you need even more fine-grained control, you can enable hardware acceleration for a given 108 window with the following code:</p> 109 110 <pre> 111 getWindow().setFlags( 112 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, 113 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); 114 115 </pre> 116 117 <p class="note"><strong>Note</strong>: You currently cannot disable hardware acceleration at 118 the window level.</p> 119 120 <h4>View level</h4> 121 122 <p>You can disable hardware acceleration for an individual view at runtime with the 123 following code:</p> 124 125 <pre> 126 myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 127 </pre> 128 129 <p class="note"><strong>Note</strong>: You currently cannot enable hardware acceleration at 130 the view level. View layers have other functions besides disabling hardware acceleration. See <a 131 href="#layers">View layers</a> for more information about their uses.</p> 132 133 <h2 id="determining">Determining if a View is Hardware Accelerated</h2> 134 135 <p>It is sometimes useful for an application to know whether it is currently hardware 136 accelerated, especially for things such as custom views. This is particularly useful if your 137 application does a lot of custom drawing and not all operations are properly supported by the new 138 rendering pipeline.</p> 139 140 <p>There are two different ways to check whether the application is hardware accelerated:</p> 141 142 <ul> 143 <li>{@link android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} returns 144 <code>true</code> if the {@link android.view.View} is attached to a hardware accelerated 145 window.</li> 146 147 <li>{@link android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()} 148 returns <code>true</code> if the {@link android.graphics.Canvas} is hardware accelerated</li> 149 </ul> 150 151 <p>If you must do this check in your drawing code, use {@link 152 android.graphics.Canvas#isHardwareAccelerated Canvas.isHardwareAccelerated()} instead of {@link 153 android.view.View#isHardwareAccelerated View.isHardwareAccelerated()} when possible. When a view 154 is attached to a hardware accelerated window, it can still be drawn using a non-hardware 155 accelerated Canvas. This happens, for instance, when drawing a view into a bitmap for caching 156 purposes.</p> 157 158 159 <h2 id="model">Android Drawing Models</h2> 160 161 <p>When hardware acceleration is enabled, the Android framework utilizes a new drawing model that 162 utilizes <em>display lists</em> to render your application to the screen. To fully understand 163 display lists and how they might affect your application, it is useful to understand how Android 164 draws views without hardware acceleration as well. The following sections describe the 165 software-based and hardware-accelerated drawing models.</p> 166 167 <h3 id="software-model">Software-based drawing model</h3> 168 <p>In the software drawing model, views are drawn with the following two steps:</p> 169 <ol> 170 <li>Invalidate the hierarchy</li> 171 172 <li>Draw the hierarchy</li> 173 </ol> 174 175 <p>Whenever an application needs to update a part of its UI, it invokes {@link 176 android.view.View#invalidate invalidate()} (or one of its variants) on any view that has changed 177 content. The invalidation messages are propagated all the way up the view hierarchy to compute 178 the regions of the screen that need to be redrawn (the dirty region). The Android system then 179 draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are 180 two drawbacks to this drawing model:</p> 181 <ul> 182 <li>First, this model requires execution of a lot of code on every draw pass. For example, if 183 your application calls {@link android.view.View#invalidate invalidate()} on a button and that 184 button sits on top of another view, the Android system redraws the view even though it hasn't 185 changed.</li> 186 <li>The second issue is that the drawing model can hide bugs in your application. Since the 187 Android system redraws views when they intersect the dirty region, a view whose content you 188 changed might be redrawn even though {@link android.view.View#invalidate invalidate()} was not 189 called on it. When this happens, you are relying on another view being invalidated to obtain the 190 proper behavior. This behavior can change every time you modify your application. Because of 191 this, you should always call {@link android.view.View#invalidate invalidate()} on your custom 192 views whenever you modify data or state that affects the views drawing code.</li> 193 </ul> 194 195 <p class="note"><strong>Note</strong>: Android views automatically call {@link 196 android.view.View#invalidate invalidate()} when their properties change, such as the background 197 color or the text in a {@link android.widget.TextView}.</p> 198 199 <h3 id="hardware-model">Hardware accelerated drawing model</h3> 200 <p>The Android system still uses {@link android.view.View#invalidate invalidate()} and {@link 201 android.view.View#draw draw()} to request screen updates and to render views, but handles the 202 actual drawing differently. Instead of executing the drawing commands immediately, the Android 203 system records them inside display lists, which contain the output of the view hierarchys 204 drawing code. Another optimization is that the Android system only needs to record and update 205 display lists for views marked dirty by an {@link android.view.View#invalidate invalidate()} 206 call. Views that have not been invalidated can be redrawn simply by re-issuing the previously 207 recorded display list. The new drawing model contains three stages:</p> 208 209 <ol> 210 <li>Invalidate the hierarchy</li> 211 212 <li>Record and update display lists</li> 213 214 <li>Draw the display lists</li> 215 </ol> 216 217 <p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link 218 android.view.View#draw draw()} method executed. To ensure that the Android system records a 219 views display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting 220 to do so causes a view to look the same even after it has been changed.</p> 221 222 <p>Using display lists also benefits animation performance because setting specific properties, 223 such as alpha or rotation, does not require invalidating the targeted view (it is done 224 automatically). This optimization also applies to views with display lists (any view when your 225 application is hardware accelerated.) For example, assume there is a {@link 226 android.widget.LinearLayout} that contains a {@link android.widget.ListView} above a {@link 227 android.widget.Button}. The display list for the {@link android.widget.LinearLayout} looks like 228 this:</p> 229 230 <ul> 231 <li>DrawDisplayList(ListView)</li> 232 233 <li>DrawDisplayList(Button)</li> 234 </ul> 235 236 <p>Assume now that you want to change the {@link android.widget.ListView}'s opacity. After 237 invoking <code>setAlpha(0.5f)</code> on the {@link android.widget.ListView}, the display list now 238 contains this:</p> 239 240 <ul> 241 <li>SaveLayerAlpha(0.5)</li> 242 243 <li>DrawDisplayList(ListView)</li> 244 245 <li>Restore</li> 246 247 <li>DrawDisplayList(Button)</li> 248 </ul> 249 250 <p>The complex drawing code of {@link android.widget.ListView} was not executed. Instead, the 251 system only updated the display list of the much simpler {@link android.widget.LinearLayout}. In 252 an application without hardware acceleration enabled, the drawing code of both the list and its 253 parent are executed again.</p> 254 255 <h2 id="unsupported">Unsupported Drawing Operations</h2> 256 257 <p>When hardware accelerated, the 2D rendering pipeline supports the most commonly used {@link 258 android.graphics.Canvas} drawing operations as well as many less-used operations. All of the 259 drawing operations that are used to render applications that ship with Android, default widgets 260 and layouts, and common advanced visual effects such as reflections and tiled textures are 261 supported.</p> 262 263 <p>The following table describes the support level of various operations across API levels:</p> 264 265 <style type="text/css"> 266 .tblGenFixed, .tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.label_pos {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.label_neg {background-color:#ececec;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.value_pos {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.value_neg {background-color:#ececec;color:#980000;text-align:center;} 267 </style> 268 <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain"> 269 <tbody> 270 <tr class="rShim"> 271 <td class="rShim" style="width:380px;"></td> 272 <td class="rShim" style="width:240px;"></td> 273 </tr> 274 <tr> 275 <td class="s0"></td> 276 <td class="s1">First supported API level</td> 277 </tr> 278 <tr> 279 <td colspan="5" class="s5">Canvas</td> 280 </tr> 281 <tr> 282 <td class="label_pos">drawBitmapMesh() (colors array)</td> 283 <td class="value_pos">18</td> 284 </tr> 285 <tr> 286 <td class="label_neg">drawPicture()</td> 287 <td class="value_neg">23</td> 288 </tr> 289 <tr> 290 <td class="label_pos">drawPosText()</td> 291 <td class="value_pos">16</td> 292 </tr> 293 <tr> 294 <td class="label_pos">drawTextOnPath()</td> 295 <td class="value_pos">16</td> 296 </tr> 297 <tr> 298 <td class="label_neg">drawVertices()</td> 299 <td class="value_neg">✗</td> 300 </tr> 301 <tr> 302 <td class="label_pos">setDrawFilter()</td> 303 <td class="value_pos">16</td> 304 </tr> 305 <tr> 306 <td class="label_pos">clipPath()</td> 307 <td class="value_pos">18</td> 308 </tr> 309 <tr> 310 <td class="label_pos">clipRegion()</td> 311 <td class="value_pos">18</td> 312 </tr> 313 <tr> 314 <td class="label_pos">clipRect(Region.Op.XOR)</td> 315 <td class="value_pos">18</td> 316 </tr> 317 <tr> 318 <td class="label_pos">clipRect(Region.Op.Difference)</td> 319 <td class="value_pos">18</td> 320 </tr> 321 <tr> 322 <td class="label_pos">clipRect(Region.Op.ReverseDifference)</td> 323 <td class="value_pos">18</td> 324 </tr> 325 <tr> 326 <td class="label_pos">clipRect() with rotation/perspective</td> 327 <td class="value_pos">18</td> 328 </tr> 329 <tr> 330 <td class="label_pos">drawArc()</td> 331 <td class="value_pos">21</td> 332 </tr> 333 <tr> 334 <td class="label_pos">drawRoundRect()</td> 335 <td class="value_pos">21</td> 336 </tr> 337 <tr> 338 <td class="label_pos">saveLayer() with RectF dimensions</td> 339 <td class="value_pos">21</td> 340 </tr> 341 <tr> 342 <td class="label_pos">saveLayer() with float dimensions</td> 343 <td class="value_pos">21</td> 344 </tr> 345 <tr> 346 <td class="label_pos">saveLayerAlpha() with RectF dimensions</td> 347 <td class="value_pos">21</td> 348 </tr> 349 <tr> 350 <td class="label_pos">saveLayerAlpha() with float dimensions</td> 351 <td class="value_pos">21</td> 352 </tr> 353 <tr> 354 <td colspan="5" class="s5">Paint</td> 355 </tr> 356 <tr> 357 <td class="label_pos">setAntiAlias() (for text)</td> 358 <td class="value_pos">18</td> 359 </tr> 360 <tr> 361 <td class="label_pos">setAntiAlias() (for lines)</td> 362 <td class="value_pos">16</td> 363 </tr> 364 <tr> 365 <td class="label_pos">setFilterBitmap()</td> 366 <td class="value_pos">17</td> 367 </tr> 368 <tr> 369 <td class="label_neg">setLinearText()</td> 370 <td class="value_neg">✗</td> 371 </tr> 372 <tr> 373 <td class="label_neg">setMaskFilter()</td> 374 <td class="value_neg">✗</td> 375 </tr> 376 <tr> 377 <td class="label_neg">setPathEffect() (for lines)</td> 378 <td class="value_neg">✗</td> 379 </tr> 380 <tr> 381 <td class="label_neg">setRasterizer()</td> 382 <td class="value_neg">✗</td> 383 </tr> 384 <tr> 385 <td class="label_neg">setShadowLayer() (other than text)</td> 386 <td class="value_neg">✗</td> 387 </tr> 388 <tr> 389 <td class="label_pos">setStrokeCap() (for lines)</td> 390 <td class="value_pos">18</td> 391 </tr> 392 <tr> 393 <td class="label_pos">setStrokeCap() (for points)</td> 394 <td class="value_pos">19</td> 395 </tr> 396 <tr> 397 <td class="label_neg">setSubpixelText()</td> 398 <td class="value_neg">✗</td> 399 </tr> 400 <tr> 401 <td class="label_pos">getFontFeatureSettings()</td> 402 <td class="value_pos">21</td> 403 </tr> 404 <tr> 405 <td class="label_pos">isElegantTextHeight()</td> 406 <td class="value_pos">21</td> 407 </tr> 408 <tr> 409 <td class="label_pos">isElegantTextHeight()</td> 410 <td class="value_pos">21</td> 411 </tr> 412 <tr> 413 <td class="label_pos">setFontFeatureSettings()</td> 414 <td class="value_pos">21</td> 415 </tr> 416 <tr> 417 <td class="label_pos">setLetterSpacing()</td> 418 <td class="value_pos">21</td> 419 </tr> 420 <tr> 421 <td colspan="5" class="s5">Xfermode</td> 422 </tr> 423 <tr> 424 <td class="label_neg">AvoidXfermode</td> 425 <td class="value_neg">✗</td> 426 </tr> 427 <tr> 428 <td class="label_neg">PixelXorXfermode</td> 429 <td class="value_neg">✗</td> 430 </tr> 431 <tr> 432 <td class="label_neg">PorterDuff.Mode.DARKEN (framebuffer)</td> 433 <td class="value_neg">✗</td> 434 </tr> 435 <tr> 436 <td class="label_neg">PorterDuff.Mode.LIGHTEN (framebuffer)</td> 437 <td class="value_neg">✗</td> 438 </tr> 439 <tr> 440 <td class="label_neg">PorterDuff.Mode.OVERLAY (framebuffer)</td> 441 <td class="value_neg">✗</td> 442 </tr> 443 <tr> 444 <td colspan="5" class="s5">Shader</td> 445 </tr> 446 <tr> 447 <td class="label_neg">ComposeShader inside ComposeShader</td> 448 <td class="value_neg">✗</td> 449 </tr> 450 <tr> 451 <td class="label_neg">Same type shaders inside ComposeShader</td> 452 <td class="value_neg">✗</td> 453 </tr> 454 <tr> 455 <td class="label_pos">Local matrix on ComposeShader</td> 456 <td class="value_pos">18</td> 457 </tr> 458 </tbody> 459 </table> 460 461 <h3 id="scaling">Canvas Scaling</h3> 462 463 <p>The hardware accelerated 2D rendering pipeline was built first to support unscaled drawing, 464 with some drawing operations degrading quality significantly at higher scale values. These 465 operations are implemented as textures drawn at scale 1.0, transformed by the GPU. In API level 466 <17, using these operations will result in scaling artifacts increasing with scale.</p> 467 468 The following table shows when implementation was changed to correctly handle large scales: 469 470 <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain"> 471 <tbody> 472 <tr class="rShim"> 473 <td class="rShim" style="width:380px;"></td> 474 <td class="rShim" style="width:240px;"></td> 475 </tr> 476 <tr> 477 <td class="s5">Drawing operation to be scaled</td> 478 <td class="s1">First supported API level</td> 479 </tr> 480 <tr> 481 <td class="label_pos">drawText()</td> 482 <td class="value_pos">18</td> 483 </tr> 484 <tr> 485 <td class="label_neg">drawPosText()</td> 486 <td class="value_neg">✗</td> 487 </tr> 488 <tr> 489 <td class="label_neg">drawTextOnPath()</td> 490 <td class="value_neg">✗</td> 491 </tr> 492 <tr> 493 <td class="label_pos">Simple Shapes*</td> 494 <td class="value_pos">17</td> 495 </tr> 496 <tr> 497 <td class="label_neg">Complex Shapes*</td> 498 <td class="value_neg">✗</td> 499 </tr> 500 <tr> 501 <td class="label_neg">drawPath()</td> 502 <td class="value_neg">✗</td> 503 </tr> 504 <tr> 505 <td class="label_neg">Shadow layer</td> 506 <td class="value_neg">✗</td> 507 </tr> 508 </tbody> 509 </table> 510 511 <p class="note"><strong>Note</strong>: 'Simple' shapes are <code>drawRect()</code>, 512 <code>drawCircle()</code>, <code>drawOval()</code>, <code>drawRoundRect()</code>, and 513 <code>drawArc()</code> (with useCenter=false) commands issued with a Paint that doesn't have a 514 PathEffect, and doesn't contain non-default joins (via <code>setStrokeJoin()</code> / 515 <code>setStrokeMiter()</code>). Other instances of those draw commands fall under 'Complex,' in 516 the above chart.</p> 517 518 <p>If your application is affected by any of these missing features or limitations, you can turn 519 off hardware acceleration for just the affected portion of your application by calling {@link 520 android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way, you can 521 still take advantage of hardware acceleration everywhere else. See <a 522 href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable 523 and disable hardware acceleration at different levels in your application. 524 525 <h2 id="layers">View Layers</h2> 526 527 <p>In all versions of Android, views have had the ability to render into off-screen buffers, 528 either by using a view's drawing cache, or by using {@link android.graphics.Canvas#saveLayer 529 Canvas.saveLayer()}. Off-screen buffers, or layers, have several uses. You can use them to get 530 better performance when animating complex views or to apply composition effects. For instance, 531 you can implement fade effects using <code>Canvas.saveLayer()</code> to temporarily render a view 532 into a layer and then composite it back on screen with an opacity factor.</p> 533 534 <p>Beginning in Android 3.0 (API level 11), you have more control on how and when to use layers 535 with the {@link android.view.View#setLayerType View.setLayerType()} method. This API takes two 536 parameters: the type of layer you want to use and an optional {@link android.graphics.Paint} 537 object that describes how the layer should be composited. You can use the {@link 538 android.graphics.Paint} parameter to apply color filters, special blending modes, or opacity to a 539 layer. A view can use one of three layer types:</p> 540 541 <ul> 542 <li>{@link android.view.View#LAYER_TYPE_NONE}: The view is rendered normally and is not backed 543 by an off-screen buffer. This is the default behavior.</li> 544 545 <li>{@link android.view.View#LAYER_TYPE_HARDWARE}: The view is rendered in hardware into a 546 hardware texture if the application is hardware accelerated. If the application is not hardware 547 accelerated, this layer type behaves the same as {@link 548 android.view.View#LAYER_TYPE_SOFTWARE}.</li> 549 550 <li>{@link android.view.View#LAYER_TYPE_SOFTWARE}: The view is rendered in software into a 551 bitmap.</li> 552 </ul> 553 554 <p>The type of layer you use depends on your goal:</p> 555 556 <ul> 557 <li><strong>Performance</strong>: Use a hardware layer type to render a view into a hardware 558 texture. Once a view is rendered into a layer, its drawing code does not have to be executed 559 until the view calls {@link android.view.View#invalidate invalidate()}. Some animations, such as 560 alpha animations, can then be applied directly onto the layer, which is very efficient 561 for the GPU to do.</li> 562 563 <li><strong>Visual effects</strong>: Use a hardware or software layer type and a {@link 564 android.graphics.Paint} to apply special visual treatments to a view. For instance, you can 565 draw a view in black and white using a {@link 566 android.graphics.ColorMatrixColorFilter}.</li> 567 568 <li><strong>Compatibility</strong>: Use a software layer type to force a view to be rendered in 569 software. If a view that is hardware accelerated (for instance, if your whole 570 application is hardware acclerated), is having rendering problems, this is an easy way to work 571 around limitations of the hardware rendering 572 pipeline.</li> 573 </ul> 574 575 <h3 id="layers-anims">View layers and animations</h3> 576 577 <p>Hardware layers can deliver faster and smoother animations when your application 578 is hardware accelerated. Running an animation at 60 frames per second is not always possible when 579 animating complex views that issue a lot of drawing operations. This can be alleviated by 580 using hardware layers to render the view to a hardware texture. The hardware texture can 581 then be used to animate the view, eliminating the need for the view to constantly redraw itself 582 when it is being animated. The view is not redrawn unless you change the view's 583 properties, which calls {@link android.view.View#invalidate invalidate()}, or if you call {@link 584 android.view.View#invalidate invalidate()} manually. If you are running an animation in 585 your application and do not obtain the smooth results you want, consider enabling hardware layers on 586 your animated views.</p> 587 588 <p>When a view is backed by a hardware layer, some of its properties are handled by the way the 589 layer is composited on screen. Setting these properties will be efficient because they do not 590 require the view to be invalidated and redrawn. The following list of properties affect the way 591 the layer is composited. Calling the setter for any of these properties results in optimal 592 invalidation and no redrawing of the targeted view:</p> 593 594 <ul> 595 <li><code>alpha</code>: Changes the layer's opacity</li> 596 597 <li><code>x</code>, <code>y</code>, <code>translationX</code>, <code>translationY</code>: 598 Changes the layer's position</li> 599 600 <li><code>scaleX</code>, <code>scaleY</code>: Changes the layer's size</li> 601 602 <li><code>rotation</code>, <code>rotationX</code>, <code>rotationY</code>: Changes the 603 layer's orientation in 3D space</li> 604 605 <li><code>pivotX</code>, <code>pivotY</code>: Changes the layer's transformations origin</li> 606 </ul> 607 608 <p>These properties are the names used when animating a view with an {@link 609 android.animation.ObjectAnimator}. If you want to access these properties, call the appropriate 610 setter or getter. For instance, to modify the alpha property, call {@link 611 android.view.View#setAlpha setAlpha()}. The following code snippet shows the most efficient way 612 to rotate a viewiew in 3D around the Y-axis:</p> 613 <pre> 614 view.setLayerType(View.LAYER_TYPE_HARDWARE, null); 615 ObjectAnimator.ofFloat(view, "rotationY", 180).start(); 616 </pre> 617 618 <p>Because hardware layers consume video memory, it is highly recommended that you enable them 619 only for the duration of the animation and then disable them after the animation is done. You 620 can accomplish this using animation listeners:</p> 621 <pre> 622 View.setLayerType(View.LAYER_TYPE_HARDWARE, null); 623 ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180); 624 animator.addListener(new AnimatorListenerAdapter() { 625 @Override 626 public void onAnimationEnd(Animator animation) { 627 view.setLayerType(View.LAYER_TYPE_NONE, null); 628 } 629 }); 630 animator.start(); 631 </pre> 632 633 <p>For more information on property animation, see <a href= 634 "{@docRoot}guide/topics/graphics/prop-animation.html">Property Animation</a>.</p> 635 636 <h2 id="tips">Tips and Tricks</h2> 637 638 <p>Switching to hardware accelerated 2D graphics can instantly increase performance, but you 639 should still design your application to use the GPU effectively by following these 640 recommendations:</p> 641 642 <dl> 643 <dt><strong>Reduce the number of views in your application</strong></dt> 644 645 <dd>The more views the system has to draw, the slower it will be. This applies to the software 646 rendering pipeline as well. Reducing views is one of the easiest ways to optimize your UI.</dd> 647 648 <dt><strong>Avoid overdraw</strong></dt> 649 650 <dd>Do not draw too many layers on top of each other. Remove any views that are completely 651 obscured by other opaque views on top of it. If you need to draw several layers blended on top 652 of each other, consider merging them into a single layer. A good rule of thumb with current 653 hardware is to not draw more than 2.5 times the number of pixels on screen per frame 654 (transparent pixels in a bitmap count!).</dd> 655 656 <dt><strong>Don't create render objects in draw methods</strong></dt> 657 658 <dd>A common mistake is to create a new {@link android.graphics.Paint} or a new {@link 659 android.graphics.Path} every time a rendering method is invoked. This forces the garbage 660 collector to run more often and also bypasses caches and optimizations in the hardware 661 pipeline.</dd> 662 663 <dt><strong>Don't modify shapes too often</strong></dt> 664 665 <dd>Complex shapes, paths, and circles for instance, are rendered using texture masks. Every 666 time you create or modify a path, the hardware pipeline creates a new mask, which can be 667 expensive.</dd> 668 669 <dt><strong>Don't modify bitmaps too often</strong></dt> 670 671 <dd>Every time you change the content of a bitmap, it is uploaded again as a GPU texture the 672 next time you draw it.</dd> 673 674 <dt><strong>Use alpha with care</strong></dt> 675 676 <dd>When you make a view translucent using {@link android.view.View#setAlpha setAlpha()}, 677 {@link android.view.animation.AlphaAnimation}, or {@link android.animation.ObjectAnimator}, it 678 is rendered in an off-screen buffer which doubles the required fill-rate. When applying alpha 679 on very large views, consider setting the view's layer type to 680 <code>LAYER_TYPE_HARDWARE</code>.</dd> 681 </dl> 682