Skip to content

Instantly share code, notes, and snippets.

@vejei
Last active July 28, 2022 08:06
Show Gist options
  • Save vejei/f7632a68ac67c0e05502e8234af709c5 to your computer and use it in GitHub Desktop.
Save vejei/f7632a68ac67c0e05502e8234af709c5 to your computer and use it in GitHub Desktop.
Apply TextAppearance to TextPaint.
<declare-styleable name="CustomView">
<attr name="android:textAppearance"/>
</declare-styleable>
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Build;
import android.os.LocaleList;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.core.content.res.ResourcesCompat;
import java.util.Locale;
public class CustomView extends View {
private static final int SANS = 1;
private static final int SERIF = 2;
private static final int MONOSPACE = 3;
private TextPaint textPaint = new TextPaint();
private String text = "Hello World";
private Rect textBounds = new Rect();
public CustomView(Context context) {
this(context, null);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
textPaint.setTextAlign(Paint.Align.CENTER);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView, 0, 0);
int textAppearanceRes = a.getResourceId(R.styleable.CustomView_android_textAppearance, 0);
applyTextAppearance(textAppearanceRes);
a.recycle();
}
private void applyTextAppearance(@StyleRes int textAppearanceRes) {
TypedArray appearance = getContext().getTheme().obtainStyledAttributes(textAppearanceRes,
androidx.appcompat.R.styleable.TextAppearance);
// text size
int textSize = appearance.getDimensionPixelSize(
androidx.appcompat.R.styleable.TextAppearance_android_textSize, 0);
textPaint.setTextSize(textSize);
// typeface
Typeface typeface = null;
if (appearance.hasValue(androidx.appcompat.R.styleable.TextAppearance_fontFamily)) {
int fontId = appearance.getResourceId(
androidx.appcompat.R.styleable.TextAppearance_fontFamily, -1);
if (fontId != -1) {
typeface = ResourcesCompat.getFont(getContext(), fontId);
} else {
String fontFamily = appearance.getString(
androidx.appcompat.R.styleable.TextAppearance_android_fontFamily);
typeface = Typeface.create(fontFamily, Typeface.NORMAL);
}
} else {
int typefaceIndex = appearance.getInt(
androidx.appcompat.R.styleable.TextAppearance_android_typeface, -1);
switch (typefaceIndex) {
case SANS:
typeface = Typeface.SANS_SERIF;
break;
case SERIF:
typeface = Typeface.SERIF;
break;
case MONOSPACE:
typeface = Typeface.MONOSPACE;
break;
}
}
int styleIndex = appearance.getInt(
androidx.appcompat.R.styleable.TextAppearance_android_textStyle, -1);
if (styleIndex != -1) {
if (typeface != null) {
typeface = Typeface.create(typeface, styleIndex);
}
setLabelTypeface(typeface, styleIndex);
}
// text shadow
int shadowColor = appearance.getColor(
androidx.appcompat.R.styleable.TextAppearance_android_shadowColor, 0);
if (shadowColor != 0) {
float shadowRadius = appearance.getFloat(
androidx.appcompat.R.styleable.TextAppearance_android_shadowRadius, 0f);
float shadowDx = appearance.getFloat(
androidx.appcompat.R.styleable.TextAppearance_android_shadowDx, 0f);
float shadowDy = appearance.getFloat(
androidx.appcompat.R.styleable.TextAppearance_android_shadowDy, 0f);
textPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
}
// text locale
String localeText = appearance.getString(
androidx.appcompat.R.styleable.TextAppearance_textLocale);
if (localeText != null && localeText.equals("")) {
final String[] tags = localeText.split(",");
final Locale[] localeArray = new Locale[tags.length];
for (int i = 0; i < localeArray.length; i++) {
localeArray[i] = Locale.forLanguageTag(tags[i]);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
textPaint.setTextLocale(localeArray[0]);
} else {
textPaint.setTextLocales(new LocaleList(localeArray));
}
}
appearance.recycle();
}
private void setLabelTypeface(Typeface typeface, int style) {
if (style > 0) {
if (typeface == null) {
typeface = Typeface.defaultFromStyle(style);
} else {
typeface = Typeface.create(typeface, style);
}
setLabelTypeface(typeface);
// now compute what (if any) algorithmic styling is needed
int typefaceStyle = typeface != null ? typeface.getStyle() : 0;
int need = style & ~typefaceStyle;
textPaint.setFakeBoldText((need & Typeface.BOLD) != 0);
textPaint.setTextSkewX((need & Typeface.ITALIC) != 0 ? -0.25f : 0);
} else {
textPaint.setFakeBoldText(false);
textPaint.setTextSkewX(0);
setLabelTypeface(typeface);
}
}
private void setLabelTypeface(Typeface typeface) {
if ((textPaint.getTypeface() != null && !textPaint.getTypeface().equals(typeface))
|| (textPaint.getTypeface() == null && typeface != null)) {
textPaint.setTypeface(typeface);
}
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
float baselineX = width / 2f;
float baselineY;
textPaint.getTextBounds(text, 0, text.length(), textBounds);
baselineY = (height / 2f) - textBounds.exactCenterY();
canvas.drawText(text, baselineX, baselineY, textPaint);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment