1page.title=Canvas and Drawables 2parent.title=Graphics 3parent.link=index.html 4@jd:body 5 6<div id="qv-wrapper"> 7 <div id="qv"> 8 <h2>In this document</h2> 9 <ol> 10 <li><a href="#draw-with-canvas">Draw with a Canvas</a> 11 <ol> 12 <li><a href="#on-view">On a View</a></li> 13 <li><a href="#on-surfaceview">On a SurfaceView</a></li> 14 </ol> 15 </li> 16 <li><a href="#drawables">Drawables</a> 17 <ol> 18 <li><a href="#drawables-from-images">Creating from resource images</a></li> 19 <li><a href="#drawables-from-xml">Creating from resource XML</a></li> 20 </ol> 21 </li> 22 <li><a href="#shape-drawable">Shape Drawable</a></li> 23 <li><a href="#nine-patch">Nine-patch</a></li> 24 </ol> 25 26 <h2>See also</h2> 27 <ol> 28 <li><a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL with the Framework 29APIs</a></li> 30 <li><a href="{@docRoot}guide/topics/renderscript/index.html">RenderScript</a></li> 31 </ol> 32 </div> 33</div> 34 35<p>The Android framework APIs provides a set 2D drawing APIs that allow you to render your own 36custom graphics onto a canvas or to modify existing Views to customize their look and feel. 37When drawing 2D graphics, you'll typically do so in one of two ways:</p> 38 39<ol type="a"> 40 <li>Draw your graphics or animations into a View object from your layout. In this manner, 41 the drawing of your graphics is handled by the system's 42 normal View hierarchy drawing process — you simply define the graphics to go inside the View.</li> 43 <li>Draw your graphics directly to a Canvas. This way, you personally call the appropriate class's 44 {@link android.view.View#onDraw onDraw()} method (passing it your Canvas), or one of the Canvas 45<code>draw...()</code> methods (like 46 <code>{@link android.graphics.Canvas#drawPicture(Picture,Rect) drawPicture()}</code>). In doing so, you are also in 47 control of any animation.</li> 48</ol> 49 50<p>Option "a," drawing to a View, is your best choice when you want to draw simple graphics that do not 51need to change dynamically and are not part of a performance-intensive game. For example, you should 52draw your graphics into a View when you want to display a static graphic or predefined animation, within 53an otherwise static application. Read <a href="#drawables">Drawables</a> for more information.</li> 54</p> 55 56<p>Option "b," drawing to a Canvas, is better when your application needs to regularly re-draw itself. 57Applications such as video games should be drawing to the Canvas on its own. However, there's more than 58one way to do this:</p> 59 60<ul> 61 <li>In the same thread as your UI Activity, wherein you create a custom View component in 62 your layout, call <code>{@link android.view.View#invalidate()}</code> and then handle the 63 <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback.</li> 64 <li>Or, in a separate thread, wherein you manage a {@link android.view.SurfaceView} and 65 perform draws to the Canvas as fast as your thread is capable 66 (you do not need to request <code>invalidate()</code>).</li> 67</ul> 68 69<h2 id="draw-with-canvas">Draw with a Canvas</h2> 70 71<p>When you're writing an application in which you would like to perform specialized drawing 72and/or control the animation of graphics, 73you should do so by drawing through a {@link android.graphics.Canvas}. A Canvas works for you as 74a pretense, or interface, to the actual surface upon which your graphics will be drawn — it 75holds all of your "draw" calls. Via the Canvas, your drawing is actually performed upon an 76underlying {@link android.graphics.Bitmap}, which is placed into the window.</p> 77 78<p>In the event that you're drawing within the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> 79callback method, the Canvas is provided for you and you need only place your drawing calls upon it. 80You can also acquire a Canvas from <code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code>, 81when dealing with a SurfaceView object. (Both of these scenarios are discussed in the following sections.) 82However, if you need to create a new Canvas, then you must define the {@link android.graphics.Bitmap} 83upon which drawing will actually be performed. The Bitmap is always required for a Canvas. You can set up 84a new Canvas like this:</p> 85<pre> 86Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); 87Canvas c = new Canvas(b); 88</pre> 89 90<p>Now your Canvas will draw onto the defined Bitmap. After drawing upon it with the Canvas, you can then carry your 91Bitmap to another Canvas with one of the <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Matrix,Paint) 92Canvas.drawBitmap(Bitmap,...)}</code> methods. It's recommended that you ultimately draw your final 93graphics through a Canvas offered to you 94by <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code> or 95<code>{@link android.view.SurfaceHolder#lockCanvas() SurfaceHolder.lockCanvas()}</code> (see the following sections).</p> 96 97<p>The {@link android.graphics.Canvas} class has its own set of drawing methods that you can use, 98like <code>drawBitmap(...)</code>, <code>drawRect(...)</code>, <code>drawText(...)</code>, and many more. 99Other classes that you might use also have <code>draw()</code> methods. For example, you'll probably 100have some {@link android.graphics.drawable.Drawable} objects that you want to put on the Canvas. Drawable 101has its own <code>{@link android.graphics.drawable.Drawable#draw(Canvas) draw()}</code> method 102that takes your Canvas as an argument.</p> 103 104 105<h3 id="on-view">On a View</h3> 106 107<p>If your application does not require a significant amount of processing or 108frame-rate speed (perhaps for a chess game, a snake game, 109or another slowly-animated application), then you should consider creating a custom View component 110and drawing with a Canvas in <code>{@link android.view.View#onDraw(Canvas) View.onDraw()}</code>. 111The most convenient aspect of doing so is that the Android framework will 112provide you with a pre-defined Canvas to which you will place your drawing calls.</p> 113 114<p>To start, extend the {@link android.view.View} class (or descendant thereof) and define 115the <code>{@link android.view.View#onDraw(Canvas) onDraw()}</code> callback method. This method will be called by the Android 116framework to request that your View draw itself. This is where you will perform all your calls 117to draw through the {@link android.graphics.Canvas}, which is passed to you through the <code>onDraw()</code> callback.</p> 118 119<p>The Android framework will only call <code>onDraw()</code> as necessary. Each time that 120your application is prepared to be drawn, you must request your View be invalidated by calling 121<code>{@link android.view.View#invalidate()}</code>. This indicates that you'd like your View to be drawn and 122Android will then call your <code>onDraw()</code> method (though is not guaranteed that the callback will 123be instantaneous). </p> 124 125<p>Inside your View component's <code>onDraw()</code>, use the Canvas given to you for all your drawing, 126using various <code>Canvas.draw...()</code> methods, or other class <code>draw()</code> methods that 127take your Canvas as an argument. Once your <code>onDraw()</code> is complete, the Android framework will 128use your Canvas to draw a Bitmap handled by the system.</p> 129 130<p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main 131Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p> 132 133<p>For information about extending the {@link android.view.View} class, read 134<a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>.</p> 135 136<p>For a sample application, see the Snake game, in the SDK samples folder: 137<code><your-sdk-directory>/samples/Snake/</code>.</p> 138 139<h3 id="on-surfaceview">On a SurfaceView</h3> 140 141<p>The {@link android.view.SurfaceView} is a special subclass of View that offers a dedicated 142drawing surface within the View hierarchy. The aim is to offer this drawing surface to 143an application's secondary thread, so that the application isn't required 144to wait until the system's View hierarchy is ready to draw. Instead, a secondary thread 145that has reference to a SurfaceView can draw to its own Canvas at its own pace.</p> 146 147<p>To begin, you need to create a new class that extends {@link android.view.SurfaceView}. The class should also 148implement {@link android.view.SurfaceHolder.Callback}. This subclass is an interface that will notify you 149with information about the underlying {@link android.view.Surface}, such as when it is created, changed, or destroyed. 150These events are important so that you know when you can start drawing, whether you need 151to make adjustments based on new surface properties, and when to stop drawing and potentially 152kill some tasks. Inside your SurfaceView class is also a good place to define your secondary Thread class, which will 153perform all the drawing procedures to your Canvas.</p> 154 155<p>Instead of handling the Surface object directly, you should handle it via 156a {@link android.view.SurfaceHolder}. So, when your SurfaceView is initialized, get the SurfaceHolder by calling 157<code>{@link android.view.SurfaceView#getHolder()}</code>. You should then notify the SurfaceHolder that you'd 158like to receive SurfaceHolder callbacks (from {@link android.view.SurfaceHolder.Callback}) by calling 159{@link android.view.SurfaceHolder#addCallback(SurfaceHolder.Callback) addCallback()} 160(pass it <var>this</var>). Then override each of the 161{@link android.view.SurfaceHolder.Callback} methods inside your SurfaceView class.</p> 162 163<p>In order to draw to the Surface Canvas from within your second thread, you must pass the thread your SurfaceHandler 164and retrieve the Canvas with <code>{@link android.view.SurfaceHolder#lockCanvas() lockCanvas()}</code>. 165You can now take the Canvas given to you by the SurfaceHolder and do your necessary drawing upon it. 166Once you're done drawing with the Canvas, call 167<code>{@link android.view.SurfaceHolder#unlockCanvasAndPost(Canvas) unlockCanvasAndPost()}</code>, passing it 168your Canvas object. The Surface will now draw the Canvas as you left it. Perform this sequence of locking and 169unlocking the canvas each time you want to redraw.</p> 170 171<p class="note"><strong>Note:</strong> On each pass you retrieve the Canvas from the SurfaceHolder, 172the previous state of the Canvas will be retained. In order to properly animate your graphics, you must re-paint the 173entire surface. For example, you can clear the previous state of the Canvas by filling in a color 174with <code>{@link android.graphics.Canvas#drawColor(int) drawColor()}</code> or setting a background image 175with <code>{@link android.graphics.Canvas#drawBitmap(Bitmap,Rect,RectF,Paint) drawBitmap()}</code>. Otherwise, 176you will see traces of the drawings you previously performed.</p> 177 178 179<p>For a sample application, see the Lunar Lander game, in the SDK samples folder: 180<code><your-sdk-directory>/samples/LunarLander/</code>. Or, 181browse the source in the <a href="{@docRoot}guide/samples/index.html">Sample Code</a> section.</p> 182 183<h2 id="drawables">Drawables</h2> 184<p>Android offers a custom 2D graphics library for drawing shapes and images. 185 The {@link android.graphics.drawable} package is where you'll find the common classes used for 186 drawing in two-dimensions.</p> 187 188<p>This document discusses the basics of using Drawable objects to draw graphics and how to use a 189couple subclasses of the Drawable class. For information on using Drawables to do frame-by-frame 190animation, see <a href="{@docRoot}guide/topics/graphics/drawable-animation.html">Drawable 191Animation</a>.</p> 192 193<p>A {@link android.graphics.drawable.Drawable} is a general abstraction for "something that can be 194 drawn." You'll discover that the Drawable class extends to define a variety of specific kinds of 195drawable graphics, including {@link android.graphics.drawable.BitmapDrawable}, {@link 196 android.graphics.drawable.ShapeDrawable}, {@link android.graphics.drawable.PictureDrawable}, 197{@link android.graphics.drawable.LayerDrawable}, and several more. Of course, you can also extend 198these to define your own custom Drawable objects that behave in unique ways.</p> 199 200<p>There are three ways to define and instantiate a Drawable: using an image saved in your project 201 resources; using an XML file that defines the Drawable properties; or using the normal class 202constructors. Below, we'll discuss each the first two techniques (using constructors is nothing new 203for an experienced developer).</p> 204 205 206<h3 id="drawables-from-images">Creating from resource images</h3> 207 208<p>A simple way to add graphics to your application is by referencing an image file from your 209 project resources. Supported file types are PNG (preferred), JPG (acceptable) and GIF 210(discouraged). This technique would obviously be preferred for application icons, logos, or other 211graphics such as those used in a game.</p> 212 213<p>To use an image resource, just add your file to the <code>res/drawable/</code> directory of your 214 project. From there, you can reference it from your code or your XML layout. 215 Either way, it is referred using a resource ID, which is the file name without the file type 216 extension (E.g., <code>my_image.png</code> is referenced as <var>my_image</var>).</p> 217 218<p class="note"><strong>Note:</strong> Image resources placed in <code>res/drawable/</code> may be 219 automatically optimized with lossless image compression by the 220 <code>aapt</code> tool during the build process. For example, a true-color PNG that does 221 not require more than 256 colors may be converted to an 8-bit PNG with a color palette. This 222 will result in an image of equal quality but which requires less memory. So be aware that the 223 image binaries placed in this directory can change during the build. If you plan on reading 224 an image as a bit stream in order to convert it to a bitmap, put your images in the 225 <code>res/raw/</code> folder instead, where they will not be optimized.</p> 226 227<h4>Example code</h4> 228<p>The following code snippet demonstrates how to build an {@link android.widget.ImageView} that 229 uses an image from drawable resources and add it to the layout.</p> 230<pre> 231 LinearLayout mLinearLayout; 232 233 protected void onCreate(Bundle savedInstanceState) { 234 super.onCreate(savedInstanceState); 235 236 // Create a LinearLayout in which to add the ImageView 237 mLinearLayout = new LinearLayout(this); 238 239 // Instantiate an ImageView and define its properties 240 ImageView i = new ImageView(this); 241 i.setImageResource(R.drawable.my_image); 242 i.setAdjustViewBounds(true); // set the ImageView bounds to match the Drawable's dimensions 243 i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, 244 LayoutParams.WRAP_CONTENT)); 245 246 // Add the ImageView to the layout and set the layout as the content view 247 mLinearLayout.addView(i); 248 setContentView(mLinearLayout); 249 } 250</pre> 251<p>In other cases, you may want to handle your image resource as a 252 {@link android.graphics.drawable.Drawable} object. 253 To do so, create a Drawable from the resource like so: 254 <pre> 255 Resources res = mContext.getResources(); 256 Drawable myImage = res.getDrawable(R.drawable.my_image); 257 </pre> 258 259 <p class="warning"><strong>Note:</strong> Each unique resource in your project can maintain only 260one state, no matter how many different objects you may instantiate for it. For example, if you 261 instantiate two Drawable objects from the same image resource, then change a property (such 262as the alpha) for one of the Drawables, then it will also affect the other. So when dealing with 263multiple instances of an image resource, instead of directly transforming the Drawable, you 264should perform a <a href="{@docRoot}guide/topics/graphics/view-animation.html#tween-animation">tween 265animation</a>.</p> 266 267 268 <h4>Example XML</h4> 269 <p>The XML snippet below shows how to add a resource Drawable to an 270 {@link android.widget.ImageView} in the XML layout (with some red tint just for fun). 271 <pre> 272 <ImageView 273 android:layout_width="wrap_content" 274 android:layout_height="wrap_content" 275 android:tint="#55ff0000" 276 android:src="@drawable/my_image"/> 277 </pre> 278 <p>For more information on using project resources, read about 279 <a href="{@docRoot}guide/topics/resources/index.html">Resources and Assets</a>.</p> 280 281 282 <h3 id="drawables-from-xml">Creating from resource XML</h3> 283 284 <p>By now, you should be familiar with Android's principles of developing a 285 <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a>. Hence, you understand the 286power and flexibility inherent in defining objects in XML. This philosophy caries over from Views 287to Drawables. If there is a Drawable object that you'd like to create, which is not initially 288dependent on variables defined by your application code or user interaction, then defining the 289Drawable in XML is a good option. Even if you expect your Drawable to change its properties 290during the user's experience with your application, you should consider defining the object in 291XML, as you can always modify properties once it is instantiated.</p> 292 293 <p>Once you've defined your Drawable in XML, save the file in the <code>res/drawable/</code> 294 directory of your project. Then, retrieve and instantiate the object by calling 295 {@link android.content.res.Resources#getDrawable(int) Resources.getDrawable()}, passing it the 296 resource ID of your XML file. (See the <a href="#drawable-xml-example">example 297below</a>.)</p> 298 299 <p>Any Drawable subclass that supports the <code>inflate()</code> method can be defined in 300 XML and instantiated by your application. Each Drawable that supports XML inflation utilizes 301specific XML attributes that help define the object 302 properties (see the class reference to see what these are). See the class documentation for each 303 Drawable subclass for information on how to define it in XML. 304 305 <h4 id="drawable-xml-example">Example</h4> 306 <p>Here's some XML that defines a TransitionDrawable:</p> 307 <pre> 308 <transition xmlns:android="http://schemas.android.com/apk/res/android"> 309 <item android:drawable="@drawable/image_expand"> 310 <item android:drawable="@drawable/image_collapse"> 311 </transition> 312 </pre> 313 314 <p>With this XML saved in the file <code>res/drawable/expand_collapse.xml</code>, 315 the following code will instantiate the TransitionDrawable and set it as the content of an 316 ImageView:</p> 317 <pre> 318 Resources res = mContext.getResources(); 319 TransitionDrawable transition = (TransitionDrawable) 320res.getDrawable(R.drawable.expand_collapse); 321 ImageView image = (ImageView) findViewById(R.id.toggle_image); 322 image.setImageDrawable(transition); 323 </pre> 324 <p>Then this transition can be run forward (for 1 second) with:</p> 325 <pre>transition.startTransition(1000);</pre> 326 327 <p>Refer to the Drawable classes listed above for more information on the XML attributes 328supported by each.</p> 329 330 331 332 <h2 id="shape-drawable">Shape Drawable</h2> 333 334 <p>When you want to dynamically draw some two-dimensional graphics, a {@link 335 android.graphics.drawable.ShapeDrawable} 336 object will probably suit your needs. With a ShapeDrawable, you can programmatically draw 337 primitive shapes and style them in any way imaginable.</p> 338 339 <p>A ShapeDrawable is an extension of {@link android.graphics.drawable.Drawable}, so you can use 340one where ever 341 a Drawable is expected — perhaps for the background of a View, set with 342 {@link android.view.View#setBackgroundDrawable(android.graphics.drawable.Drawable) 343 setBackgroundDrawable()}. 344 Of course, you can also draw your shape as its own custom {@link android.view.View}, 345 to be added to your layout however you please. 346 Because the ShapeDrawable has its own <code>draw()</code> method, you can create a subclass of 347View that 348 draws the ShapeDrawable during the <code>View.onDraw()</code> method. 349 Here's a basic extension of the View class that does just this, to draw a ShapeDrawable as a 350 View:</p> 351 <pre> 352 public class CustomDrawableView extends View { 353 private ShapeDrawable mDrawable; 354 355 public CustomDrawableView(Context context) { 356 super(context); 357 358 int x = 10; 359 int y = 10; 360 int width = 300; 361 int height = 50; 362 363 mDrawable = new ShapeDrawable(new OvalShape()); 364 mDrawable.getPaint().setColor(0xff74AC23); 365 mDrawable.setBounds(x, y, x + width, y + height); 366 } 367 368 protected void onDraw(Canvas canvas) { 369 mDrawable.draw(canvas); 370 } 371 } 372 </pre> 373 374 <p>In the constructor, a ShapeDrawable is defines as an {@link 375 android.graphics.drawable.shapes.OvalShape}. 376 It's then given a color and the bounds of the shape are set. If you do not set the bounds, 377then the 378 shape will not be drawn, whereas if you don't set the color, it will default to black.</p> 379 <p>With the custom View defined, it can be drawn any way you like. With the sample above, we can 380 draw the shape programmatically in an Activity:</p> 381 <pre> 382 CustomDrawableView mCustomDrawableView; 383 384 protected void onCreate(Bundle savedInstanceState) { 385 super.onCreate(savedInstanceState); 386 mCustomDrawableView = new CustomDrawableView(this); 387 388 setContentView(mCustomDrawableView); 389 } 390 </pre> 391 392 <p>If you'd like to draw this custom drawable from the XML layout instead of from the Activity, 393 then the CustomDrawable class must override the {@link 394 android.view.View#View(android.content.Context, android.util.AttributeSet) View(Context, 395 AttributeSet)} constructor, which is called when 396 instantiating a View via inflation from XML. Then add a CustomDrawable element to the XML, 397 like so:</p> 398 <pre> 399 <com.example.shapedrawable.CustomDrawableView 400 android:layout_width="fill_parent" 401 android:layout_height="wrap_content" 402 /> 403 </pre> 404 405 <p>The ShapeDrawable class (like many other Drawable types in the {@link 406android.graphics.drawable} package) 407 allows you to define various properties of the drawable with public methods. 408 Some properties you might want to adjust include 409 alpha transparency, color filter, dither, opacity and color.</p> 410 411 <p>You can also define primitive drawable shapes using XML. For more information, see the 412 section about Shape Drawables in the <a 413 414href="{@docRoot}guide/topics/resources/drawable-resource.html#Shape">Drawable Resources</a> 415 document.</p> 416 417 <!-- TODO 418 <h2 id="state-list">StateListDrawable</h2> 419 420 <p>A StateListDrawable is an extension of the DrawableContainer class, making it little 421different. 422 The primary distinction is that the 423 StateListDrawable manages a collection of images for the Drawable, instead of just one. 424 This means that it can switch the image when you want, without switching objects. However, 425the 426 intention of the StateListDrawable is to automatically change the image used based on the 427state 428 of the object it's attached to. 429 --> 430 431 <h2 id="nine-patch">Nine-patch</h2> 432 433 <p>A {@link android.graphics.drawable.NinePatchDrawable} graphic is a stretchable bitmap 434image, which Android 435 will automatically resize to accommodate the contents of the View in which you have 436placed it as the background. 437 An example use of a NinePatch is the backgrounds used by standard Android buttons — 438 buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a 439standard PNG 440 image that includes an extra 1-pixel-wide border. It must be saved with the extension 441 <code>.9.png</code>, 442 and saved into the <code>res/drawable/</code> directory of your project. 443 </p> 444 <p> 445 The border is used to define the stretchable and static areas of 446 the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide 447 black line(s) in the left and top part of the border (the other border pixels should 448 be fully transparent or white). You can have as many stretchable sections as you want: 449 their relative size stays the same, so the largest sections always remain the largest. 450 </p> 451 <p> 452 You can also define an optional drawable section of the image (effectively, 453 the padding lines) by drawing a line on the right and bottom lines. 454 If a View object sets the NinePatch as its background and then specifies the 455 View's text, it will stretch itself so that all the text fits inside only 456 the area designated by the right and bottom lines (if included). If the 457 padding lines are not included, Android uses the left and top lines to 458 define this drawable area. 459 </p> 460 <p>To clarify the difference between the different lines, the left and top lines define 461 which pixels of the image are allowed to be replicated in order to stretch the image. 462 The bottom and right lines define the relative area within the image that the contents 463 of the View are allowed to lie within.</p> 464 <p> 465 Here is a sample NinePatch file used to define a button: 466 </p> 467 <img src="{@docRoot}images/ninepatch_raw.png" alt="" /> 468 469 <p>This NinePatch defines one stretchable area with the left and top lines 470 and the drawable area with the bottom and right lines. In the top image, the dotted grey 471 lines identify the regions of the image that will be replicated in order to stretch the 472image. The pink 473 rectangle in the bottom image identifies the region in which the contents of the View are 474allowed. 475 If the contents don't fit in this region, then the image will be stretched so that they 476do. 477</p> 478 479<p>The <a href="{@docRoot}tools/help/draw9patch.html">Draw 9-patch</a> tool offers 480 an extremely handy way to create your NinePatch images, using a WYSIWYG graphics editor. It 481even raises warnings if the region you've defined for the stretchable area is at risk of 482producing drawing artifacts as a result of the pixel replication. 483</p> 484 485<h3>Example XML</h3> 486 487<p>Here's some sample layout XML that demonstrates how to add a NinePatch image to a 488couple of buttons. (The NinePatch image is saved as 489<code>res/drawable/my_button_background.9.png</code> 490<pre> 491<Button id="@+id/tiny" 492 android:layout_width="wrap_content" 493 android:layout_height="wrap_content" 494 android:layout_alignParentTop="true" 495 android:layout_centerInParent="true" 496 android:text="Tiny" 497 android:textSize="8sp" 498 android:background="@drawable/my_button_background"/> 499 500<Button id="@+id/big" 501 android:layout_width="wrap_content" 502 android:layout_height="wrap_content" 503 android:layout_alignParentBottom="true" 504 android:layout_centerInParent="true" 505 android:text="Biiiiiiig text!" 506 android:textSize="30sp" 507 android:background="@drawable/my_button_background"/> 508</pre> 509<p>Note that the width and height are set to "wrap_content" to make the button fit neatly around the 510text. 511</p> 512 513<p>Below are the two buttons rendered from the XML and NinePatch image shown above. 514Notice how the width and height of the button varies with the text, and the background image 515stretches to accommodate it. 516</p> 517 518<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>