Como alterar o espaçamento entre letras em um Textview?

127

Como posso alterar o espaçamento entre letras em uma visualização de texto? Ajudará se eu tiver texto HTML (não consigo usar a visualização da web no meu código).

PS Estou usando meu próprio tipo de letra na visualização de texto com texto HTML.

OkyDokyman
fonte
5
No editor de layout, você pode fazer android:letterSpacing=".05"Where .05 seria aproximadamente "50" em um programa como o photoshop
Jacksonkr

Respostas:

26

confira android: textScaleX

Dependendo do espaçamento necessário, isso pode ajudar. Essa é a única coisa remotamente relacionada ao espaçamento entre letras no TextView.

Editar: consulte a resposta de @ JerabekJakub abaixo para obter um método melhor e atualizado para fazer isso, começando com a api 21 (pirulito)

zrgiu
fonte
9
Como você traduziria isso para espaçamento entre letras?
Eric Novins
92
Existe uma maneira de aumentar / diminuir o espaço entre letras / caracteres? textScaleX - Literário dimensiona as letras / caracteres.
Kaymatrix
2
@Barts resposta faz o que a questão está pedindo
bkurzius
2
Escalar o texto no eixo X não é a maneira correta de lidar com kerning ou rastreamento no Android. Existe uma API para pirulito que realiza isso, porém, anterior ao pirulito, você precisará de uma visualização de texto personalizada para fazer isso.
Elliott
2
Não sei como essa solução recebeu tantos votos positivos (+33, -24) que as pessoas estão apenas cegamente votando? letterSpacingvs textScaleXo que uma enorme diferença
Jimit Patel
230

Desde a API 21, existe um espaçamento entre letras do conjunto de opções. Você pode chamar o método setLetterSpacing ou configurá-lo em XML com o atributo letterSpacing .

JerabekJakub
fonte
1
Na verdade, isso não funciona quando definido no XML. Eu recebo um erro como este:"1.2dp" in attribute "letterSpacing" cannot be converted to float."
dopatraman 16/01
20
@dopatraman Você tem que omitir unidades, digite apenas o valor: android: letterSpacing = "1.2" em vez de android: letterSpacing = "1.2dp"
JerabekJakub
12
Sabendo que 31% dos dispositivos não oferecem suporte à API 21, como você faria isso nas versões anteriores?
Ninjaneer 2/16
25
Observe que o valor de letterSpacing não está em dp / sp, está em unidades 'EM'. Os valores típicos para leve expansão serão em torno de 0,05. Valores negativos restringem o texto.
Cristan
25
Por algum motivo letterSpacingnão estava mudando na visualização do AS. Eu tive que realmente executar o aplicativo em um dispositivo físico para ver a mudança.
Tirou Szurko
46

Mais espaço:

  android:letterSpacing="0.1"

Menos espaço:

 android:letterSpacing="-0.07"
Pablo Cegarra
fonte
2
qual é o letterSpacing padrão?
Shivam
3
O padrão letterSpacingé 0.0, de acordo com developer.android.com/reference/android/widget/…
Evin1_
talvez adicione o comentário de @ Evin1_ na sua resposta
Sarthak Mittal
qual é o letterSpacing máximo e mínimo suportado?
Jimit Patel
26

Esta resposta é baseada na resposta de Pedro, mas ajustada para que também funcione se o atributo de texto já estiver definido:

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

Se você deseja usá-lo programaticamente:

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
fonte
isso é adicionado, na verdade, espaços entre os caracteres? Boo ... se alguém copiar esse texto, ele incluirá os espaços extras. No-Joy
johnw182
Precisa de um nullcheck-in applyLetterSpacing, mas fora isso, salva-vidas!
Bart van Nierop
não funciona quando u definir os afterwords de texto e depois aplicar espaçamento programaticamente
Jonathan
@ Jonney deveria, eu tenho que trabalhar assim. Você poderia enviar um exemplo?
Bart Burg
1
O espaço sem interrupção - "\ u00A0" - é realmente útil. Graças
Shayan_Aryan
11

depois da API> = 21, existe o método inbuild fornecido pelo TextView chamado setLetterSpacing

verifique isso para mais

Ravi
fonte
3
Como pode o mesmo em <21?
Rahul Devanavar 01/03/19
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

Criei uma classe personalizada que estende TextViewe resolve esse problema ... Confira minha resposta aqui =)

Pedro Barros
fonte
\\ muito obrigado por poupar meu tempo ^ _ ^
Muhamed El-Banna
0

Como o Android não suporta isso, você pode fazê-lo manualmente com o FontCreator. Tem boas opções para modificar fontes. Usei essa ferramenta para criar uma fonte personalizada, mesmo que demore algum tempo, mas você sempre pode usá-la em seus projetos.

Todos
fonte