Jak zmienić odstępy między literami w widoku tekstowym?

127

Jak mogę zmienić odstępy między literami w widoku tekstu? Czy to pomoże, jeśli mam w nim tekst HTML (nie mogę użyć webview w moim kodzie).

PS Używam własnego kroju w widoku tekstowym z tekstem HTML.

OkyDokyman
źródło
5
W edytorze układu możesz zrobić android:letterSpacing=".05"Gdzie .05 byłoby mniej więcej „50” w programie takim jak Photoshop
Jacksonkr

Odpowiedzi:

26

sprawdź android: textScaleX

W zależności od potrzebnych odstępów może to pomóc. To jedyna rzecz, która jest zdalnie związana z odstępami między literami w TextView.

Edycja: zobacz odpowiedź @ JerabekJakub poniżej, aby uzyskać zaktualizowaną, lepszą metodę, aby to zrobić, zaczynając od api 21 (Lollipop)

zrgiu
źródło
9
Jak przełożyłbyś to na odstępy między literami?
Eric Novins
92
Czy istnieje sposób na zwiększenie / zmniejszenie odstępu między literami / znakami? textScaleX - Literackie skaluje litery / znaki.
Kaymatrix
2
@Barts odpowiada na pytanie
bkurzius
2
Skalowanie tekstu na osi X nie jest właściwym sposobem obsługi kerningu lub śledzenia w systemie Android. Istnieje interfejs API dla Lollipopa, który to robi, jednak przed Lollipopem będziesz potrzebować niestandardowego widoku tekstu, aby to osiągnąć.
Elliott,
2
Nie wiem, jak to rozwiązanie zyskało tak wiele głosów za (+33, -24), czy ludzie po prostu ślepo oddają swoje głosy? letterSpacingvs textScaleXjaka ogromna różnica
Jimit Patel
230

Od API 21 istnieje możliwość ustawienia odstępów między literami. Możesz wywołać metodę setLetterSpacing lub ustawić ją w XML z atrybutem letterSpacing .

JerabekJakub
źródło
1
To faktycznie nie działa, gdy jest ustawione w XML. Otrzymuję taki błąd:"1.2dp" in attribute "letterSpacing" cannot be converted to float."
dopatraman
20
@dopatraman Musisz ominąć jednostki, wpisz po prostu wartość: android: letterSpacing = "1.2" zamiast android: letterSpacing = "1.2dp"
JerabekJakub
12
Wiedząc, że 31% urządzeń nie obsługuje API 21, jak byś to zrobił w poprzednich wersjach?
ninjaneer
25
Zwróć uwagę, że wartość odstępu między literami nie jest wyrażona w dp / sp, ale w jednostkach „EM”. Typowe wartości dla niewielkiego rozszerzenia będą wynosić około 0,05. Wartości ujemne zawężają tekst.
Cristan,
25
Z jakiegoś powodu letterSpacingnie zmienia się w podglądzie AS. Musiałem faktycznie uruchomić aplikację na urządzeniu fizycznym, aby zobaczyć zmianę.
Drew Szurko
46

Więcej przestrzeni:

  android:letterSpacing="0.1"

Mniej miejsca:

 android:letterSpacing="-0.07"
Pablo Cegarra
źródło
2
jakie są domyślne odstępy między literami?
Shivam
3
Wartość domyślna letterSpacingto 0,0 według developer.android.com/reference/android/widget/ ...
Evin1_
może dodać komentarz @ Evin1_ w swojej odpowiedzi
Sarthak Mittal
jakie są maksymalne i minimalne odstępy między literami?
Jimit Patel
26

Ta odpowiedź jest oparta na odpowiedzi Pedro, ale została dostosowana, więc działa również, jeśli atrybut tekstu jest już ustawiony:

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

Jeśli chcesz używać go programowo:

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);
Bart Burg
źródło
czy to jest faktycznie dodane spacje między znakami? Boo ... jeśli ktoś skopiuje ten tekst, będzie zawierał dodatkowe spacje. No-Joy
johnw182
Potrzebuje nullzameldowania applyLetterSpacing, ale poza tym ratuje życie!
Bart van Nierop
nie działa, gdy ustawisz tekst po słowie, a następnie programowo zastosujesz odstępy
Jonathan
@jonney powinno, mam to tak działające. Czy mógłbyś podać przykład?
Bart Burg
1
Przestrzeń bez przerwy - „\ u00A0” - jest naprawdę przydatna. Dzięki
Shayan_Aryan,
11

po API> = 21 istnieje metoda wbudowana dostarczana przez TextView o nazwie setLetterSpacing

sprawdź to po więcej

Ravi
źródło
3
Jak to samo w <21?
Rahul Devanavar
2
if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.LOLLIPOP) {this.setLetterSpacing (getResources (). getDimension (R.dimen.letter_spacing)); } else {this.setTextScaleX (getResources (). getDimension (R.dimen.letter_spacing)); }
Maulik Patel
10

Zbudowałem niestandardową klasę, która rozszerza TextViewi rozwiązuje ten problem ... Sprawdź moją odpowiedź tutaj =)

Pedro Barros
źródło
\\ wielkie dzięki za zaoszczędzenie czasu ^ _ ^
Muhamed El-Banna
0

Ponieważ Android nie obsługuje czegoś takiego, możesz to zrobić ręcznie za pomocą FontCreator. Ma dobre opcje modyfikowania czcionek. Użyłem tego narzędzia do zbudowania niestandardowej czcionki, nawet jeśli zajmuje to trochę czasu, ale zawsze możesz jej użyć w swoich projektach.

Ali
źródło