2d-graphics.jd revision b6322a5bb9fda370cccf89434b939370dfa36b02
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 &mdash; 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 &mdash; 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>&lt;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>&lt;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      &lt;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      &lt;transition xmlns:android="http://schemas.android.com/apk/res/android">
309      &lt;item android:drawable="&#64;drawable/image_expand">
310      &lt;item android:drawable="&#64;drawable/image_collapse">
311      &lt;/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 &mdash; 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      &lt;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 &mdash;
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}guide/developing/tools/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&lt;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"/&gt;
499
500&lt;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"/&gt;
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=""/>