| page.title=Building Custom Components |
| parent.title=User Interface |
| parent.link=index.html |
| @jd:body |
| |
| <div id="qv-wrapper"> |
| <div id="qv"> |
| <h2>In this document</h2> |
| <ol> |
| <li><a href="#basic">The Basic Approach</a></li> |
| <li><a href="#custom">Fully Customized Components</a></li> |
| <li><a href="#compound">Compound Controls</a></li> |
| <li><a href="#modifying">Modifying an Existing View Type</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p>Android offers a sophisticated and powerful componentized model for building your UI, |
| based on the fundamental layout classes: {@link android.view.View} and |
| {@link android.view.ViewGroup}. To start with, the platform includes a variety of prebuilt |
| View and ViewGroup subclasses — called widgets and layouts, respectively — |
| that you can use to construct your UI.</p> |
| |
| <p>A partial list of available widgets includes {@link android.widget.Button Button}, |
| {@link android.widget.TextView TextView}, |
| {@link android.widget.EditText EditText}, |
| {@link android.widget.ListView ListView}, |
| {@link android.widget.CheckBox CheckBox}, |
| {@link android.widget.RadioButton RadioButton}, |
| {@link android.widget.Gallery Gallery}, |
| {@link android.widget.Spinner Spinner}, and the more special-purpose |
| {@link android.widget.AutoCompleteTextView AutoCompleteTextView}, |
| {@link android.widget.ImageSwitcher ImageSwitcher}, and |
| {@link android.widget.TextSwitcher TextSwitcher}. </p> |
| |
| <p>Among the layouts available are {@link android.widget.LinearLayout LinearLayout}, |
| {@link android.widget.FrameLayout FrameLayout}, {@link android.widget.RelativeLayout RelativeLayout}, |
| and others. For more examples, see <a href="layout-objects.html">Common Layout Objects</a>.</p> |
| |
| <p>If none of the prebuilt widgets or layouts meets your needs, you can create your own View subclass. |
| If you only need to make small adjustments to an existing widget or layout, you can simply subclass |
| the widget or layout and override its methods. |
| </p> |
| |
| <p>Creating your own View subclasses gives you precise control over the appearance and function |
| of a screen element. To give an idea of the control you get with custom views, here are some |
| examples of what you could do with them:</p> |
| |
| <ul> |
| <li> |
| You could create a completely custom-rendered View type, for example a "volume |
| control" knob rendered using 2D graphics, and which resembles an |
| analog electronic control. |
| </li> |
| <li> |
| You could combine a group of View components into a new single component, perhaps |
| to make something like a ComboBox (a combination of popup list and free |
| entry text field), a dual-pane selector control (a left and right pane |
| with a list in each where you can re-assign which item is in which |
| list), and so on. |
| </li> |
| <li> |
| You could override the way that an EditText component is rendered on the screen |
| (the <a href="{@docRoot}resources/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect, |
| to create a lined-notepad page). |
| </li> |
| <li> |
| You could capture other events like key presses and handle them in some custom |
| way (such as for a game). |
| </li> |
| </ul> |
| <p> |
| The sections below explain how to create custom Views and use them in your application. |
| For detailed reference information, see the {@link android.view.View} class. </p> |
| |
| |
| <h2 id="basic">The Basic Approach</h2> |
| |
| <p>Here is a high level overview of what you need to know to get started in creating your own |
| View components:</p> |
| |
| <ol> |
| <li> |
| Extend an existing {@link android.view.View View} class or subclass |
| with your own class. |
| </li> |
| <li> |
| Override some of the methods from the superclass. The superclass methods |
| to override start with '<code>on</code>', for |
| example, {@link android.view.View#onDraw onDraw()}, |
| {@link android.view.View#onMeasure onMeasure()}, and |
| {@link android.view.View#onKeyDown onKeyDown()}. |
| This is similar to the <code>on...</code> events in {@link android.app.Activity Activity} |
| or {@link android.app.ListActivity ListActivity} |
| that you override for lifecycle and other functionality hooks. |
| <li> |
| Use your new extension class. Once completed, your new extension class |
| can be used in place of the view upon which it was based. |
| </li> |
| </ol> |
| <p class="note"><strong>Tip:</strong> |
| Extension classes can be defined as inner classes inside the activities |
| that use them. This is useful because it controls access to them but |
| isn't necessary (perhaps you want to create a new public View for |
| wider use in your application). |
| </p> |
| |
| |
| |
| <h2 id="custom">Fully Customized Components</h2> |
| <p> |
| Fully customized components can be used to create graphical components that |
| appear however you wish. Perhaps a graphical VU |
| meter that looks like an old analog gauge, or a sing-a-long text view where |
| a bouncing ball moves along the words so you can sing along with a karaoke |
| machine. Either way, you want something that the built-in components just |
| won't do, no matter how you combine them.</p> |
| <p>Fortunately, you can easily create components that look and behave in any |
| way you like, limited perhaps only by your imagination, the size of the |
| screen, and the available processing power (remember that ultimately your |
| application might have to run on something with significantly less power |
| than your desktop workstation).</p> |
| <p>To create a fully customized component:</p> |
| <ol> |
| <li> |
| The most generic view you can extend is, unsurprisingly, {@link |
| android.view.View View}, so you will usually start by extending this to |
| create your new super component. |
| </li> |
| <li> |
| You can supply a constructor which can |
| take attributes and parameters from the XML, and you can also consume |
| your own such attributes and parameters (perhaps the color and range of |
| the VU meter, or the width and damping of the needle, etc.) |
| </li> |
| <li> |
| You will probably want to create your own event listeners, |
| property accessors and modifiers, and possibly more sophisticated |
| behavior in your component class as well. |
| </li> |
| <li> |
| You will almost certainly want to override <code>onMeasure()</code> and |
| are also likely to need to override <code>onDraw()</code> if you want |
| the component to show something. While both have default behavior, |
| the default <code>onDraw()</code> will do nothing, and the default |
| <code>onMeasure()</code> will always set a size of 100x100 — which is |
| probably not what you want. |
| </li> |
| <li> |
| Other <code>on...</code> methods may also be overridden as required. |
| </li> |
| </ol> |
| |
| <h3>Extend <code>onDraw()</code> and <code>onMeasure()</code></h3> |
| <p>The <code>onDraw()</code> method delivers you a {@link android.graphics.Canvas Canvas} |
| upon which you can implement anything you want: 2D graphics, other standard or |
| custom components, styled text, or anything else you can think of.</p> |
| |
| <p class="note"><strong>Note:</strong> |
| This does not apply to 3D graphics. If you want to |
| use 3D graphics, you must extend {@link android.view.SurfaceView SurfaceView} |
| instead of View, and draw from a separate thread. See the |
| GLSurfaceViewActivity sample |
| for details.</p> |
| |
| <p><code>onMeasure()</code> is a little more involved. <code>onMeasure()</code> |
| is a critical piece of the rendering contract between your component and its |
| container. <code>onMeasure()</code> should be overridden to efficiently and |
| accurately report the measurements of its contained parts. This is made |
| slightly more complex by the requirements of limits from the parent |
| (which are passed in to the <code>onMeasure()</code> method) and by the |
| requirement to call the <code>setMeasuredDimension()</code> method with the |
| measured width and height once they have been calculated. If you fail to |
| call this method from an overridden <code>onMeasure()</code> method, the |
| result will be an exception at measurement time.</p> |
| <p>At a high level, implementing <code>onMeasure()</code> looks something |
| like this:</p> |
| |
| <ol> |
| <li> |
| The overridden <code>onMeasure()</code> method is called with width and |
| height measure specifications (<code>widthMeasureSpec</code> and |
| <code>heightMeasureSpec</code> parameters, both are integer codes |
| representing dimensions) which should be treated as requirements for |
| the restrictions on the width and height measurements you should produce. A |
| full reference to the kind of restrictions these specifications can require |
| can be found in the reference documentation under {@link |
| android.view.View#onMeasure View.onMeasure(int, int)} (this reference |
| documentation does a pretty good job of explaining the whole measurement |
| operation as well). |
| </li> |
| <li> |
| Your component's <code>onMeasure()</code> method should calculate a |
| measurement width and height which will be required to render the |
| component. It should try to stay within the specifications passed in, |
| although it can choose to exceed them (in this case, the parent can |
| choose what to do, including clipping, scrolling, throwing an exception, |
| or asking the <code>onMeasure()</code> to try again, perhaps with |
| different measurement specifications). |
| </li> |
| <li> |
| Once the width and height are calculated, the <code>setMeasuredDimension(int |
| width, int height)</code> method must be called with the calculated |
| measurements. Failure to do this will result in an exception being |
| thrown. |
| </li> |
| </ol> |
| |
| <p> |
| Here's a summary of some of the other standard methods that the framework calls on views: |
| </p> |
| <table border="2" width="85%" align="center" cellpadding="5"> |
| <thead> |
| <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr> |
| </thead> |
| |
| <tbody> |
| <tr> |
| <td rowspan="2">Creation</td> |
| <td>Constructors</td> |
| <td>There is a form of the constructor that are called when the view |
| is created from code and a form that is called when the view is |
| inflated from a layout file. The second form should parse and apply |
| any attributes defined in the layout file. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onFinishInflate()}</code></td> |
| <td>Called after a view and all of its children has been inflated |
| from XML.</td> |
| </tr> |
| |
| <tr> |
| <td rowspan="3">Layout</td> |
| <td><code>{@link android.view.View#onMeasure}</code></td> |
| <td>Called to determine the size requirements for this view and all |
| of its children. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onLayout}</code></td> |
| <td>Called when this view should assign a size and position to all |
| of its children. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onSizeChanged}</code></td> |
| <td>Called when the size of this view has changed. |
| </td> |
| </tr> |
| |
| <tr> |
| <td>Drawing</td> |
| <td><code>{@link android.view.View#onDraw}</code></td> |
| <td>Called when the view should render its content. |
| </td> |
| </tr> |
| |
| <tr> |
| <td rowspan="4">Event processing</td> |
| <td><code>{@link android.view.View#onKeyDown}</code></td> |
| <td>Called when a new key event occurs. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onKeyUp}</code></td> |
| <td>Called when a key up event occurs. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onTrackballEvent}</code></td> |
| <td>Called when a trackball motion event occurs. |
| </td> |
| </tr> |
| <tr> |
| <td><code>{@link android.view.View#onTouchEvent}</code></td> |
| <td>Called when a touch screen motion event occurs. |
| </td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2">Focus</td> |
| <td><code>{@link android.view.View#onFocusChanged}</code></td> |
| <td>Called when the view gains or loses focus. |
| </td> |
| </tr> |
| |
| <tr> |
| <td><code>{@link android.view.View#onWindowFocusChanged}</code></td> |
| <td>Called when the window containing the view gains or loses focus. |
| </td> |
| </tr> |
| |
| <tr> |
| <td rowspan="3">Attaching</td> |
| <td><code>{@link android.view.View#onAttachedToWindow()}</code></td> |
| <td>Called when the view is attached to a window. |
| </td> |
| </tr> |
| |
| <tr> |
| <td><code>{@link android.view.View#onDetachedFromWindow}</code></td> |
| <td>Called when the view is detached from its window. |
| </td> |
| </tr> |
| |
| <tr> |
| <td><code>{@link android.view.View#onWindowVisibilityChanged}</code></td> |
| <td>Called when the visibility of the window containing the view |
| has changed. |
| </td> |
| </tr> |
| </tbody> |
| |
| </table> |
| |
| |
| |
| <h3 id="customexample">A Custom View Example</h3> |
| <p>The CustomView sample in the |
| <a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a> provides an example |
| of a customized View. The custom View is defined in the |
| <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a> |
| class.</p> |
| <p>The LabelView sample demonstrates a number of different aspects of custom components:</p> |
| <ul> |
| <li>Extending the View class for a completely custom component.</li> |
| <li>Parameterized constructor that takes the view inflation parameters |
| (parameters defined in the XML). Some of these are passed through to the |
| View superclass, but more importantly, there are some custom attributes defined |
| and used for LabelView.</li> |
| <li>Standard public methods of the type you would expect to see for a label |
| component, for example <code>setText()</code>, <code>setTextSize()</code>, |
| <code>setTextColor()</code> and so on.</li> |
| <li>An overridden <code>onMeasure</code> method to determine and set the |
| rendering size of the component. (Note that in LabelView, the real work is done |
| by a private <code>measureWidth()</code> method.)</li> |
| <li>An overridden <code>onDraw()</code> method to draw the label onto the |
| provided canvas.</li> |
| </ul> |
| <p>You can see some sample usages of the LabelView custom View in |
| <a href="{@docRoot}resources/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a> |
| from the samples. In particular, you can see a mix of both <code>android:</code> |
| namespace parameters and custom <code>app:</code> namespace parameters. These |
| <code>app:</code> parameters are the custom ones that the LabelView recognizes |
| and works with, and are defined in a styleable inner class inside of the |
| samples R resources definition class.</p> |
| |
| |
| <h2 id="compound">Compound Controls |
| </h2> |
| <p>If you don't want to create a completely customized component, but instead |
| are looking to put together a reusable component that consists of a group of |
| existing controls, then creating a Compound Component (or Compound Control) might |
| fit the bill. In a nutshell, this brings together a number of more atomic |
| controls (or views) into a logical group of items that can be treated as a |
| single thing. For example, a Combo Box can be thought of as a |
| combination of a single line EditText field and an adjacent button with an attached |
| PopupList. If you press the button and select |
| something from the list, it populates the EditText field, but the user can |
| also type something directly into the EditText if they prefer.</p> |
| <p>In Android, there are actually two other Views readily available to do |
| this: {@link android.widget.Spinner Spinner} and |
| {@link android.widget.AutoCompleteTextView AutoCompleteTextView}, but |
| regardless, the concept of a Combo Box makes an easy-to-understand |
| example.</p> |
| <p>To create a compound component:</p> |
| <ol> |
| <li> |
| The usual starting point is a Layout of some kind, so create a class |
| that extends a Layout. Perhaps in the case of a Combo box we might use |
| a LinearLayout with horizontal orientation. Remember that other layouts |
| can be nested inside, so the compound component can be arbitrarily |
| complex and structured. Note that just like with an Activity, you can |
| use either the declarative (XML-based) approach to creating the |
| contained components, or you can nest them programmatically from your |
| code. |
| </li> |
| <li> |
| In the constructor for the new class, take whatever parameters the |
| superclass expects, and pass them through to the superclass constructor |
| first. Then you can set up the other views to use within your new |
| component; this is where you would create the EditText field and the |
| PopupList. Note that you also might introduce your own attributes and |
| parameters into the XML that can be pulled out and used by your |
| constructor. |
| </li> |
| <li> |
| You can also create listeners for events that your contained views might |
| generate, for example, a listener method for the List Item Click Listener |
| to update the contents of the EditText if a list selection is made. |
| </li> |
| <li> |
| You might also create your own properties with accessors and modifiers, |
| for example, allow the EditText value to be set initially in the |
| component and query for its contents when needed. |
| </li> |
| <li> |
| In the case of extending a Layout, you don't need to override the |
| <code>onDraw()</code> and <code>onMeasure()</code> methods since the |
| layout will have default behavior that will likely work just fine. However, |
| you can still override them if you need to. |
| </li> |
| <li> |
| You might override other <code>on...</code> methods, like |
| <code>onKeyDown()</code>, to perhaps choose certain default values from |
| the popup list of a combo box when a certain key is pressed. |
| </li> |
| </ol> |
| <p> |
| To summarize, the use of a Layout as the basis for a Custom Control has a |
| number of advantages, including:</p> |
| |
| <ul> |
| <li> |
| You can specify the layout using the declarative XML files just like |
| with an activity screen, or you can create views programmatically and |
| nest them into the layout from your code. |
| </li> |
| <li> |
| The <code>onDraw()</code> and <code>onMeasure()</code> methods (plus |
| most of the other <code>on...</code> methods) will likely have suitable behavior so |
| you don't have to override them. |
| </li> |
| <li> |
| In the end, you can very quickly construct arbitrarily complex compound |
| views and re-use them as if they were a single component. |
| </li> |
| </ul> |
| <h4>Examples of Compound Controls</h4> |
| <p>In the API Demos project |
| that comes with the SDK, there are two List |
| examples — Example 4 and Example 6 under Views/Lists demonstrate a |
| SpeechView which extends LinearLayout to make a component for displaying |
| Speech quotes. The corresponding classes in the sample code are |
| <code>List4.java</code> and <code>List6.java</code>.</p> |
| |
| |
| |
| <h2 id="modifying">Modifying an Existing View Type</h2> |
| <p>There is an even easier option for creating a custom View which is |
| useful in certain circumstances. If there is a component that is already very |
| similar to what you want, you can simply extend that component and just |
| override the behavior that you want to change. You can do all of the things |
| you would do with a fully customized component, but by starting with a more |
| specialized class in the View hierarchy, you can also get a lot of behavior for |
| free that probably does exactly what you want.</p> |
| <p>For example, the SDK includes a <a |
| href="{@docRoot}resources/samples/NotePad/index.html">NotePad application</a> in the |
| samples. This demonstrates many aspects of using the Android platform, among |
| them is extending an EditText View to make a lined notepad. This is not a |
| perfect example, and the APIs for doing this might change from this early |
| preview, but it does demonstrate the principles.</p> |
| <p>If you haven't done so already, import the |
| NotePad sample into Eclipse (or |
| just look at the source using the link provided). In particular look at the definition of |
| <code>MyEditText</code> in the <a |
| href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a> |
| file.</p> |
| <p>Some points to note here</p> |
| <ol> |
| <li> |
| <strong>The Definition</strong> |
| <p>The class is defined with the following line:<br/> |
| <code>public static class MyEditText extends EditText</code></p> |
| |
| <ul> |
| <li> |
| It is defined as an inner class within the <code>NoteEditor</code> |
| activity, but it is public so that it could be accessed as |
| <code>NoteEditor.MyEditText</code> from outside of the <code>NoteEditor</code> |
| class if desired. |
| </li> |
| <li> |
| It is <code>static</code>, meaning it does not generate the so-called |
| "synthetic methods" that allow it to access data from the parent |
| class, which in turn means that it really behaves as a separate |
| class rather than something strongly related to <code>NoteEditor</code>. |
| This is a cleaner way to create inner classes if they do not need |
| access to state from the outer class, keeps the generated class |
| small, and allows it to be used easily from other classes. |
| </li> |
| <li> |
| It extends <code>EditText</code>, which is the View we have chosen to |
| customize in this case. When we are finished, the new class will be |
| able to substitute for a normal <code>EditText</code> view. |
| </li> |
| </ul> |
| </li> |
| <li> |
| <strong>Class Initialization</strong> |
| <p>As always, the super is called first. Furthermore, |
| this is not a default constructor, but a parameterized one. The |
| EditText is created with these parameters when it is inflated from an |
| XML layout file, thus, our constructor needs to both take them and pass them |
| to the superclass constructor as well.</p> |
| </li> |
| <li> |
| <strong>Overridden Methods</strong> |
| <p>In this example, there is only one method to be overridden: |
| <code>onDraw()</code> — but there could easily be others needed when you |
| create your own custom components.</p> |
| <p>For the NotePad sample, overriding the <code>onDraw()</code> method allows |
| us to paint the blue lines on the <code>EditText</code> view canvas (the |
| canvas is passed into the overridden <code>onDraw()</code> method). The |
| super.onDraw() method is called before the method ends. The |
| superclass method should be invoked, but in this case, we do it at the |
| end after we have painted the lines we want to include.</p> |
| <li> |
| <strong>Use the Custom Component</strong> |
| <p>We now have our custom component, but how can we use it? In the |
| NotePad example, the custom component is used directly from the |
| declarative layout, so take a look at <code>note_editor.xml</code> in the |
| <code>res/layout</code> folder.</p> |
| <pre> |
| <view |
| class="com.android.notepad.NoteEditor$MyEditText" |
| id="@+id/note" |
| android:layout_width="fill_parent" |
| android:layout_height="fill_parent" |
| android:background="@android:drawable/empty" |
| android:padding="10dip" |
| android:scrollbars="vertical" |
| android:fadingEdge="vertical" /> |
| </pre> |
| |
| <ul> |
| <li> |
| The custom component is created as a generic view in the XML, and |
| the class is specified using the full package. Note also that the |
| inner class we defined is referenced using the |
| <code>NoteEditor$MyEditText</code> notation which is a standard way to |
| refer to inner classes in the Java programming language. |
| <p>If your custom View component is not defined as an inner class, then you can, |
| alternatively, declare the View component |
| with the XML element name, and exclude the <code>class</code> attribute. For example:</p> |
| <pre> |
| <com.android.notepad.MyEditText |
| id="@+id/note" |
| ... /> |
| </pre> |
| <p>Notice that the <code>MyEditText</code> class is now a separate class file. When the class |
| is nested in the <code>NoteEditor</code> class, this technique will not work.</p> |
| </li> |
| <li> |
| The other attributes and parameters in the definition are the ones |
| passed into the custom component constructor, and then passed |
| through to the EditText constructor, so they are the same |
| parameters that you would use for an EditText view. Note that it is |
| possible to add your own parameters as well, and we will touch on |
| this again below. |
| </li> |
| </ul> |
| </li> |
| </ol> |
| <p>And that's all there is to it. Admittedly this is a simple case, but |
| that's the point — creating custom components is only as complicated as you |
| need it to be.</p> |
| <p>A more sophisticated component may override even more <code>on...</code> methods and |
| introduce some of its own helper methods, substantially customizing its properties and |
| behavior. The only limit is your imagination and what you need the component to |
| do.</p> |
| |