/*
The MIT License (MIT)
Copyright (c) 2014 Amulya Khare
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package com.amulyakhare.textdrawable;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.graphics.drawable.shapes.RectShape;
import android.graphics.drawable.shapes.RoundRectShape;
import android.support.annotation.ColorInt;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
/**
* @author amulya
* @datetime 14 Oct 2014, 3:53 PM
* <p/>
* MIT LICENSE: https://github.com/amulyakhare/TextDrawable/blob/master/LICENSE
*/
public class TextDrawable extends ShapeDrawable {
private static final float SHADE_FACTOR = 0.9f;
private final Paint textPaint;
private final Paint borderPaint;
private final String text;
private final int color;
private final RectShape shape;
private final int height;
private final int width;
private final int fontSize;
private final float radius;
private final int borderThickness;
private TextDrawable(Builder builder) {
super(builder.shape);
// shape properties
shape = builder.shape;
height = builder.height;
width = builder.width;
radius = builder.radius;
// text and color
text = builder.toUpperCase ? builder.text.toUpperCase() : builder.text;
color = builder.color;
// text paint settings
fontSize = builder.fontSize;
textPaint = new Paint();
textPaint.setColor(builder.textColor);
textPaint.setAntiAlias(true);
textPaint.setFakeBoldText(builder.isBold);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTypeface(builder.font);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setStrokeWidth(builder.borderThickness);
// border paint settings
borderThickness = builder.borderThickness;
borderPaint = new Paint();
borderPaint.setColor(getDarkerShade(color));
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(borderThickness);
// drawable paint color
Paint paint = getPaint();
paint.setColor(color);
}
public static IShapeBuilder builder() {
return new Builder();
}
private int getDarkerShade(@ColorInt int color) {
return Color.rgb((int) (SHADE_FACTOR * Color.red(color)), (int) (SHADE_FACTOR * Color
.green(color)), (int) (SHADE_FACTOR * Color.blue(color)));
}
private void drawBorder(Canvas canvas) {
RectF rect = new RectF(getBounds());
rect.inset(borderThickness / 2, borderThickness / 2);
if (shape instanceof OvalShape) {
canvas.drawOval(rect, borderPaint);
} else if (shape instanceof RoundRectShape) {
canvas.drawRoundRect(rect, radius, radius, borderPaint);
} else {
canvas.drawRect(rect, borderPaint);
}
}
@Override
public int getIntrinsicWidth() {
return width;
}
@Override
public int getIntrinsicHeight() {
return height;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
Rect r = getBounds();
// draw border
if (borderThickness > 0) {
drawBorder(canvas);
}
int count = canvas.save();
canvas.translate(r.left, r.top);
// draw text
int width = this.width < 0 ? r.width() : this.width;
int height = this.height < 0 ? r.height() : this.height;
int fontSize = this.fontSize < 0 ? (Math.min(width, height) / 2) : this.fontSize;
textPaint.setTextSize(fontSize);
canvas.drawText(text, width / 2, height / 2 - ((textPaint.descent() + textPaint.ascent())
/ 2), textPaint);
canvas.restoreToCount(count);
}
@Override
public void setAlpha(@IntRange(from = 0, to = 255) int alpha) {
textPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
textPaint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
public interface IConfigBuilder {
IConfigBuilder width(int width);
IConfigBuilder height(int height);
IConfigBuilder textColor(int color);
IConfigBuilder withBorder(int thickness);
IConfigBuilder useFont(Typeface font);
IConfigBuilder fontSize(int size);
IConfigBuilder bold();
IConfigBuilder toUpperCase();
IShapeBuilder endConfig();
}
public interface IBuilder {
TextDrawable build(@NonNull String text, @ColorInt int color);
}
public interface IShapeBuilder {
IConfigBuilder beginConfig();
IBuilder rect();
IBuilder round();
IBuilder roundRect(int radius);
TextDrawable buildRect(@NonNull String text, @ColorInt int color);
TextDrawable buildRoundRect(@NonNull String text, @ColorInt int color, int radius);
TextDrawable buildRound(@NonNull String text, @ColorInt int color);
}
public static class Builder implements IConfigBuilder, IShapeBuilder, IBuilder {
public int textColor;
public float radius;
private String text;
private int color;
private int borderThickness;
private int width;
private int height;
private Typeface font;
private RectShape shape;
private int fontSize;
private boolean isBold;
private boolean toUpperCase;
private Builder() {
text = "";
color = Color.GRAY;
textColor = Color.WHITE;
borderThickness = 0;
width = -1;
height = -1;
shape = new RectShape();
font = Typeface.create("sans-serif-light", Typeface.NORMAL);
fontSize = -1;
isBold = false;
toUpperCase = false;
}
public IConfigBuilder width(int width) {
this.width = width;
return this;
}
public IConfigBuilder height(int height) {
this.height = height;
return this;
}
public IConfigBuilder textColor(int color) {
this.textColor = color;
return this;
}
public IConfigBuilder withBorder(int thickness) {
this.borderThickness = thickness;
return this;
}
public IConfigBuilder useFont(Typeface font) {
this.font = font;
return this;
}
public IConfigBuilder fontSize(int size) {
this.fontSize = size;
return this;
}
public IConfigBuilder bold() {
this.isBold = true;
return this;
}
public IConfigBuilder toUpperCase() {
this.toUpperCase = true;
return this;
}
@Override
public IShapeBuilder endConfig() {
return this;
}
@Override
public IConfigBuilder beginConfig() {
return this;
}
@Override
public IBuilder rect() {
this.shape = new RectShape();
return this;
}
@Override
public IBuilder round() {
this.shape = new OvalShape();
return this;
}
@Override
public IBuilder roundRect(int radius) {
this.radius = radius;
float[] radii = {radius, radius, radius, radius, radius, radius, radius, radius};
this.shape = new RoundRectShape(radii, null, null);
return this;
}
@Override
public TextDrawable buildRect(@NonNull String text, @ColorInt int color) {
rect();
return build(text, color);
}
@Override
public TextDrawable buildRoundRect(@NonNull String text, @ColorInt int color, int radius) {
roundRect(radius);
return build(text, color);
}
@Override
public TextDrawable buildRound(@NonNull String text, @ColorInt int color) {
round();
return build(text, color);
}
@Override
public TextDrawable build(@NonNull String text, @ColorInt int color) {
this.color = color;
this.text = text;
return new TextDrawable(this);
}
}
}