| page.title=Custom Components | |
| page.tags=view,widget | |
| @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 Android Studio (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> | |