¿Cómo cambiar el espacio entre letras en una vista de texto?

127

¿Cómo puedo cambiar el espacio entre letras en una vista de texto? Ayudará si tengo texto HTML (no puedo usar webview en mi código).

PD: Estoy usando mi propio tipo de letra en la vista de texto con texto HTML.

OkyDokyman
fuente
55
En el editor de diseño puede hacer android:letterSpacing=".05"Donde .05 sería aproximadamente "50" en un programa como Photoshop
Jacksonkr

Respuestas:

26

echa un vistazo a android: textScaleX

Dependiendo de cuánto espacio necesite, esto podría ayudar. Esa es la única cosa remotamente relacionada con el espacio entre letras en TextView.

Editar: consulte la respuesta de @ JerabekJakub a continuación para obtener un método actualizado y mejor para hacerlo, comenzando con la API 21 (Lollipop)

zrgiu
fuente
9
¿Cómo traducirías eso al espacio entre letras?
Eric Novins
92
¿Hay alguna manera de aumentar / disminuir el espacio entre letras / caracteres? textScaleX - Literary escala las letras / caracteres.
Kaymatrix
2
La respuesta de @Barts hace lo que pregunta
bkurzius el
2
Escalar el texto en el eje X no es la forma correcta de manejar el kerning o el seguimiento en Android. Hay una API para Lollipop que logra esto, sin embargo, antes de Lollipop, necesitará una vista de texto personalizada para lograrlo.
Elliott
2
No sé cómo esta solución obtuvo tantos votos positivos (+33, -24) ¿las personas simplemente están votando a ciegas? letterSpacingvs textScaleXqué gran diferencia
Jimit Patel
230

Desde API 21 hay una opción para establecer el espaciado entre letras. Puede llamar al método setLetterSpacing o establecerlo en XML con el atributo letterSpacing .

JerabekJakub
fuente
1
Esto realmente no funciona cuando se establece en el XML. Me sale un error como este:"1.2dp" in attribute "letterSpacing" cannot be converted to float."
dopatraman
20
@dopatraman Debe omitir unidades, escriba solo el valor: android: letterSpacing = "1.2" en lugar de android: letterSpacing = "1.2dp"
JerabekJakub
12
Sabiendo que el 31% de los dispositivos no son compatibles con API 21, ¿cómo haría esto en versiones anteriores?
ninjaneer
25
Tenga en cuenta que el valor de letterSpacing no está en dp / sp, está en unidades 'EM'. Los valores típicos para una ligera expansión serán alrededor de 0.05. Los valores negativos ajustan el texto.
Cristan
25
Por alguna razón letterSpacingno estaba cambiando en la vista previa de AS. Tuve que ejecutar la aplicación en un dispositivo físico para ver el cambio.
Drew Szurko
46

Más espacio:

  android:letterSpacing="0.1"

Menos espacio:

 android:letterSpacing="-0.07"
Pablo Cegarra
fuente
2
¿Cuál es el espaciado de letras predeterminado?
Shivam
3
El valor predeterminado letterSpacinges 0.0 según developer.android.com/reference/android/widget/…
Evin1_
quizás agregue el comentario de @ Evin1_ en su respuesta
Sarthak Mittal
¿Cuál es el máximo y mínimo de LetterSpacing compatible?
Jimit Patel
26

Esta respuesta se basa en la respuesta de Pedro pero ajustada, por lo que también funciona si el atributo de texto ya está configurado:

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

Si quieres usarlo programáticamente:

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
fuente
¿Se agrega esto realmente espacios entre los personajes? Boo ... si alguien copia este texto, incluirá los espacios adicionales. No-Joy
johnw182
Necesita un nullregistro applyLetterSpacing, pero aparte de eso, ¡salva vidas!
Bart van Nierop
no funciona cuando configura las palabras clave del texto y luego aplica el espaciado programáticamente
Jonathan
@jonney debería, lo tengo funcionando así. ¿Podrías enviar un ejemplo?
Bart Burg
1
El espacio sin interrupción - "\ u00A0" - es realmente útil. Gracias
Shayan_Aryan
11

después de API> = 21 hay un método incorporado incorporado por TextView llamado setLetterSpacing

mira esto para más

Ravi
fuente
3
¿Cómo se puede igual en <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

Creé una clase personalizada que extiende TextViewy resuelve este problema ... Mira mi respuesta aquí =)

Pedro Barros
fuente
\\ muchas gracias por ahorrarme tiempo ^ _ ^
Muhamed El-Banna
0

Como Android no admite tal cosa, puede hacerlo manualmente con FontCreator. Tiene buenas opciones para modificar la fuente. Utilicé esta herramienta para construir una fuente personalizada, incluso si lleva algún tiempo, pero siempre puedes usarla en tus proyectos.

Ali
fuente