Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Character style / span to set letter spacing

The TextView.setLetterSpacing allows the letter spacing / character spacing to be set.

Is there a corresponding CharacterStyle / span class that allows the letter spacing to be set on a subset of the text in a TextView?

like image 615
alexbirkett Avatar asked Dec 05 '22 22:12

alexbirkett


2 Answers

So I solved this by wring my own span class, it works on API level 21 and up.

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Parcel;
import android.text.TextPaint;
import android.text.style.MetricAffectingSpan;

/**
 * Created by alex on 19/02/2015.
 */
@TargetApi(21)
public class LetterSpacingSpan extends MetricAffectingSpan {
    private float letterSpacing;

    /**
     * @param letterSpacing
     */
    public LetterSpacingSpan(float letterSpacing) {
        this.letterSpacing = letterSpacing;
    }

    public float getLetterSpacing() {
        return letterSpacing;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        apply(ds);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint);
    }

    private void apply(TextPaint paint) {
        paint.setLetterSpacing(letterSpacing);
    }

}
like image 100
alexbirkett Avatar answered Dec 27 '22 17:12

alexbirkett


You can take a look at this custom class implementation that implements what you need.

EDIT: Ok, if you want to apply to a small portion of the text you can do this:

CharSequence firstPart = "First Part";
CharSequence thirdPart = "Third Part";
SpannableStringBuilder middlePart = new SpannableStringBuilder("Middle Part");

int spacing = 2;
final String nonBreakingSpace = "\u00A0";


for (int i = middlePart.length() - 1; i >= 1; i--){
    middlePart.insert(i, nonBreakingSpace);
    middlePart.setSpan(new ScaleXSpan(spacing), i, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}

((TextView) rootView.findViewById(R.id.text_view)).setText(TextUtils.concat(firstPart, " ", middlePart, " ", thirdPart));

It's not perfect though.

EDIT:

To be clear, this is the outcome of the code above

The first line ("Custom Spannable") is the result of (+/-) the code above. The second line ("Letter Spacing") is the result of the property android:letterSpacing="1".

enter image description here

As you can see, and as I said, it's not perfect, but is the only solution I found for pre-lollipop devices.

I also thought the whole point of your question was to make this compatible with pre-lollipop devices. My bad.

Cheers

like image 36
Joao Sousa Avatar answered Dec 27 '22 15:12

Joao Sousa