How to change letter spacing in a Textview?

179,405

Solution 1

check out android:textScaleX

Depending on how much spacing you need, this might help. That's the only thing remotely related to letter-spacing in the TextView.

Edit: please see @JerabekJakub's response below for an updated, better method to do this starting with api 21 (Lollipop)

Solution 2

Since API 21 there is an option set letter spacing. You can call method setLetterSpacing or set it in XML with attribute letterSpacing.

Solution 3

More space:

  android:letterSpacing="0.1"

Less space:

 android:letterSpacing="-0.07"

Solution 4

This answer is based on Pedro's answer but adjusted so it also works if text attribute is already set:

package nl.raakict.android.spc.widget;
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 letterSpacing = LetterSpacing.BIGGEST;
    private CharSequence originalText = "";


    public LetterSpacingTextView(Context context) {
        super(context);
    }

    public LetterSpacingTextView(Context context, AttributeSet attrs){
        super(context, attrs);
        originalText = super.getText();
        applyLetterSpacing();
        this.invalidate();
    }

    public LetterSpacingTextView(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
    }

    public float getLetterSpacing() {
        return letterSpacing;
    }

    public void setLetterSpacing(float letterSpacing) {
        this.letterSpacing = letterSpacing;
        applyLetterSpacing();
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        originalText = text;
        applyLetterSpacing();
    }

    @Override
    public CharSequence getText() {
        return originalText;
    }

    private void applyLetterSpacing() {
        if (this == null || this.originalText == null) return;
        StringBuilder builder = new StringBuilder();
        for(int i = 0; i < originalText.length(); i++) {
            String c = ""+ originalText.charAt(i);
            builder.append(c.toLowerCase());
            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((letterSpacing+1)/10), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        super.setText(finalText, BufferType.SPANNABLE);
    }

    public class LetterSpacing {
        public final static float NORMAL = 0;
        public final static float NORMALBIG = (float)0.025;
        public final static float BIG = (float)0.05;
        public final static float BIGGEST = (float)0.2;
    }
}

If you want to use it programatically:

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

Solution 5

after API >=21 there is inbuild method provided by TextView called setLetterSpacing

check this for more

Share:
179,405

Related videos on Youtube

OkyDokyman
Author by

OkyDokyman

Developer

Updated on October 10, 2020

Comments

  • OkyDokyman
    OkyDokyman over 3 years

    How can i change letter spacing in a textview? Will it help if I have HTML text in it (I cannot use webview in my code).

    P.S. I'm using my own typeface in the textview with HTML text.

    • Jacksonkr
      Jacksonkr over 8 years
      In the layout editor you can do android:letterSpacing=".05" Where .05 would be roughly "50" in a program like photoshop
  • Eric Novins
    Eric Novins over 13 years
    How would you translate that over to letter spacing?
  • Kaymatrix
    Kaymatrix almost 12 years
    Is there a way to increase/decrease the space between letters/characters? textScaleX - Literary scales the letters/characters.
  • bkurzius
    bkurzius over 9 years
    @Barts answer does what the question is asking
  • johnw182
    johnw182 over 9 years
    is this added actually spaces between the characters? Boo... if someone copies this text it will include the extra spaces. No-Joy
  • Bart van Nierop
    Bart van Nierop over 9 years
    Needs a null check in applyLetterSpacing, but other than that, life saver!
  • Jono
    Jono over 9 years
    doesnt work when u set the text afterwords and then apply spacing programatically
  • Bart Burg
    Bart Burg over 9 years
    @jonney it should, I have it working like that. Could you send an example?
  • Jono
    Jono over 9 years
    Ok when I get to the office I will. Basically I added this view in xml and then did a find view by id to get the object and changed the spacing and text programmatically and it did not change it. If i dont set text the spacing works. If i do settext the spacing only applies a small amount? It's as if it can only apply the big size amount but nothing greater than that at all
  • JerabekJakub
    JerabekJakub over 9 years
    @Kumaresan Yes, there is - since API 21, see my answer below.
  • jguffey
    jguffey about 9 years
    @EricNovins did you ever find the answer to your question?
  • Shivam Bhalla
    Shivam Bhalla almost 9 years
    Hey, this doesn't work with ellipsis at the end of the text. Any ideas on how to fix that ?
  • Elliott
    Elliott almost 9 years
    Scaling the text in the X axis is not the proper way to handle kerning or tracking in Android. There is an api for lollipop that accomplishes this however previous to lollipop you will need a custom text view to accomplish this.
  • dopatraman
    dopatraman over 8 years
    This doesnt actually work when set in the XML. I get an error like this: "1.2dp" in attribute "letterSpacing" cannot be converted to float."
  • JerabekJakub
    JerabekJakub over 8 years
    @dopatraman You have to ommit units, type just value: android:letterSpacing="1.2" instead of android:letterSpacing="1.2dp"
  • lhunath
    lhunath over 8 years
    What is the purpose of c.toLowerCase()?
  • Bart Burg
    Bart Burg over 8 years
    @Ihunath to be completely honest, I don't remember. Try to remove it and see what happens
  • k2col
    k2col about 8 years
    how does this help? I'm not aware of an HTML tag for letter spacing that works in a TextView.
  • DearDhruv
    DearDhruv about 8 years
    @BartBurg your code works great. but If TextView has spannable string already then this code removes it.
  • ninjaneer
    ninjaneer almost 8 years
    Knowing that 31% of the devices don't support API 21, how would you do this in previous versions?
  • JerabekJakub
    JerabekJakub almost 8 years
    To be fair, according to Google there are more than 45% devices with API 21 and higher (June 2016). For lower API, you can check another answers here, for example Bart's below.
  • Shayan_Aryan
    Shayan_Aryan almost 8 years
    The no-break space - "\u00A0" - is really useful. Thanks
  • Cristan
    Cristan almost 8 years
    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. Negative values tighten text.
  • Rahul Devanavar
    Rahul Devanavar over 7 years
    How can to same in <21 ?
  • Jimit Patel
    Jimit Patel over 7 years
    I don't know how this solution got so many upvotes (+33, -24) are people just blindly putting up their votes? letterSpacing vs textScaleX what a huge difference
  • Jimit Patel
    Jimit Patel over 7 years
    @JerabekJakub is there any alternative for using letterSpacing below API 21?
  • JerabekJakub
    JerabekJakub over 7 years
    @JimitPatel Hi, as I said before, you can check other answers, for example Bart's answer below.
  • Drew Szurko
    Drew Szurko over 6 years
    For some reason letterSpacing wasn't changing in the AS preview. I had to actually run the app on a physical device to see the change.
  • Someone Somewhere
    Someone Somewhere about 6 years
    It's true - Android Studio design mode does NOT properly respect this parameter. Probably worthy of a bug write-up against the tool. OR don't report it and tell your manager you need a device just to test this. ;-)
  • Maulik Patel
    Maulik Patel about 6 years
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { this.setLetterSpacing(getResources().getDimension(R.dimen.le‌​tter_spacing)); }else{ this.setTextScaleX(getResources().getDimension(R.dimen.lette‌​r_spacing)); }
  • Shivam
    Shivam about 5 years
    what is the default letterSpacing?
  • Evin1_
    Evin1_ almost 5 years
    The default letterSpacing is 0.0 according to developer.android.com/reference/android/widget/…
  • Valter Ekholm
    Valter Ekholm over 4 years
    I tried putting normal spaces between each letter, it worked.
  • reactor
    reactor over 4 years
    if I toggle between numberPassword as the initial setting in xml and then swap to inputField.setInputType( InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD);, the masking bullets initially take up way less space until changed via Java. I was wondering how letterspacing can be used to keep spacing consistent when changing between these two types
  • ToolmakerSteve
    ToolmakerSteve over 4 years
    @JimitPatel - At the time the question was asked, letterSpacing option did not exist.
  • Jimit Patel
    Jimit Patel over 4 years
    @ToolmakerSteve that does not make me to write an answer to popular question with latest findings. That will help other users to get an answer easily. That was only my intention
  • Sarthak Mittal
    Sarthak Mittal over 4 years
    maybe add @Evin1_'s comment in ur answer
  • Jimit Patel
    Jimit Patel about 4 years
    what is the maximum and minimum letterSpacing supported?