Fuente de sugerencia de contraseña en Android


255

Cuando un EditText está en modo de contraseña, parece que la sugerencia se muestra en una fuente diferente (¿mensajería?). ¿Cómo puedo evitar esto? Me gustaría que la pista aparezca en la misma fuente que cuando EditText no está en modo de contraseña.

Mi xml actual:

<EditText 
android:hint="@string/edt_password_hint"
android:layout_width="fill_parent"
android:layout_height="wrap_content" 
android:password="true"
android:singleLine="true" />

1
Tenga en cuenta que no todos los dispositivos se comportan de esta manera. El "HTC One X @ 4.1.1" sí (monoespacio). El "Samsung GT-7510 @ 4.0.4" no. (misma fuente)
Loda

1
Mismo comportamiento en LeWa OS 4.2.2. API demasiado inconsistente ..
ruX

todavía existe en la piruleta también
Mightian

Puedes consultar mi respuesta aquí, espero que funcione.
Dmila Ram

Respuestas:


395

Cambiar el tipo de letra en xml tampoco funcionó en el texto de la pista. Encontré dos soluciones diferentes, la segunda de las cuales tiene un mejor comportamiento para mí:

1) Elimine android:inputType="textPassword"de su archivo xml y, en su lugar, configúrelo en Java:

EditText password = (EditText) findViewById(R.id.password_text);
password.setTransformationMethod(new PasswordTransformationMethod());

Con este enfoque, la fuente de sugerencia se ve bien, pero a medida que escribe en ese campo de edición, no verá cada carácter en texto sin formato antes de que se convierta en un punto de contraseña. Además, al realizar la entrada en pantalla completa, los puntos no aparecerán, sino la contraseña en texto claro.

2) Deja android:inputType="textPassword"en tu xml. En Java, TAMBIÉN establezca el tipo de letra y la contraseña Método:

EditText password = (EditText) findViewById(R.id.register_password_text);
password.setTypeface(Typeface.DEFAULT);
password.setTransformationMethod(new PasswordTransformationMethod());

Este enfoque me dio la fuente de pistas que quería Y me da el comportamiento que quiero con los puntos de contraseña.

¡Espero que ayude!


3
Genial, este es un comportamiento extraño, ¡no esperarías de forma predeterminada!
Sander Versluys

15
Es lo password.setTransformationMethod(new PasswordTransformationMethod());necesario? Parece funcionar bien para mí sin.
loeschg

1
No necesitaba usar el setTransformationMethod()tampoco. Sin embargo, hay algunos efectos secundarios de este enfoque que lo hacen indeseable porque da como resultado un comportamiento no estándar en comparación con el textPasswordcomportamiento predeterminado . Para una solución más completa, vea la clase auxiliar en: stackoverflow.com/a/17582092/231078
Joe

10
Mejor aún, mire esta gran solución simple en una respuesta en esta página: stackoverflow.com/a/18073897
Marcin Koziński

16
Tenga en cuenta que usar la primera solución es una mala idea: los usuarios que tienen habilitada la sugerencia automática comenzarán a ver su contraseña en otras aplicaciones, se les sugirió, porque EditText no se declaró comoinputType="textPassword"
Elad Nava

193

Encontré este consejo útil de la Guía de Diálogos

Consejo: De manera predeterminada, cuando configura un elemento EditText para usar el tipo de entrada "textPassword", la familia de fuentes se configura en monoespacio, por lo que debe cambiar su familia de fuentes a "sans-serif" para que ambos campos de texto usen una fuente coincidente estilo.


Por ejemplo

android:fontFamily="sans-serif"

21
Esta debería ser la respuesta aceptada. Es más simple y es de los documentos.
Marcin Koziński el

29
Es bueno, excepto que solo funciona en el nivel API 16 y superior
Ben Clayton

66
Tenga en cuenta que si bien solo funciona en el nivel 16 de API o superior, los atributos xml no causan fallas en dispositivos más antiguos, simplemente se ignoran.
Adam Johns

No funcionará si hace clic en mostrar / ocultar contraseña varias veces
Ali Habbash

32

Esto es lo que hice para solucionar este problema. Por alguna razón, no tuve que configurar el método de transformación, así que esta puede ser una mejor solución:

En mi xml:

<EditText
    android:id="@+id/password_edit_field"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:hint="Password"
    android:inputType="textPassword" />

En mi Activity:

EditText password = (EditText) findViewById( R.id.password_edit_field );
password.setTypeface( Typeface.DEFAULT );

Acabo de probarlo con textPassword en XML y como lo estabas haciendo en el archivo .java, y funcionó bien. Para mí, no parecía necesitar la transformación
Joe Plante

2
Recordatorio: llame a setTypeface () DESPUÉS de cambiar el InputType por código. setTransformationMethod no es necesario si InputType incluye xx_VARIATION_PASSWORD;
Loda

21

El enfoque setTransformationMethod rompe android: imeOption para mí y permite que los retornos de carro se escriban en el campo de contraseña. En cambio estoy haciendo esto:

setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);

Y no estoy configurando android: password = "true" en XML.


sí, esto también funcionó para mí en 6.0.1, la respuesta elegida no lo hizo
Nactus

5

La respuesta proporcionada por manisha funciona, pero deja el campo de contraseña en un estado no estándar en comparación con el predeterminado. Es decir, la fuente predeterminada se aplica también al campo de contraseña, incluidos los reemplazos de puntos y los caracteres de vista previa que aparecen antes de ser reemplazados por los puntos (así como cuando es un campo de "contraseña visible").

Para arreglar esto y hacer que 1) se vea y actúe exactamente como el textPasswordtipo de entrada predeterminado , pero también 2) permita que el texto de la sugerencia aparezca en una fuente predeterminada (no monoespacio), debe tener un TextWatchercampo en el campo que pueda alternar fontface correctamente de ida y vuelta entre Typeface.DEFAULTy Typeface.MONOSPACEsegún si está vacío o no. Creé una clase auxiliar que se puede usar para lograr eso:

import android.graphics.Typeface;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;

/**
 * This class watches the text input in a password field in order to toggle the field's font so that the hint text
 * appears in a normal font and the password appears as monospace.
 *
 * <p />
 * Works around an issue with the Hint typeface.
 *
 * @author jhansche
 * @see <a
 * href="http://stackoverflow.com/questions/3406534/password-hint-font-in-android">http://stackoverflow.com/questions/3406534/password-hint-font-in-android</a>
 */
public class PasswordFontfaceWatcher implements TextWatcher {
    private static final int TEXT_VARIATION_PASSWORD =
            (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
    private TextView mView;

    /**
     * Register a new watcher for this {@code TextView} to alter the fontface based on the field's contents.
     *
     * <p />
     * This is only necessary for a textPassword field that has a non-empty hint text. A view not meeting these
     * conditions will incur no side effects.
     *
     * @param view
     */
    public static void register(TextView view) {
        final CharSequence hint = view.getHint();
        final int inputType = view.getInputType();
        final boolean isPassword = ((inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
                == TEXT_VARIATION_PASSWORD);

        if (isPassword && hint != null && !"".equals(hint)) {
            PasswordFontfaceWatcher obj = new PasswordFontfaceWatcher(view);
            view.addTextChangedListener(obj);

            if (view.length() > 0) {
                obj.setMonospaceFont();
            } else {
                obj.setDefaultFont();
            }
        }
    }

    public PasswordFontfaceWatcher(TextView view) {
        mView = view;
    }

    public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
        // Not needed
    }

    public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
        if (s.length() == 0 && after > 0) {
            // Input field went from empty to non-empty
            setMonospaceFont();
        }
    }

    public void afterTextChanged(final Editable s) {
        if (s.length() == 0) {
            // Input field went from non-empty to empty
            setDefaultFont();
        }
    }

    public void setDefaultFont() {
        mView.setTypeface(Typeface.DEFAULT);
    }

    public void setMonospaceFont() {
        mView.setTypeface(Typeface.MONOSPACE);
    }
}

Luego, para usarlo, todo lo que necesita hacer es llamar al register(View)método estático. Todo lo demás es automático (¡incluso omitir la solución si la vista no lo requiere!):

    final EditText txtPassword = (EditText) view.findViewById(R.id.txt_password);
    PasswordFontfaceWatcher.register(txtPassword);

1
Buen trabajo. Un pequeño cambio: si configura una fuente en EditText(por ejemplo, haciendo que el texto de sugerencia sea Roboto Light), la configuración Typeface.DEFAULTposterior lo anulará. Llamo field.getTypeface()por adelantado y uso ese tipo de letra cada vez que necesito restablecer la fuente "predeterminada" más adelante.
Christopher Orr

Bueno, las llamadas field.getTypeface()no parecen ser 100% confiables (ya que a menudo solo recuperarás la fuente monoespacial), pero crear una Tipografía vía Typeface.create()y luego configurar eso parece funcionar bien.
Christopher Orr

5

Hay muchas maneras de resolver este problema, pero cada una tiene ventajas y desventajas. Aquí está mi prueba

Solo enfrento este problema de fuente en algún dispositivo (lista al final de mi respuesta) cuando habilito la contraseña de entrada

edtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);

Si uso android:inputType="textPassword", este problema no sucedió

Algo que he intentado

1) Use en su setTransformationMethodlugarinputType

edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
  • La fuente funcionará bien
  • La pantalla del teclado no está muy bien (solo muestra texto, no muestra el número encima del texto)

2) uso Typeface.DEFAULT

setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
  • Pantalla del teclado bien ,
  • La fuente puede no funcionar bien . El ejemplo sans-serif-lightes una fuente predeterminada para todos Viewen mi aplicación => después setTypeface(Typeface.DEFAULT), la EditTextfuente aún se ve diferente en algunos dispositivos

3) uso android:fontFamily="sans-serif"

MI SOLUCIÓN

almacenar en caché el tipo de letra antes de setInputTypereutilizarlo

Typeface cache = edtPassword.getTypeface();
edtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
edtPassword.setTypeface(cache);

Prueba de
algunos problemas de fuente de la cara del dispositivo

  • Xiaomi A2 (8.0.1)
  • Pixel XL (8.1.0)
  • Sony Xperia Z5 Au (SOV32) (6.0)
  • Flecha NX (F-04G) (6.0.1)
  • Kyocera (S2) (7.0)

Algunos dispositivos no enfrentan problemas de fuente

  • Samsung S4 (SC-04E) (5.0.1)
  • Samsung Galaxy Node 5 (5.1.1)
  • Samsung S7 Edge (SM-G935F) (7.0)

¿Cuál es el dispositivo (nombre y sistema operativo)?
CoolMind

1
@CoolMind gracias por su sugerencia, he actualizado el problema de fuente de la fuente del dispositivo y la base del problema de la fuente del dispositivo no está en mi dispositivo actual
Phan Van Linh

Gracias por una gran prueba! La vine de stackoverflow.com/a/52178340/2914140 . En Samsung S4 utilicé el setTransformationMethodmétodo (donde no enfrentaba un problema).
CoolMind

Como mencioné en mi respuesta, setTransformationMethodfuncionará pero el teclado no se mostrará bien. Sin embargo, si lo haces bien, sigue siendo así porque es solo un pequeño problema
Phan Van Linh

4

Las otras respuestas son la solución correcta para la mayoría de los casos.

Sin embargo, si está utilizando una EditTextsubclase personalizada para, por ejemplo, aplicar una fuente personalizada de forma predeterminada, hay un problema sutil. Si establece la fuente personalizada en el constructor de su subclase, el sistema la sobrescribirá si la establece inputType="textPassword".

En este caso, mueva su estilo a onAttachedToWindowdespués de su super.onAttachedToWindowllamada.

Implementación de ejemplo:

package net.petosky.android.ui;

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.EditText;

/**
 * An EditText that applies a custom font.
 *
 * @author cory@petosky.net
 */
public class EditTextWithCustomFont extends EditText {

    private static Typeface customTypeface;

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

    public EditTextWithCustomFont(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public EditTextWithCustomFont(
            Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * Load and store the custom typeface for this app.
     *
     * You should have a font file in: project-root/assets/fonts/
     */
    private static Typeface getTypeface(Context context) {
        if (customTypeface == null) {
            customTypeface = Typeface.createFromAsset(
                    context.getAssets(), "fonts/my_font.ttf");
        }
        return customTypeface;
    }

    /**
     * Set a custom font for our EditText.
     *
     * We do this in onAttachedToWindow instead of the constructor to support
     * password input types. Internally in TextView, setting the password
     * input type overwrites the specified typeface with the system default
     * monospace.
     */
    @Override protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // Our fonts aren't present in developer tools, like live UI
        // preview in AndroidStudio.
        if (!isInEditMode()) {
            setTypeface(getTypeface(getContext()));
        }
    }
}

3

Sé que este puede ser el más antiguo, pero me he metido en algo relacionado con este problema cuando lo usé InputTypey app:passwordToggleEnabled="true"juntos.

Entonces, escribir esto, ya que puede ayudar a alguien por aquí.

Quiero usar una fuente personalizada para el campo de contraseña junto con la app:passwordToggleEnabledopción para mi campo de entrada de contraseña. Pero en la biblioteca de soporte 27.1.1 (mientras escribía esto), se bloqueaba.

Entonces el código era como a continuación,

<android.support.design.widget.TextInputLayout
        android:id="@+id/input_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/_10dp"
        android:layout_marginTop="@dimen/_32dp"
        android:hint="@string/current_password"
        android:textColorHint="@color/hint_text_color"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/black">


        <EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="start|left"
            android:maxLines="1"
            android:textAlignment="viewStart"
            android:textColor="@color/black"
            android:textColorHint="@color/camel"
            android:textSize="@dimen/txt_16sp"
            app:font_style="regular"
            app:drawableEnd="@drawable/ic_remove_eye" />

    </android.support.design.widget.TextInputLayout>

El código anterior no se ha inputTypedefinido en XML

EditText password = (EditText) findViewById(R.id.password);
password.setTransformationMethod(new PasswordTransformationMethod());

Y en Java, setTransformationMethodme ayudará a adquirir las propiedades del textPasswordtipo de entrada y también estoy contento con mi estilo de fuente personalizado.

Pero el bloqueo mencionado a continuación ocurrió en todos los niveles de API con la biblioteca de soporte 27.1.1.

java.lang.NullPointerException: intento de invocar el método virtual 'void android.support.design.widget.CheckableImageButton.setChecked (boolean)' en una referencia de objeto nulo

Esto estaba fallando debido a la clase onRestoreInstanceStateinterna TextInputLayout.

Reproduzca pasos: cambie la visibilidad de la contraseña y minimice la aplicación y ábrala desde las aplicaciones recientes. Uh, ho se estrelló!

Todo lo que necesitaba es la opción de alternar contraseña predeterminada (usando la biblioteca de soporte) y la fuente personalizada en el campo de entrada de contraseña.

Después de un tiempo, descubierto haciendo lo siguiente,

<android.support.design.widget.TextInputLayout
        android:id="@+id/input_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="@dimen/_10dp"
        android:layout_marginTop="@dimen/_32dp"
        android:hint="@string/current_password"
        android:textColorHint="@color/hint_text_color"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:passwordToggleEnabled="true"
        app:passwordToggleTint="@color/black">


        <EditText
            android:id="@+id/password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="start|left"
            android:maxLines="1"
            android:textAlignment="viewStart"
            android:textColor="@color/black"
            android:textColorHint="@color/camel"
            android:textSize="@dimen/txt_16sp"
            app:font_style="regular"
            app:drawableEnd="@drawable/ic_remove_eye"
            android:inputType="textPassword" />

    </android.support.design.widget.TextInputLayout>

En XML, agregado android:inputType="textPassword"

TextInputLayout inputPassword = findViewById(R.id.input_password);
EditText password = findViewById(R.id.password);
EditText userName = findViewById(R.id.user_name);
// Get the typeface of user name or other edit text
Typeface typeface = userName.getTypeface();
if (typeface != null)
   inputLayout.setTypeface(typeface); // set to password text input layout

En el código de Java anterior,

Adquirí el tipo de letra personalizado del nombre de usuario EditTexty lo apliqué al TextInputLayoutcampo de contraseña. Ahora no necesita establecer el tipo de letra explícitamente en la contraseña, EditTextya que adquirirá la TextInputLayoutpropiedad.

Además, eliminé password.setTransformationMethod(new PasswordTransformationMethod());

Al hacer esto, passwordToggleEnabledestá funcionando, la fuente personalizada también se aplica y adiós al bloqueo. Espero que este problema se solucione en las próximas versiones de soporte.


2

También puede usar un widget personalizado. Es muy simple y no satura tu código de Actividad / Fragmento.

Aquí está el código:

public class PasswordEditText extends EditText {

  public PasswordEditText(Context context) {
    super(context);
    init();
  }

  public PasswordEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();

  }

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

  private void init() {
    setTypeface(Typeface.DEFAULT);
  }
}

Y su XML se verá así:

<com.sample.PasswordEditText
  android:id="@+id/password_edit_field"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:hint="Password"
  android:inputType="textPassword"
  android:password="true" />

En mi experiencia, esto no funciona: internamente TextViewparece sobrescribir el tipo de letra personalizado después de la llamada del constructor. Proporcionó una solución alternativa en otra respuesta.
Cory Petosky

2

usa la biblioteca de caligrafía .

entonces todavía no actualizará los campos de contraseña con la fuente correcta. así que haz esto en código no en xml:

Typeface typeface_temp = editText.getTypeface();
editText.setInputType(inputType); /*whatever inputType you want like "TYPE_TEXT_FLAG_NO_SUGGESTIONS"*/
//font is now messed up ..set it back with the below call
editText.setTypeface(typeface_temp); 

0

Recientemente agregué la capacidad de activar / desactivar el monoespacio a una extensión de EditText específicamente para contraseñas que puede ayudar a algunas personas. No utiliza, android:fontFamilypor lo que es compatible <16.


0

También puedes usar el

<android.support.design.widget.TextInputLayout/>

Juntos con

<android.support.v7.widget.AppCompatEditText/>

0

Utilizo esta solución para alternar el Tipo de letra dependiendo de la visibilidad de la pista. Es similar a la respuesta de Joe, pero en su lugar extiende EditText:

public class PasswordEditText extends android.support.v7.widget.AppCompatEditText {

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

    public PasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public PasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        if (text.length() > 0) setTypeface(Typeface.MONOSPACE);
        else setTypeface(Typeface.DEFAULT);
    }

}

0

En caso de que esté utilizando la biblioteca de caligrafía en combinación con un TextInputLayout y un EditText, el siguiente código funciona bien.

    EditText password = (EditText) findViewById(R.id.password);
    TextInputLayout passwordLayout = (TextInputLayout) findViewById(R.id.passwordLayout);

    Typeface typeface_temp = password.getTypeface();
    password.setInputType(InputType.TYPE_CLASS_TEXT |
            InputType.TYPE_TEXT_VARIATION_PASSWORD); 

    password.setTypeface(typeface_temp);
    passwordLayout.setTypeface(typeface_temp);

Esto no modificó mi tipo de letra de pista
Rafael Ruiz Muñoz

0

Un caso extraño quizás, pero he experimentado con esto y descubrí que:

password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
password.setTransformationMethod(new PasswordTransformationMethod());

¡cambió el tamaño de la fuente de la pista en lugar de la fuente en sí! Esto sigue siendo un efecto no deseado. Curiosamente, la operación inversa:

password.setTransformationMethod(new PasswordTransformationMethod());
password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);

Mantiene el mismo tamaño de fuente.


0

Encontré una solución segura a este problema

La mejor manera de Hola, encontré una solución segura para este problema

La mejor manera es crear un editText personalizado y guardar el valor de la tipografía como temporal y luego aplicar el método a los cambios de InputType. Finalmente, establecemos el valor de la cara del tipo temporal en editText. al igual que :

public class AppCompatPasswordEditText extends AppCompatEditText {


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

    public AppCompatPasswordEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AppCompatPasswordEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        // Our fonts aren't present in developer tools, like live UI
        // preview in AndroidStudio.
        Typeface cache = getTypeface();

        if (!isInEditMode() && cache != null) {
            setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
            setTypeface(cache);
        }
    }

}

-1

¡Así se hace una contraseña de entrada que tiene una pista que no se convirtió a * y tipo de letra predeterminado!

En XML:

android:inputType="textPassword"
android:gravity="center"
android:ellipsize="start"
android:hint="Input Password !."

En la actividad:

inputPassword.setTypeface(Typeface.DEFAULT);

gracias a: mango y rjrjr por la información: D.


-2

como el anterior, pero asegúrese de que los campos no tengan el estilo en negrita en xml, ya que nunca se verán iguales incluso con la corrección anterior.


2
No digas "arriba" ... las cosas cambian con el tiempo :-)
ZaBlanc
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.