Last active
November 22, 2018 14:00
-
-
Save ok3141/ac4e44974794241e4888e3b565791ed5 to your computer and use it in GitHub Desktop.
TextDrawable which can be used for drawing iconiс fonts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import android.content.res.ColorStateList; | |
| 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.Typeface; | |
| import android.graphics.drawable.Drawable; | |
| import android.os.Build; | |
| import android.support.annotation.NonNull; | |
| import android.text.TextPaint; | |
| import android.view.View; | |
| public class TextDrawable extends Drawable { | |
| @NonNull | |
| private String text; | |
| @NonNull | |
| private ColorStateList textColor; | |
| private float textSize; | |
| private boolean autoMirrored; | |
| @NonNull | |
| private final TextPaint paint; | |
| @NonNull | |
| private final Rect rect; | |
| private boolean boundsChanged; | |
| public TextDrawable() { | |
| text = ""; | |
| textColor = ColorStateList.valueOf(Color.BLACK); | |
| textSize = 16; | |
| paint = new TextPaint(); | |
| rect = new Rect(); | |
| paint.setAntiAlias(true); | |
| paint.setTextAlign(Paint.Align.LEFT); | |
| } | |
| private void updatePaint() { | |
| updatePaint(false, false); | |
| } | |
| private void updatePaint(boolean updateBounds, @SuppressWarnings("SameParameterValue") boolean forcedInvalidate) { | |
| boolean colorChanged = updatePaintColor(getState()); | |
| boolean textSizeChanged = false; | |
| float oldTextSize = paint.getTextSize(); | |
| float newTextSize = textSize; | |
| if (Float.compare(oldTextSize, newTextSize) != 0) { | |
| paint.setTextSize(newTextSize); | |
| textSizeChanged = true; | |
| } | |
| if (textSizeChanged || updateBounds) { | |
| boundsChanged = false; | |
| paint.getTextBounds(text, 0, text.length(), rect); | |
| fitRect(rect, (int) textSize); | |
| setBounds(rect); | |
| } | |
| if (colorChanged || forcedInvalidate || boundsChanged) { | |
| invalidateSelf(); | |
| } | |
| } | |
| private static void fitRect(Rect rect, int size) { | |
| int w = rect.width(); | |
| if (size > w) { | |
| int d1 = (size - w) / 2; | |
| int d2 = size - w - d1; | |
| rect.left -= d1; | |
| rect.right += d2; | |
| } | |
| int h = rect.height(); | |
| if (size > h) { | |
| int d1 = (size - h) / 2; | |
| int d2 = size - h - d1; | |
| rect.top -= d1; | |
| rect.bottom += d2; | |
| } | |
| } | |
| private boolean updatePaintColor(int[] state) { | |
| int oldColor = paint.getColor(); | |
| int newColor = textColor.getColorForState(state, textColor.getDefaultColor()); | |
| if (oldColor != newColor) { | |
| paint.setColor(newColor); | |
| return true; | |
| } | |
| return false; | |
| } | |
| @Override | |
| public boolean isStateful() { | |
| return textColor.isStateful(); | |
| } | |
| @Override | |
| protected boolean onStateChange(int[] state) { | |
| return updatePaintColor(state); | |
| } | |
| public void setTypeface(@NonNull Typeface typeface) { | |
| paint.setTypeface(typeface); | |
| updatePaint(true, false); | |
| } | |
| @NonNull | |
| public String getText() { | |
| return text; | |
| } | |
| public void setText(String text) { | |
| this.text = text != null ? text : ""; | |
| updatePaint(true, false); | |
| } | |
| public float getTextSize() { | |
| return textSize; | |
| } | |
| public void setTextSize(float textSize) { | |
| this.textSize = textSize; | |
| updatePaint(); | |
| } | |
| public int getTextColor() { | |
| return textColor.getColorForState(getState(), textColor.getDefaultColor()); | |
| } | |
| public void setTextColor(int color) { | |
| textColor = ColorStateList.valueOf(color); | |
| updatePaint(); | |
| } | |
| @NonNull | |
| public ColorStateList getTextColorStateList() { | |
| return textColor; | |
| } | |
| public void setTextColorStateList(@NonNull ColorStateList color) { | |
| textColor = color; | |
| updatePaint(); | |
| } | |
| public boolean isAutoMirrored() { | |
| return autoMirrored; | |
| } | |
| public void setAutoMirrored(boolean autoMirrored) { | |
| this.autoMirrored = autoMirrored; | |
| } | |
| @Override | |
| public void setAlpha(int alpha) { | |
| paint.setAlpha(alpha); | |
| invalidateSelf(); | |
| } | |
| @Override | |
| public void setColorFilter(ColorFilter cf) { | |
| paint.setColorFilter(cf); | |
| invalidateSelf(); | |
| } | |
| @Override | |
| public int getOpacity() { | |
| return PixelFormat.TRANSLUCENT; | |
| } | |
| protected void onBoundsChange(Rect bounds) { | |
| boundsChanged = true; | |
| } | |
| @Override | |
| public int getIntrinsicWidth() { | |
| return rect.width(); | |
| } | |
| @Override | |
| public int getIntrinsicHeight() { | |
| return rect.height(); | |
| } | |
| protected boolean needMirroring() { | |
| boolean rtl = false; | |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |
| rtl = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; | |
| } | |
| return isAutoMirrored() && rtl; | |
| } | |
| @Override | |
| public void draw(@NonNull Canvas canvas) { | |
| final boolean needMirroring = needMirroring(); | |
| if (needMirroring) { | |
| canvas.save(); | |
| canvas.translate(rect.right - rect.left, 0); | |
| canvas.scale(-1.0f, 1.0f); | |
| } | |
| canvas.drawText(text, -rect.left, -rect.top, paint); | |
| if (needMirroring) { | |
| canvas.restore(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment