Our project uses the custom class TextDrawable. This class extends Drawable and in its method, draw(Canvas)it simply draws text on canvas. The class is suitable for our specific needs, but I think the idea (mainly in the method draw()will help you:
public class TextDrawable extends Drawable {
protected final Paint textPaint;
protected ColorStateList color;
protected String text;
protected int iHeight;
protected int iWidth;
protected int measuredWidth, measuredHeight;
private float ascent;
protected boolean stateful;
private VerticalAlignment verticalAlignment;
.... some constructors...
public TextDrawable(Context ctx, String text, ColorStateList color, float textSize, VerticalAlignment verticalAlignment) {
textPaint = new Paint();
this.text = text;
initPaint();
this.textPaint.setTextSize(textSize);
measureSize();
setBounds(0, 0, iWidth, iHeight);
this.color = color;
textPaint.setColor(color.getDefaultColor());
this.verticalAlignment = verticalAlignment;
}
public final void setBoundsByMeasuredSize() {
setBounds(0, 0, measuredWidth, measuredHeight);
invalidateSelf();
}
@Override
public boolean isStateful() {
return stateful;
}
public void setStateful(boolean stateful) {
this.stateful = stateful;
}
private void initPaint() {
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
}
public VerticalAlignment getVerticalAlignment() {
return verticalAlignment;
}
public void setVerticalAlignment(VerticalAlignment verticalAlignment) {
if (this.verticalAlignment != verticalAlignment) {
this.verticalAlignment = verticalAlignment;
invalidateSelf();
}
}
public String getText() {
return text;
}
public void setText(String text) {
if (this.text == null || !this.text.equals(text)) {
this.text = text;
invalidateSelf();
}
}
public ColorStateList getColor() {
return color;
}
public void setColor(ColorStateList colorStateList) {
if (this.color == null || !this.color.equals(colorStateList)) {
this.color = colorStateList;
invalidateSelf();
}
}
public void setColor(int color) {
setColor(ColorStateList.valueOf(color));
}
public void setTextSize(float size) {
if (this.textPaint.getTextSize() != size) {
this.textPaint.setTextSize(size);
measureSize();
invalidateSelf();
}
}
public void setTextSize(int unit, float size, Context context) {
setTextSize(TypedValue.applyDimension(unit, size, context.getResources().getDisplayMetrics()));
}
protected void measureSize() {
ascent = -textPaint.ascent();
iWidth = (int) (0.5f + textPaint.measureText(text));
iHeight = (int) (0.5f + textPaint.descent() + ascent);
measuredWidth = iWidth;
measuredHeight = iHeight;
}
public float getTextSize() {
return textPaint.getTextSize();
}
@Override
protected boolean onStateChange(int[] state) {
int clr = color != null ? color.getColorForState(state, 0) : 0;
if (textPaint.getColor() != clr) {
textPaint.setColor(clr);
return true;
} else {
return false;
}
}
public Typeface getTypeface() {
return textPaint.getTypeface();
}
public void setTypeface(Typeface typeface) {
if (!textPaint.getTypeface().equals(typeface)) {
textPaint.setTypeface(typeface);
invalidateSelf();
}
}
protected void drawBefore(Canvas canvas, Rect bounds) {
}
protected void drawAfter(Canvas canvas, Rect bounds) {
}
@Override
public void draw(Canvas canvas) {
if (text == null || text.isEmpty()) {
return;
}
final Rect bounds = getBounds();
int stack = canvas.save();
canvas.translate(bounds.left, bounds.top);
drawBefore(canvas, bounds);
if (text != null && !text.isEmpty()) {
final float x = bounds.width() >= iWidth ? bounds.centerX() : iWidth * 0.5f;
float y = 0;
switch (verticalAlignment) {
case BASELINE:
y = (bounds.height() - iHeight) * 0.5f + ascent;
break;
case TOP:
y = bounds.height();
break;
case BOTTOM:
y = bounds.height();
break;
}
canvas.drawText(text, x, y, textPaint);
}
drawAfter(canvas, bounds);
canvas.restoreToCount(stack);
}
@Override
public void setAlpha(int alpha) {
if (textPaint.getAlpha() != alpha) {
textPaint.setAlpha(alpha);
invalidateSelf();
}
}
@Override
public void setColorFilter(ColorFilter cf) {
if (textPaint.getColorFilter() == null || !textPaint.getColorFilter().equals(cf)) {
textPaint.setColorFilter(cf);
invalidateSelf();
}
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public enum VerticalAlignment {
TOP, BOTTOM, BASELINE
}
and how to use it:
fab.setImageDrawable(new TextDrawable(fab.getContext(), "FAB", ColorStateList.valueOf(Color.BLACK), 32.f, VerticalAlignment.BASELINE));
(fab - FloatingActionButton)