I'm trying to create a drawable on the fly to use as a background for a custom linearlayout. It needs to have hash marks and such (no big deal), but also have numbers labeling what the hash marks are (like a ruler). I know I can just create text elements and put them inside the linearlayout and just have the hash marks in the drawable, but I'm hoping to have them inside the drawable as well, so I don't have to do measurement calculations twice.
5 Answers
Here is a brief example of a TextDrawable
which works like a normal drawable but lets you specify text as the only constructor variable:
public class TextDrawable extends Drawable {
private final String text;
private final Paint paint;
public TextDrawable(String text) {
this.text = text;
this.paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(22f);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
paint.setShadowLayer(6f, 0, 0, Color.BLACK);
paint.setStyle(Paint.Style.FILL);
paint.setTextAlign(Paint.Align.LEFT);
}
@Override
public void draw(Canvas canvas) {
canvas.drawText(text, 0, 0, paint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}

- 13,335
- 8
- 53
- 53
-
it works fine the only problem is text displayed wide.i am drawing text at (x,y) according to progress. where x = progress*seekBar.getWidth()/seekBar.getMax() and y = seekBar.getHeight()/2. can you please tell me where is my mistake to calculate the x,y co-ordinates. – Hiren Dabhi Mar 12 '12 at 12:11
-
ok it works perfect. that was my mistake. i have putted padding(left and right) of seek bar.Thanks plowman. – Hiren Dabhi Mar 12 '12 at 14:22
-
Any Idea for [How to display Text in Android Canvas ShapeDrawable with RectShape?](http://stackoverflow.com/questions/25401981/how-to-display-text-in-android-canvas-shapedrawable-with-rectshape) – LOG_TAG Aug 21 '14 at 05:21
-
Am trying to use type face in the paint object, but it didn't work. Any ideas? paint.setTypeface(Typeface.createFromAsset(context.getAssets(), "custom_font.ttf")); – Sathesh Jan 24 '15 at 07:45
-
@Sathesh make sure you have a font called "custom_font.ttf" in the assets folder of your project. – plowman Jan 26 '15 at 21:14
-
@Sathesh haha, okay... without seeing your code I can't guess what's wrong. If you post a gist I can take a quick look. – plowman Jan 27 '15 at 20:03
-
How do I put the text nicely in the center of the drawable? I remember it is a very known issue. – android developer Sep 07 '15 at 11:31
-
@android-developer I believe you use `paint.setTextAlign(Paint.Align.CENTER);` – plowman Sep 08 '15 at 00:11
-
@plowman As I said, I remember this is problematic, as the text font doesn't center correctly. Maybe I'm wrong and it's a similar issue. Anyway thank you. – android developer Sep 08 '15 at 06:57
-
4Sorry for foolishness but how to use this class to draw text in a drawable – Leap Hawk Oct 18 '16 at 11:28
-
1
-
-
I tried this code but somehow the only method that is being called is getOpacity(). So no image is shown in the imageView. Any clue? – Leandro Ocampo Jun 25 '19 at 20:31
-
I realised there was a stack trace saying that the drawable needs to have width and height > 0. So I set those in intrinsicWidth and intrinsicHeight to make it work. – Leandro Ocampo Jun 25 '19 at 22:05
I've read the book "Professional Android 2 Application Development" (by Reto Meier). Amongst others, it contains an example project where you create a simple compass application where you "draw" text, markers etc.
The brief explanation is that you create a class that extends the android.view.View
class and overrides the onDraw(Canvas)
method.
All the source code form the book is available for download here: http://www.wrox.com/WileyCDA/WroxTitle/Professional-Android-2-Application-Development.productCd-0470565527,descCd-DOWNLOAD.html. If you download the code and look inside the project named "Chapter 4 Compass", I believe you would find what you're looking for :)

- 20,008
- 17
- 77
- 108
Looking at Plowman's answer and trying to adjust it to my needs I stumpled upon a Class that is used for Camera in this link
Here is the code from the TextDrawable Class. Looks pretty simillar with Plowmans but for me works better:
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
public class TextDrawable extends Drawable {
private static final int DEFAULT_COLOR = Color.WHITE;
private static final int DEFAULT_TEXTSIZE = 15;
private Paint mPaint;
private CharSequence mText;
private int mIntrinsicWidth;
private int mIntrinsicHeight;
public TextDrawable(Resources res, CharSequence text) {
mText = text;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setTextAlign(Align.CENTER);
float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
DEFAULT_TEXTSIZE, res.getDisplayMetrics());
mPaint.setTextSize(textSize);
mIntrinsicWidth = (int) (mPaint.measureText(mText, 0, mText.length()) + .5);
mIntrinsicHeight = mPaint.getFontMetricsInt(null);
}
@Override
public void draw(Canvas canvas) {
Rect bounds = getBounds();
canvas.drawText(mText, 0, mText.length(),
bounds.centerX(), bounds.centerY(), mPaint);
}
@Override
public int getOpacity() {
return mPaint.getAlpha();
}
@Override
public int getIntrinsicWidth() {
return mIntrinsicWidth;
}
@Override
public int getIntrinsicHeight() {
return mIntrinsicHeight;
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter filter) {
mPaint.setColorFilter(filter);
}
}

- 16,223
- 11
- 86
- 117
-
Seems a bit cut to me, and not centered correctly: https://i.stack.imgur.com/2xRyf.png . Can you please check the code again? – android developer Dec 13 '17 at 08:09
-
-
-
@androiddeveloper yeah sorry. I stopped with Android for 1+ year now. I am really sorry. – Jimmy Kane Dec 13 '17 at 11:48
-
That's ok. I would appreciate it if you could try to check it though. – android developer Dec 13 '17 at 15:15
-
-
-
Also works better for me. But there is a a part cut off at the very top – mathematics-and-caffeine Jun 02 '22 at 16:30
To answer the comments above regarding how to center the text:
mPaint.textAlign = Align.CENTER
...
// Centering for mixed case letters
canvas.drawText(mText, 0, mText.length,
bounds.centerX().toFloat(), bounds.centerY().toFloat() - ((mPaint.descent() + mPaint.ascent()) / 2), mPaint)
// Centering for all uppercase letters
canvas.drawText(mText, 0, mText.length,
bounds.centerX().toFloat(), bounds.centerY().toFloat() - mPaint.ascent() / 2, mPaint)

- 63
- 1
- 4
-
Perfect. This worked for me. Test for all caps in the constructor, not draw(). – Clark Battle Dec 04 '18 at 19:39
-
This allows you to put any View in a Drawable, including a TextView. You can even use styles in your XML layout.
public class ViewDrawable extends Drawable {
final View mView;
public ViewDrawable(final Context context, final @LayoutRes int layoutId) {
this(LayoutInflater.from(context).inflate(layoutId, null));
}
public ViewDrawable(final @NonNull View view) {
mView = view;
}
public View getView() {
return mView;
}
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
final int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(right - left, View.MeasureSpec.EXACTLY);
final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(bottom - top, View.MeasureSpec.EXACTLY);
mView.measure(widthMeasureSpec, heightMeasureSpec);
mView.layout(left, top, right, bottom);
}
@Override
public void draw(@NonNull Canvas canvas) {
mView.draw(canvas);
}
@Override
public void setAlpha(int alpha) {
mView.setAlpha(alpha/255f);
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
}

- 2,064
- 1
- 16
- 12