Is there a way to adjust the spacing between characters in an Android TextView? I believe this is typically called "kerning".
I'm aware of the android:textScaleX attribute, but that compresses the characters along with the spacing.
Is there a way to adjust the spacing between characters in an Android TextView? I believe this is typically called "kerning".
I'm aware of the android:textScaleX attribute, but that compresses the characters along with the spacing.
If anyone is looking for a simple way to apply the kerning to any string (technically, CharSequence) without using a TextView:
public static Spannable applyKerning(CharSequence src, float kerning)
{
if (src == null) return null;
final int srcLength = src.length();
if (srcLength < 2) return src instanceof Spannable
? (Spannable)src
: new SpannableString(src);
final String nonBreakingSpace = "\u00A0";
final SpannableStringBuilder builder = src instanceof SpannableStringBuilder
? (SpannableStringBuilder)src
: new SpannableStringBuilder(src);
for (int i = src.length() - 1; i >= 1; i--)
{
builder.insert(i, nonBreakingSpace);
builder.setSpan(new ScaleXSpan(kerning), i, i + 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
Since Android 21, you can use set the letterSpacing attribute.
<TextView
android:width="..."
android:height="..."
android:letterSpacing="1.3"/>
It's difficult to adjust spacing between characters, when you are using TextView. But if you can handle the drawing yourself, there should be some way to do that.
My answer to this question is: use your custom Span .
My code:
public class LetterSpacingSpan extends ReplacementSpan {
private int letterSpacing = 0;
public LetterSpacingSpan spacing(int space) {
letterSpacing = space;
return this;
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
return (int) paint.measureText(text, start, end) + (text.length() - 1) * letterSpacing;
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
int length = text.length();
float currentX = x;
for (int i = 1; i < length; i++) {
canvas.drawText(text, i, i + 1, currentX, y, paint);
currentX += paint.measureText(text, i, i + 1) + letterSpacing;
}
}
}
Explain:
Building your own Span can help you achieve many amazing effect, like make a blur TextView, change the background or foreground for your TextView, even make some animation. I learn a lot from this post Span a powerful concept .
Because you are adding spacing to each character, so we should use a character level base span, in this case, ReplacementSpan is the best choice. I add a spacing method, so when using it, you can simply pass the space you want for each character as parameter.
When building your custom span, you need to override at least two method, getSize and draw. The getSize method should return the final width after we add the spacing for the whole charsequence, and inside the draw method block, you can control the Canvas to do the drawing you want.
So how we use this LetterSpacingSpan? It's easy:
Usage:
TextView textView;
Spannable content = new SpannableString("This is the content");
textView.setSpan(new LetterSpacingSpan(), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(content);
And that's it.
You can also try using a SpannedString but you would need to parse it and change the character spacing for each of the words