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.
You can call method setLetterSpacing or set it in XML with attribute letterSpacing. Knowing that 31% of the devices don't support API 21, how would you do this in previous versions? Note that the value of letterSpacing isn't in dp/sp, it is in 'EM' units. Typical values for slight expansion will be around 0.05.
I made fixed size column and scrollable textview. Firstly I remove size tag from shape drawable resource. And I add the following code for each column. LayoutParams params = new TableRow.
Kerning looks at the adjustments of spaces between a pair of letters, while tracking examines the spacing between larger groups of letters and blocks of text. Kerning and tracking are usually accessed simultaneously for things like webpage design and the production of branded materials (like catalogues).
I built a custom class that extends TextView and adds a method "setSpacing". The workaround is similar to what @Noah said. The method adds a space between each letter of the String and with SpannedString changes the TextScaleX of the spaces, allowing positive and negative spacing.
Hope that helps someone ^^
/** * Text view that allows changing the letter spacing of the text. * * @author Pedro Barros (pedrobarros.dev at gmail.com) * @since May 7, 2013 */ import android.content.Context; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ScaleXSpan; import android.util.AttributeSet; import android.widget.TextView; public class LetterSpacingTextView extends TextView { private float spacing = Spacing.NORMAL; private CharSequence originalText = ""; public LetterSpacingTextView(Context context) { super(context); } public LetterSpacingTextView(Context context, AttributeSet attrs){ super(context, attrs); } public LetterSpacingTextView(Context context, AttributeSet attrs, int defStyle){ super(context, attrs, defStyle); } public float getSpacing() { return this.spacing; } public void setSpacing(float spacing) { this.spacing = spacing; applySpacing(); } @Override public void setText(CharSequence text, BufferType type) { originalText = text; applySpacing(); } @Override public CharSequence getText() { return originalText; } private void applySpacing() { if (this == null || this.originalText == null) return; StringBuilder builder = new StringBuilder(); for(int i = 0; i < originalText.length(); i++) { builder.append(originalText.charAt(i)); if(i+1 < originalText.length()) { builder.append("\u00A0"); } } SpannableString finalText = new SpannableString(builder.toString()); if(builder.toString().length() > 1) { for(int i = 1; i < builder.toString().length(); i+=2) { finalText.setSpan(new ScaleXSpan((spacing+1)/10), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } super.setText(finalText, BufferType.SPANNABLE); } public class Spacing { public final static float NORMAL = 0; } }
Using it:
LetterSpacingTextView textView = new LetterSpacingTextView(context); textView.setSpacing(10); //Or any float. To reset to normal, use 0 or LetterSpacingTextView.Spacing.NORMAL textView.setText("My text"); //Add the textView in a layout, for instance: ((LinearLayout) findViewById(R.id.myLinearLayout)).addView(textView);
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; }
AFAIK, you cannot adjust kerning in TextView
. You may be able to adjust kerning if you draw the text on the Canvas
yourself using the 2D graphics APIs.
Since Android 21, you can use set the letterSpacing
attribute.
<TextView
android:width="..."
android:height="..."
android:letterSpacing="1.3"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With