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