blob: 703a5cebfa3053564051c8a5b5f0554b877421b4 [file] [log] [blame]
Scott Mainb10b48f2011-09-13 16:40:52 -07001page.title=Custom Components
Scott Main64461bf2013-04-11 19:32:08 -07002page.tags="view","widget"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003@jd:body
4
5<div id="qv-wrapper">
6<div id="qv">
7 <h2>In this document</h2>
8 <ol>
9 <li><a href="#basic">The Basic Approach</a></li>
10 <li><a href="#custom">Fully Customized Components</a></li>
11 <li><a href="#compound">Compound Controls</a></li>
12 <li><a href="#modifying">Modifying an Existing View Type</a></li>
13 </ol>
14</div>
15</div>
16
17<p>Android offers a sophisticated and powerful componentized model for building your UI,
18based on the fundamental layout classes: {@link android.view.View} and
19{@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt
20View and ViewGroup subclasses &mdash; called widgets and layouts, respectively &mdash;
21that you can use to construct your UI.</p>
22
23<p>A partial list of available widgets includes {@link android.widget.Button Button},
24{@link android.widget.TextView TextView},
25{@link android.widget.EditText EditText},
26{@link android.widget.ListView ListView},
27{@link android.widget.CheckBox CheckBox},
28{@link android.widget.RadioButton RadioButton},
29{@link android.widget.Gallery Gallery},
30{@link android.widget.Spinner Spinner}, and the more special-purpose
31{@link android.widget.AutoCompleteTextView AutoCompleteTextView},
32{@link android.widget.ImageSwitcher ImageSwitcher}, and
33{@link android.widget.TextSwitcher TextSwitcher}. </p>
34
35<p>Among the layouts available are {@link android.widget.LinearLayout LinearLayout},
Scott Maineb086d62009-05-04 13:20:20 -070036{@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037and others. For more examples, see <a href="layout-objects.html">Common Layout Objects</a>.</p>
38
39<p>If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass.
40If you only need to make small adjustments to an existing widget or layout, you can simply subclass
41the widget or layout and override its methods.
42</p>
43
44<p>Creating your own View subclasses gives you precise control over the appearance and function
45of a screen element. To give an idea of the control you get with custom views, here are some
46examples of what you could do with them:</p>
47
48<ul>
49 <li>
50 You could create a completely custom-rendered View type, for example a "volume
51 control" knob rendered using 2D graphics, and which resembles an
52 analog electronic control.
53 </li>
54 <li>
55 You could combine a group of View components into a new single component, perhaps
56 to make something like a ComboBox (a combination of popup list and free
57 entry text field), a dual-pane selector control (a left and right pane
58 with a list in each where you can re-assign which item is in which
59 list), and so on.
60 </li>
61 <li>
62 You could override the way that an EditText component is rendered on the screen
Dirk Dougherty22558d02009-12-10 16:25:06 -080063 (the <a href="{@docRoot}resources/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 to create a lined-notepad page).
65 </li>
66 <li>
67 You could capture other events like key presses and handle them in some custom
68 way (such as for a game).
69 </li>
70</ul>
71<p>
72The sections below explain how to create custom Views and use them in your application.
73For detailed reference information, see the {@link android.view.View} class. </p>
74
75
76<h2 id="basic">The Basic Approach</h2>
77
78<p>Here is a high level overview of what you need to know to get started in creating your own
79View components:</p>
80
81<ol>
82 <li>
83 Extend an existing {@link android.view.View View} class or subclass
84 with your own class.
85 </li>
86 <li>
87 Override some of the methods from the superclass. The superclass methods
88 to override start with '<code>on</code>', for
89 example, {@link android.view.View#onDraw onDraw()},
90 {@link android.view.View#onMeasure onMeasure()}, and
91 {@link android.view.View#onKeyDown onKeyDown()}.
92 This is similar to the <code>on...</code> events in {@link android.app.Activity Activity}
93 or {@link android.app.ListActivity ListActivity}
94 that you override for lifecycle and other functionality hooks.
95 <li>
96 Use your new extension class. Once completed, your new extension class
97 can be used in place of the view upon which it was based.
98 </li>
99</ol>
100<p class="note"><strong>Tip:</strong>
101 Extension classes can be defined as inner classes inside the activities
102 that use them. This is useful because it controls access to them but
103 isn't necessary (perhaps you want to create a new public View for
104 wider use in your application).
105</p>
106
107
108
109<h2 id="custom">Fully Customized Components</h2>
110<p>
111Fully customized components can be used to create graphical components that
112appear however you wish. Perhaps a graphical VU
113meter that looks like an old analog gauge, or a sing-a-long text view where
114a bouncing ball moves along the words so you can sing along with a karaoke
115machine. Either way, you want something that the built-in components just
116won't do, no matter how you combine them.</p>
117<p>Fortunately, you can easily create components that look and behave in any
118way you like, limited perhaps only by your imagination, the size of the
119screen, and the available processing power (remember that ultimately your
120application might have to run on something with significantly less power
121than your desktop workstation).</p>
122<p>To create a fully customized component:</p>
123<ol>
124 <li>
125 The most generic view you can extend is, unsurprisingly, {@link
126 android.view.View View}, so you will usually start by extending this to
127 create your new super component.
128 </li>
129 <li>
130 You can supply a constructor which can
131 take attributes and parameters from the XML, and you can also consume
132 your own such attributes and parameters (perhaps the color and range of
133 the VU meter, or the width and damping of the needle, etc.)
134 </li>
135 <li>
136 You will probably want to create your own event listeners,
137 property accessors and modifiers, and possibly more sophisticated
138 behavior in your component class as well.
139 </li>
140 <li>
141 You will almost certainly want to override <code>onMeasure()</code> and
142 are also likely to need to override <code>onDraw()</code> if you want
143 the component to show something. While both have default behavior,
144 the default <code>onDraw()</code> will do nothing, and the default
145 <code>onMeasure()</code> will always set a size of 100x100 &mdash; which is
146 probably not what you want.
147 </li>
148 <li>
149 Other <code>on...</code> methods may also be overridden as required.
150 </li>
151</ol>
152
153<h3>Extend <code>onDraw()</code> and <code>onMeasure()</code></h3>
154<p>The <code>onDraw()</code> method delivers you a {@link android.graphics.Canvas Canvas}
155upon which you can implement anything you want: 2D graphics, other standard or
156custom components, styled text, or anything else you can think of.</p>
157
158<p class="note"><strong>Note:</strong>
159This does not apply to 3D graphics. If you want to
160use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView}
Elliott Hughes7f877062009-07-30 17:00:34 -0700161instead of View, and draw from a separate thread. See the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162GLSurfaceViewActivity sample
163for details.</p>
164
165<p><code>onMeasure()</code> is a little more involved. <code>onMeasure()</code>
166is a critical piece of the rendering contract between your component and its
167container. <code>onMeasure()</code> should be overridden to efficiently and
168accurately report the measurements of its contained parts. This is made
169slightly more complex by the requirements of limits from the parent
170(which are passed in to the <code>onMeasure()</code> method) and by the
171requirement to call the <code>setMeasuredDimension()</code> method with the
172measured width and height once they have been calculated. If you fail to
173call this method from an overridden <code>onMeasure()</code> method, the
174result will be an exception at measurement time.</p>
175<p>At a high level, implementing <code>onMeasure()</code> looks something
176 like this:</p>
177
178<ol>
179 <li>
180 The overridden <code>onMeasure()</code> method is called with width and
181 height measure specifications (<code>widthMeasureSpec</code> and
182 <code>heightMeasureSpec</code> parameters, both are integer codes
183 representing dimensions) which should be treated as requirements for
184 the restrictions on the width and height measurements you should produce. A
185 full reference to the kind of restrictions these specifications can require
186 can be found in the reference documentation under {@link
187 android.view.View#onMeasure View.onMeasure(int, int)} (this reference
188 documentation does a pretty good job of explaining the whole measurement
189 operation as well).
190 </li>
191 <li>
192 Your component's <code>onMeasure()</code> method should calculate a
193 measurement width and height which will be required to render the
194 component. It should try to stay within the specifications passed in,
195 although it can choose to exceed them (in this case, the parent can
196 choose what to do, including clipping, scrolling, throwing an exception,
197 or asking the <code>onMeasure()</code> to try again, perhaps with
198 different measurement specifications).
199 </li>
200 <li>
201 Once the width and height are calculated, the <code>setMeasuredDimension(int
202 width, int height)</code> method must be called with the calculated
203 measurements. Failure to do this will result in an exception being
204 thrown.
205 </li>
206</ol>
207
208<p>
209Here's a summary of some of the other standard methods that the framework calls on views:
210</p>
211<table border="2" width="85%" align="center" cellpadding="5">
212 <thead>
213 <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
214 </thead>
215
216 <tbody>
217 <tr>
218 <td rowspan="2">Creation</td>
219 <td>Constructors</td>
220 <td>There is a form of the constructor that are called when the view
221 is created from code and a form that is called when the view is
222 inflated from a layout file. The second form should parse and apply
223 any attributes defined in the layout file.
224 </td>
225 </tr>
226 <tr>
227 <td><code>{@link android.view.View#onFinishInflate()}</code></td>
228 <td>Called after a view and all of its children has been inflated
229 from XML.</td>
230 </tr>
231
232 <tr>
233 <td rowspan="3">Layout</td>
234 <td><code>{@link android.view.View#onMeasure}</code></td>
235 <td>Called to determine the size requirements for this view and all
236 of its children.
237 </td>
238 </tr>
239 <tr>
240 <td><code>{@link android.view.View#onLayout}</code></td>
241 <td>Called when this view should assign a size and position to all
242 of its children.
243 </td>
244 </tr>
245 <tr>
246 <td><code>{@link android.view.View#onSizeChanged}</code></td>
247 <td>Called when the size of this view has changed.
248 </td>
249 </tr>
250
251 <tr>
252 <td>Drawing</td>
253 <td><code>{@link android.view.View#onDraw}</code></td>
254 <td>Called when the view should render its content.
255 </td>
256 </tr>
257
258 <tr>
259 <td rowspan="4">Event processing</td>
260 <td><code>{@link android.view.View#onKeyDown}</code></td>
261 <td>Called when a new key event occurs.
262 </td>
263 </tr>
264 <tr>
265 <td><code>{@link android.view.View#onKeyUp}</code></td>
266 <td>Called when a key up event occurs.
267 </td>
268 </tr>
269 <tr>
270 <td><code>{@link android.view.View#onTrackballEvent}</code></td>
271 <td>Called when a trackball motion event occurs.
272 </td>
273 </tr>
274 <tr>
275 <td><code>{@link android.view.View#onTouchEvent}</code></td>
276 <td>Called when a touch screen motion event occurs.
277 </td>
278 </tr>
279
280 <tr>
281 <td rowspan="2">Focus</td>
282 <td><code>{@link android.view.View#onFocusChanged}</code></td>
283 <td>Called when the view gains or loses focus.
284 </td>
285 </tr>
286
287 <tr>
288 <td><code>{@link android.view.View#onWindowFocusChanged}</code></td>
289 <td>Called when the window containing the view gains or loses focus.
290 </td>
291 </tr>
292
293 <tr>
294 <td rowspan="3">Attaching</td>
295 <td><code>{@link android.view.View#onAttachedToWindow()}</code></td>
296 <td>Called when the view is attached to a window.
297 </td>
298 </tr>
299
300 <tr>
301 <td><code>{@link android.view.View#onDetachedFromWindow}</code></td>
302 <td>Called when the view is detached from its window.
303 </td>
304 </tr>
305
306 <tr>
307 <td><code>{@link android.view.View#onWindowVisibilityChanged}</code></td>
308 <td>Called when the visibility of the window containing the view
309 has changed.
310 </td>
311 </tr>
312 </tbody>
313
314 </table>
315
316
317
318<h3 id="customexample">A Custom View Example</h3>
319<p>The CustomView sample in the
Dirk Dougherty22558d02009-12-10 16:25:06 -0800320<a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a> provides an example
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321of a customized View. The custom View is defined in the
Dirk Dougherty22558d02009-12-10 16:25:06 -0800322<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323class.</p>
324<p>The LabelView sample demonstrates a number of different aspects of custom components:</p>
325<ul>
326 <li>Extending the View class for a completely custom component.</li>
327 <li>Parameterized constructor that takes the view inflation parameters
328 (parameters defined in the XML). Some of these are passed through to the
329 View superclass, but more importantly, there are some custom attributes defined
330 and used for LabelView.</li>
331 <li>Standard public methods of the type you would expect to see for a label
332 component, for example <code>setText()</code>, <code>setTextSize()</code>,
333 <code>setTextColor()</code> and so on.</li>
334 <li>An overridden <code>onMeasure</code> method to determine and set the
335 rendering size of the component. (Note that in LabelView, the real work is done
336 by a private <code>measureWidth()</code> method.)</li>
337 <li>An overridden <code>onDraw()</code> method to draw the label onto the
338 provided canvas.</li>
339</ul>
340<p>You can see some sample usages of the LabelView custom View in
Dirk Dougherty22558d02009-12-10 16:25:06 -0800341<a href="{@docRoot}resources/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342from the samples. In particular, you can see a mix of both <code>android:</code>
343namespace parameters and custom <code>app:</code> namespace parameters. These
344<code>app:</code> parameters are the custom ones that the LabelView recognizes
345and works with, and are defined in a styleable inner class inside of the
346samples R resources definition class.</p>
347
348
349<h2 id="compound">Compound Controls
350</h2>
351<p>If you don't want to create a completely customized component, but instead
352are looking to put together a reusable component that consists of a group of
353existing controls, then creating a Compound Component (or Compound Control) might
354fit the bill. In a nutshell, this brings together a number of more atomic
355controls (or views) into a logical group of items that can be treated as a
356single thing. For example, a Combo Box can be thought of as a
357combination of a single line EditText field and an adjacent button with an attached
358 PopupList. If you press the button and select
359something from the list, it populates the EditText field, but the user can
360also type something directly into the EditText if they prefer.</p>
361<p>In Android, there are actually two other Views readily available to do
362this: {@link android.widget.Spinner Spinner} and
363{@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but
364regardless, the concept of a Combo Box makes an easy-to-understand
365example.</p>
366<p>To create a compound component:</p>
367<ol>
368 <li>
369 The usual starting point is a Layout of some kind, so create a class
370 that extends a Layout. Perhaps in the case of a Combo box we might use
371 a LinearLayout with horizontal orientation. Remember that other layouts
372 can be nested inside, so the compound component can be arbitrarily
373 complex and structured. Note that just like with an Activity, you can
374 use either the declarative (XML-based) approach to creating the
375 contained components, or you can nest them programmatically from your
376 code.
377 </li>
378 <li>
379 In the constructor for the new class, take whatever parameters the
380 superclass expects, and pass them through to the superclass constructor
381 first. Then you can set up the other views to use within your new
382 component; this is where you would create the EditText field and the
383 PopupList. Note that you also might introduce your own attributes and
384 parameters into the XML that can be pulled out and used by your
385 constructor.
386 </li>
387 <li>
388 You can also create listeners for events that your contained views might
389 generate, for example, a listener method for the List Item Click Listener
390 to update the contents of the EditText if a list selection is made.
391 </li>
392 <li>
393 You might also create your own properties with accessors and modifiers,
394 for example, allow the EditText value to be set initially in the
395 component and query for its contents when needed.
396 </li>
397 <li>
398 In the case of extending a Layout, you don't need to override the
399 <code>onDraw()</code> and <code>onMeasure()</code> methods since the
400 layout will have default behavior that will likely work just fine. However,
401 you can still override them if you need to.
402 </li>
403 <li>
404 You might override other <code>on...</code> methods, like
405 <code>onKeyDown()</code>, to perhaps choose certain default values from
406 the popup list of a combo box when a certain key is pressed.
407 </li>
408</ol>
409<p>
410 To summarize, the use of a Layout as the basis for a Custom Control has a
411number of advantages, including:</p>
412
413<ul>
414 <li>
415 You can specify the layout using the declarative XML files just like
416 with an activity screen, or you can create views programmatically and
417 nest them into the layout from your code.
418 </li>
419 <li>
420 The <code>onDraw()</code> and <code>onMeasure()</code> methods (plus
421 most of the other <code>on...</code> methods) will likely have suitable behavior so
422 you don't have to override them.
423 </li>
424 <li>
425 In the end, you can very quickly construct arbitrarily complex compound
426 views and re-use them as if they were a single component.
427 </li>
428</ul>
429<h4>Examples of Compound Controls</h4>
430<p>In the API Demos project
431 that comes with the SDK, there are two List
432 examples &mdash; Example 4 and Example 6 under Views/Lists demonstrate a
433 SpeechView which extends LinearLayout to make a component for displaying
434 Speech quotes. The corresponding classes in the sample code are
435 <code>List4.java</code> and <code>List6.java</code>.</p>
436
437
438
439<h2 id="modifying">Modifying an Existing View Type</h2>
440<p>There is an even easier option for creating a custom View which is
441useful in certain circumstances. If there is a component that is already very
442similar to what you want, you can simply extend that component and just
443override the behavior that you want to change. You can do all of the things
444you would do with a fully customized component, but by starting with a more
Elliott Hughes7f877062009-07-30 17:00:34 -0700445specialized class in the View hierarchy, you can also get a lot of behavior for
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446free that probably does exactly what you want.</p>
447<p>For example, the SDK includes a <a
Dirk Dougherty22558d02009-12-10 16:25:06 -0800448href="{@docRoot}resources/samples/NotePad/index.html">NotePad application</a> in the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449samples. This demonstrates many aspects of using the Android platform, among
450them is extending an EditText View to make a lined notepad. This is not a
451perfect example, and the APIs for doing this might change from this early
452preview, but it does demonstrate the principles.</p>
453<p>If you haven't done so already, import the
454NotePad sample into Eclipse (or
455just look at the source using the link provided). In particular look at the definition of
456<code>MyEditText</code> in the <a
Dirk Dougherty22558d02009-12-10 16:25:06 -0800457href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458file.</p>
459<p>Some points to note here</p>
460<ol>
461 <li>
462 <strong>The Definition</strong>
463 <p>The class is defined with the following line:<br/>
464 <code>public static class MyEditText extends EditText</code></p>
465
466 <ul>
467 <li>
468 It is defined as an inner class within the <code>NoteEditor</code>
469 activity, but it is public so that it could be accessed as
470 <code>NoteEditor.MyEditText</code> from outside of the <code>NoteEditor</code>
471 class if desired.
472 </li>
473 <li>
474 It is <code>static</code>, meaning it does not generate the so-called
475 "synthetic methods" that allow it to access data from the parent
476 class, which in turn means that it really behaves as a separate
477 class rather than something strongly related to <code>NoteEditor</code>.
478 This is a cleaner way to create inner classes if they do not need
479 access to state from the outer class, keeps the generated class
480 small, and allows it to be used easily from other classes.
481 </li>
482 <li>
483 It extends <code>EditText</code>, which is the View we have chosen to
484 customize in this case. When we are finished, the new class will be
485 able to substitute for a normal <code>EditText</code> view.
486 </li>
487 </ul>
488 </li>
489 <li>
490 <strong>Class Initialization</strong>
491 <p>As always, the super is called first. Furthermore,
492 this is not a default constructor, but a parameterized one. The
493 EditText is created with these parameters when it is inflated from an
494 XML layout file, thus, our constructor needs to both take them and pass them
495 to the superclass constructor as well.</p>
496 </li>
497 <li>
498 <strong>Overridden Methods</strong>
499 <p>In this example, there is only one method to be overridden:
500 <code>onDraw()</code> &mdash; but there could easily be others needed when you
501 create your own custom components.</p>
502 <p>For the NotePad sample, overriding the <code>onDraw()</code> method allows
503 us to paint the blue lines on the <code>EditText</code> view canvas (the
504 canvas is passed into the overridden <code>onDraw()</code> method). The
505 super.onDraw() method is called before the method ends. The
506 superclass method should be invoked, but in this case, we do it at the
507 end after we have painted the lines we want to include.</p>
508 <li>
509 <strong>Use the Custom Component</strong>
510 <p>We now have our custom component, but how can we use it? In the
511 NotePad example, the custom component is used directly from the
512 declarative layout, so take a look at <code>note_editor.xml</code> in the
513 <code>res/layout</code> folder.</p>
514<pre>
515&lt;view
516 class=&quot;com.android.notepad.NoteEditor$MyEditText&quot;
517 id=&quot;&#64;+id/note&quot;
518 android:layout_width=&quot;fill_parent&quot;
519 android:layout_height=&quot;fill_parent&quot;
520 android:background=&quot;&#64;android:drawable/empty&quot;
521 android:padding=&quot;10dip&quot;
522 android:scrollbars=&quot;vertical&quot;
523 android:fadingEdge=&quot;vertical&quot; /&gt;
524</pre>
525
526 <ul>
527 <li>
528 The custom component is created as a generic view in the XML, and
529 the class is specified using the full package. Note also that the
530 inner class we defined is referenced using the
531 <code>NoteEditor$MyEditText</code> notation which is a standard way to
532 refer to inner classes in the Java programming language.
533 <p>If your custom View component is not defined as an inner class, then you can,
534 alternatively, declare the View component
535 with the XML element name, and exclude the <code>class</code> attribute. For example:</p>
536<pre>
537&lt;com.android.notepad.MyEditText
538 id=&quot;&#64;+id/note&quot;
539 ... />
540</pre>
541 <p>Notice that the <code>MyEditText</code> class is now a separate class file. When the class
542 is nested in the <code>NoteEditor</code> class, this technique will not work.</p>
543 </li>
544 <li>
545 The other attributes and parameters in the definition are the ones
546 passed into the custom component constructor, and then passed
547 through to the EditText constructor, so they are the same
548 parameters that you would use for an EditText view. Note that it is
549 possible to add your own parameters as well, and we will touch on
550 this again below.
551 </li>
552 </ul>
553 </li>
554</ol>
555<p>And that's all there is to it. Admittedly this is a simple case, but
556that's the point &mdash; creating custom components is only as complicated as you
557need it to be.</p>
558<p>A more sophisticated component may override even more <code>on...</code> methods and
559introduce some of its own helper methods, substantially customizing its properties and
560behavior. The only limit is your imagination and what you need the component to
561do.</p>
562