|
Creating a custom view is as simple as inheriting from the
View class and overriding the methods that need to be overridden. In this example,
a custom button is implemented in this way. The button shall feature a labelled
image (i.e. an image with text underneath).
1 public
class CustomImageButton
extends View {
2
private final
static int
WIDTH_PADDING = 8;
3
private final
static int
HEIGHT_PADDING = 10;
4
private final
String label;
5
private final
int imageResId;
6
private final
Bitmap image;
7
private final
InternalListener listenerAdapter = new InternalListener();
8
The constructor can take in the parameters to set the button image and label.
9
/**
10
* Constructor.
11
*
12
* @param
context
13
* Activity context
in which the button view is being placed for.
14
*
15
* @param
resImage
16
* Image to put on
the button. This image should have been placed
17
* in the drawable
resources directory.
18
*
19
* @param
label
20
* The text label
to display for the custom button.
21
*/
22
public CustomImageButton(Context context,
int resImage, String label)
23 {
24
super(context);
25
this.label = label;
26
this.imageResId = resImage;
27
this.image = BitmapFactory.decodeResource(context.getResources(),
28
imageResId);
29
30
setFocusable(true);
31
setBackgroundColor(Color.WHITE);
32
33
setOnClickListener(listenerAdapter);
34
setClickable(true);
35 }
36
With the constructor defined, there are a number of methods in the View
class that needs to be overridden to this view behave like a button. Firstly, the
onFocusChanged gets triggered when the focus moves onto or off the view.
In the case of our custom button, we want the button to be “highlighted” when ever
the focus is on the button.
49
{
50
this.setBackgroundColor(Color.WHITE);
51
}
52 }
53
The method responsible for rendering the contents of the view to the screen is
the draw method. In this case, it handles placing the image and text label
on to the custom view.
54
/**
55 * Method called on
to render the view.
56 */
57
protected void
onDraw(Canvas canvas)
58 {
59
Paint textPaint = new Paint();
60
textPaint.setColor(Color.BLACK);
61
canvas.drawBitmap(image, WIDTH_PADDING / 2, HEIGHT_PADDING
/ 2, null);
62
canvas.drawText(label, WIDTH_PADDING / 2, (HEIGHT_PADDING
/ 2) +
63
image.getHeight() + 8, textPaint);
64 }
65
For the elements to be displayed correctly on the screen, Android needs to know
the how big the custom view is. This is done through overriding the onMeasure
method. The measurement specification parameters represent dimension restrictions
that are imposed by the parent view.
66
@Override
67
protected void
onMeasure(int widthMeasureSpec,
int heightMeasureSpec)
68
{
69
setMeasuredDimension(measureWidth(widthMeasureSpec),
70
measureHeight(heightMeasureSpec));
71
}
72
The call to setMeasuredDimension in the onMeasure method is important.
The
documentation states that the call is necessary to avoid a IllegalStateException.
73
private int
measureWidth(int measureSpec)
74 {
75
int preferred = image.getWidth() *
2;
76
return getMeasurement(measureSpec, preferred);
77 }
78
79
private int
measureHeight(int measureSpec)
80 {
81
int preferred = image.getHeight() *
2;
82
return getMeasurement(measureSpec, preferred);
83 }
84
To calculate the width and height measurements, I’ve chosen to keep the logic
simple by using a simple formula to calculate the dimensions. This simple formula
computes the dimensions based on the dimensions of the image. The
measureSpec parameter specifies what restrictions are imposed by the parent
layout.
85
private int
getMeasurement(int measureSpec,
int preferred)
86 {
87
int specSize = MeasureSpec.getSize(measureSpec);
88
int measurement = 0;
89
90
switch(MeasureSpec.getMode(measureSpec))
91
{
92
case MeasureSpec.EXACTLY:
93
// This means the width of this view has been given.
94
measurement = specSize;
95
break;
96
case MeasureSpec.AT_MOST:
97
// Take the minimum of the preferred size and what
98
// we were told to be.
99
measurement = Math.min(preferred, specSize);
100
break;
101
default:
102
measurement = preferred;
103
break;
104
}
105
106
return measurement;
107 }
108
To make the customised button useful, it needs to trigger some kind of action
when it is clicked (i.e. a listener). The view class already defines methods
for setting the listener, but a more specialised listener could be better suited
to the custom button. For example, the specialised listener could pass back information
on the instance of the custom button.
109 /**
110 * Sets the listener object
that is triggered when the view is clicked.
111 *
112 *
@param newListener
113 *
The instance of the listener to trigger.
114 */
115
public void setOnClickListener(ClickListener
newListener)
116 {
117
listenerAdapter.setListener(newListener);
118 }
119
If the custom listener passes information about this instance of the custom button,
it may as well have accessors so listener implementation can get useful information
about this custom button.
120 /**
121 * Returns the label of the
button.
122 */
123
public String getLabel()
124 {
125
return label;
126 }
127
128 /**
129 * Returns the resource id
of the image.
130 */
131
public int getImageResId()
132 {
133
return imageResId;
134 }
135
Finally, for our custom button class that is using a custom listener, the custom
listener class needs to be defined.
136 /**
137 * Internal click listener
class. Translates a view’s click listener to
138 * one that is more appropriate
for the custom image button class.
139 *
140 *
@author Kah
141 */
142
private class InternalListener
implements View.OnClickListener
143 {
144
private ClickListener listener =
null;
145
146
/**
147
* Changes the listener to the given listener.
148
*
149
* @param newListener
150
* The listener to change to.
151
*/
152
public void
setListener(ClickListener newListener)
153
{
154
listener = newListener;
155
}
156
157
@Override
158
public void
onClick(View v)
159
{
160
if (listener != null)
161
{
162
listener.onClick(CustomImageButton.this);
163
}
164
}
165 }
166 }
167
Source:
kahdev blog
{mos_fb_discuss:18}
|
How to display a JPG...
Is that posible to zoom in and drag p...
Making a custom Andr...
Cool - I will use it carefully i promise
How to display a JPG...
problem in image loading - i have exe...
Introducing Calculon...
Thank You for your contribution - Hi,...
Debug a Native Appli...
Never mind, I somehow overlooked the ...