Reputation: 12627
I wrote a small class, which can be used to create custom drawables. For the most part everything works as expected, but when it comes to display the drawables nearly "pixel-perfect", I really have no idea how get a proper solution. A proper solution would be to get an 100% centred character/text on the underlying shape. Any advice is welcome. Thanks in advance.
Here is the class:
public class DrawableSquareLetter extends Drawable {
private final Paint paint;
private Paint textPaint;
private final Builder builder;
public DrawableSquareLetter(Builder builder) {
this.builder = builder;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
paint.setColor(builder.color);
if (builder.applySurfaceShadow) {
paint.setShadowLayer(
DeviceUtils.dp2px(4),
DeviceUtils.dp2px(2),
DeviceUtils.dp2px(2),
Color.parseColor(MaterialColor.GREY_900));
}
textPaint = new Paint();
textPaint.setColor(builder.textColor);
textPaint.setAntiAlias(true);
textPaint.setFakeBoldText(builder.isBold);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTypeface(builder.typeface);
textPaint.setTextAlign(Paint.Align.CENTER);
if (builder.applyTextShadow) {
textPaint.setShadowLayer(
DeviceUtils.dp2px(2),
DeviceUtils.dp2px(1),
DeviceUtils.dp2px(1),
Color.parseColor(MaterialColor.GREY_800));
}
}
@Override
public void draw(Canvas canvas) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
canvas.drawRoundRect(0, 0, builder.size, builder.size, builder.rounded, builder.rounded, paint);
} else canvas.drawRect(0, 0, builder.size, builder.size, paint);
if (builder.textSize == -1) {
textPaint.setTextSize(builder.size * .80f);
} else textPaint.setTextSize(builder.textSize);
float width = builder.size;
float height = builder.size;
String text = builder.isUpperCase ? builder.text.toUpperCase() : builder.text;
canvas.drawText(text, width / 2f, height / 2f - (((textPaint.descent() + textPaint.ascent())) / 2f), textPaint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public static class Builder {
private final float size;
private final int color;
private String tag = "";
private float rounded;
private final String text;
private int textColor = Color.BLACK;
private float textSize = -1;
private Typeface typeface = Typeface.DEFAULT;
private boolean isUpperCase = true;
private boolean isBold = true;
private boolean applyTextShadow = true;
private boolean applySurfaceShadow = true;
public Builder(int sizeDp, int color, String text) {
this.text = text;
this.size = DeviceUtils.dp2px(sizeDp);
this.color = color;
}
public Builder(int sizeDp, String color, String text) {
this.text = text;
this.size = DeviceUtils.dp2px(sizeDp);
this.color = Color.parseColor(color);
}
public Builder textSize(float textSize) {
this.textSize = DeviceUtils.sp2px(textSize);
return this;
}
public Builder rounded(int radiusDp) {
this.rounded = DeviceUtils.dp2px(radiusDp);
return this;
}
public Builder textColor(int textColor) {
this.textColor = textColor;
return this;
}
public Builder textColor(String textColor) {
this.textColor = Color.parseColor(textColor);
return this;
}
public Builder typeface(Typeface typeface) {
this.typeface = typeface;
return this;
}
public Builder disableUpperCase() {
this.isUpperCase = false;
return this;
}
public Builder disableBold() {
this.isBold = false;
return this;
}
public Builder disableShadowOnSurface() {
this.applySurfaceShadow = false;
return this;
}
public Builder disableShadowOnText() {
this.applyTextShadow = false;
return this;
}
public Builder setTag(String tag) {
this.tag = tag;
return this;
}
public DrawableSquareLetter build() {
return new DrawableSquareLetter(this);
}
public void show(ImageView imageView) {
imageView.setImageDrawable(this.build());
}
}
public String getTag() { return builder.tag; }
}
Upvotes: 0
Views: 141
Reputation: 17841
If you want to center the text in the underlying shape, you need to draw the text in the right place and for that you need to use Paint.getTextBounds (String text, int start, int end, Rect bounds)
public void getTextBounds (String text, int start, int end, Rect bounds)
Return in bounds (allocated by the caller) the smallest rectangle that encloses all of the characters, with an implied origin at (0,0).
Once you execute this method, you will have information in the bounds
. All you need to do is write a logic in the draw
method of your Drawable
, where you calculate the x/y coordinates to perform drawText()
(based on this bounds
rect).
Upvotes: 1