Fully Customized Components

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.

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).

To create a fully customized component:

Extend onDraw() and onMeasure()

The onDraw( ) method delivers you a 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.

Note: This does not apply to 3D graphics. If you want to use 3D graphics, you must extend SurfaceView instead of View, and draw from a seperate thread. See the GLSurfaceViewActivity sample for details.

onMeasure() is a little more involved. onMeasure() is a critical piece of the rendering contract between your component and its container. onMeasure() 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 onMeasure() method) and by the requirement to call the setMeasuredDimension() method with the measured width and height once they have been calculated. If you fail to call this method from an overridden onMeasure() method, the result will be an exception at measurement time.

At a high level, implementing onMeasure() looks something like this:

1. The overridden onMeasure() method is called with width and height measure specifications (widthMeasureSpec and heightMeasureSpec 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 View.onMeasure(int, int) (this reference documentation does a pretty good job of explaining the whole measurement operation as well).

2. Your component's onMeasure() 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 onMeasure() to try again, perhaps with different measurement specifications).

3. Once the width and height are calculated, the setMeasuredDimension(int width, int height) method must be called with the calculated measurements. Failure to do this will result in an exception being thrown.

1. The most generic view you can extend is, unsurprisingly, View, so you will usually start by extending this to create your new super component.

2. 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.)

3. 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.

4. You will almost certainly want to override onMeasure() and are also likely to need to override onDraw() if you want the component to show something. While both have default behavior, the default onDraw( ) will do nothing, and the default onMeasure() will always set a size of 100x100 — which is probably not what you want.

5. Other on... methods may also be overridden as required.

Here's a summary of some of the other standard methods that the framework calls on views:

Category

Methods

Description

Creation

Constructors

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.

onFinishInflate()

Called after a view and all of its children has been inflated from XML.

Layout

onMeasure(int, int)

Called to determine the size requirements for this view and all of its children.

onLayout(boolean, int, int, int, int)

Called when this view should assign a size and position to all of its children.

onSizeChanged(int, int, int, int)

Called when the size of this view has changed.

Drawing

onDraw(Canvas)

Called when the view should render its content.

Event processing

onKeyDown(int, KeyEvent)

Called when a new key event occurs.

onKeyUp(int, KeyEvent)

Called when a key up event occurs.

onTrackballEvent(MotionEvent)

Called when a trackball motion event occurs.

onTouchEvent(MotionEvent)

Called when a touch screen motion event occurs.

Focus

onFocusChanged(boolean, int, Rect)

Called when the view gains or loses focus.

onWindowFocusChanged(boolean)

Called when the window containing the view gains or loses focus.

Attaching

onAttachedToWindow()

Called when the view is attached to a window.

onDetachedFromWindow()

Called when the view is detached from its window.

onWindowVisibilityChanged(int)

Called when the visibility of the window containing the view has changed.

0 0

Post a comment