Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to adjust text kerning in Android TextView?

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.

like image 504
emmby Avatar asked Oct 28 '09 22:10

emmby


People also ask

How do I change the spacing between letters in android?

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.

How to fix size of TextView in android?

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.

What is the difference between kerning and tracking?

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).


4 Answers

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); 
like image 188
Pedro Barros Avatar answered Sep 22 '22 06:09

Pedro Barros


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; } 
like image 45
Takhion Avatar answered Sep 26 '22 06:09

Takhion


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.

like image 43
CommonsWare Avatar answered Sep 26 '22 06:09

CommonsWare


Since Android 21, you can use set the letterSpacing attribute.

<TextView
    android:width="..."
    android:height="..."
    android:letterSpacing="1.3"/>
like image 25
Algar Avatar answered Sep 25 '22 06:09

Algar