Fonte de dica de senha no Android

255

Quando um EditText está no modo de senha, parece que a dica é mostrada em uma fonte diferente (courrier?). Como posso evitar isso? Gostaria que a dica apareça na mesma fonte que quando o EditText não está no modo de senha.

Meu xml atual:

<EditText 
android:hint="@string/edt_password_hint"
android:layout_width="fill_parent"
android:layout_height="wrap_content" 
android:password="true"
android:singleLine="true" />
hpique
fonte
1
Observe que nem todos os dispositivos se comportam dessa maneira. O "HTC One X @ 4.1.1" funciona (monoespaço). O "Samsung GT-7510 @ 4.0.4" não. (mesma fonte)
Loda
1
Mesmo comportamento no LeWa OS 4.2.2. Muito inconsistente API ..
Rux
ainda existe no pirulito também
Mightian
você pode conferir minha resposta aqui espero que funcione.
Dmila Ram

Respostas:

394

Alterar o tipo de letra em xml também não funcionou no texto da dica para mim. Encontrei duas soluções diferentes, a segunda com melhor comportamento para mim:

1) Remova android:inputType="textPassword"do seu arquivo xml e, em vez disso, configure-o em java:

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

Com essa abordagem, a fonte da dica parece boa, mas enquanto você digita esse campo de edição, você não vê cada caractere em texto sem formatação antes de se transformar em um ponto de senha. Além disso, ao inserir entradas em tela cheia, os pontos não aparecerão, mas a senha em texto não criptografado.

2) Deixe android:inputType="textPassword"no seu xml. Em Java, defina TAMBÉM o tipo de letra e passwordMethod:

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

Essa abordagem me deu a fonte da dica que eu queria E me deu o comportamento que eu quero com os pontos da senha.

Espero que ajude!

manisha
fonte
3
Ótimo, esse é um comportamento estranho, você não esperaria do padrão!
Sander Versluys
15
É password.setTransformationMethod(new PasswordTransformationMethod());necessário? Parece funcionar bem para mim sem.
precisa
1
Eu também não precisava usar o setTransformationMethod(). No entanto, existem alguns efeitos colaterais dessa abordagem que a tornam indesejável, pois resulta em um comportamento não padrão comparado ao textPasswordcomportamento padrão . Para obter uma solução mais completa, consulte a classe helper em: stackoverflow.com/a/17582092/231078
Joe
10
Melhor ainda, olhar para este grande solução simples em uma resposta certa desta página: stackoverflow.com/a/18073897
Marcin Kozinski
16
Lembre-se de que usar a primeira solução é uma péssima idéia - os usuários com sugestão automática ativada começarão a ver sua senha em outros aplicativos, sugeridos a eles, porque o EditText não foi declarado comoinputType="textPassword"
Elad Nava
193

Encontrei essa dica útil no Dialogs Guide

Dica: Por padrão, quando você define um elemento EditText para usar o tipo de entrada "textPassword", a família de fontes é definida como monoespaçada, portanto, você deve alterar sua família de fontes para "sans-serif" para que os dois campos de texto usem uma fonte correspondente estilo.


Por exemplo

android:fontFamily="sans-serif"
aysonje
fonte
21
Essa deve ser a resposta aceita. É mais simples e é dos documentos.
Marcin Koziński
29
É bom, exceto que ele só funciona em nível de API 16 e acima
Ben Clayton
6
Observe que, embora funcione apenas no nível 16 e acima da API, os atributos xml não causam falhas em dispositivos mais antigos, mas são ignorados.
Adam Johns
Ele não funcionará se você clicar em Mostrar / esconder senha várias vezes
Ali Habbash
32

Foi isso que fiz para corrigir esse problema. Por alguma razão, não precisei definir o método de transformação, portanto essa pode ser uma solução melhor:

No meu xml:

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

No meu Activity:

EditText password = (EditText) findViewById( R.id.password_edit_field );
password.setTypeface( Typeface.DEFAULT );
James McCracken
fonte
Eu apenas tentei com textPassword em XML e como você estava fazendo no arquivo .java, e funcionou perfeitamente. Para mim, parece que não precisava da transformação #
Joe Plante
2
Lembrete: Ligue para setTypeface () DEPOIS de alterar o InputType por código. setTransformationMethod não é necessário se InputType incluir xx_VARIATION_PASSWORD;
Loda
21

A abordagem setTransformationMethod quebra android: imeOption para mim e permite que os retornos de carro sejam digitados no campo de senha. Em vez disso, estou fazendo o seguinte:

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

E não estou definindo android: password = "true" em XML.

rjrjr
fonte
yap, isso funcionou para mim em 6.0.1, bem como, a resposta escolhida não
Nactus
5

A resposta fornecida pelo manisha funciona, mas deixa o campo de senha em um estado não padrão comparado ao padrão. Ou seja, a fonte padrão também se aplica ao campo de senha, incluindo as substituições de pontos e os caracteres de visualização que aparecem antes de serem substituídos pelos pontos (bem como quando é um campo de "senha visível").

Para corrigir isso e fazer com que 1) pareça e atue exatamente como o textPasswordtipo de entrada padrão , mas também 2) permita que o texto da dica apareça em uma fonte padrão (não monoespaçada), você precisa ter um TextWatchercampo que possa alternar o fontface adequadamente entre Typeface.DEFAULTe com Typeface.MONOSPACEbase em se está vazio ou não. Eu criei uma classe auxiliar que pode ser usada para fazer isso:

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

Então, para usá-lo, tudo o que você precisa fazer é chamar o register(View)método estático. Todo o resto é automático (incluindo pular a solução alternativa se a exibição não exigir isso!):

    final EditText txtPassword = (EditText) view.findViewById(R.id.txt_password);
    PasswordFontfaceWatcher.register(txtPassword);
Joe
fonte
1
Bom trabalho. Uma pequena alteração: se você definir uma fonte no EditText(por exemplo, fazer o texto da dica Roboto Light), a configuração Typeface.DEFAULTposterior substituirá isso. Eu ligo field.getTypeface()de frente e uso esse tipo de letra sempre que preciso redefinir a fonte "padrão" posteriormente.
Christopher Orr
Bem, a chamada field.getTypeface()não parece ser 100% confiável (como muitas vezes você receberá a fonte monoespaçada), mas a criação de um Typeface via Typeface.create()e depois a configuração que parece funcionar bem.
Christopher Orr
5

Há muitas maneiras de resolver esse problema, mas cada uma delas tem prós e contras. Aqui está o meu teste

Eu só enfrento esse problema de fonte em algum dispositivo (lista no final da minha resposta) ao ativar a senha de entrada por

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

Se eu usar android:inputType="textPassword", esse problema não aconteceu

Algo que eu tentei

1) Use em setTransformationMethodvez dissoinputType

edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
  • Font vai funcionar bem
  • A exibição do teclado não está muito bem (apenas exibe texto, não exibe o número na parte superior do texto)

2) Use Typeface.DEFAULT

setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
  • Teclado exibir bem ,
  • Fonte pode não funcionar bem . Exemplo sans-serif-lighté uma fonte padrão para todos Viewno meu aplicativo => depois setTypeface(Typeface.DEFAULT), a EditTextfonte ainda parece diferente em alguns dispositivos

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

MINHA SOLUÇÃO

armazenar em cache o tipo de letra antes de setInputTypereutilizá-lo

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

Testando
algum dispositivo enfrenta problema de fonte

  • Xiaomi A2 (8.0.1)
  • Pixel XL (8.1.0)
  • Sony Xperia Z5 (SOV32) (6.0)
  • Arrow NX (F-04G) (6.0.1)
  • Kyocera (S2) (7,0)

Alguns dispositivos não enfrentam problemas de fonte

  • Samsung S4 (SC-04E) (5.0.1)
  • Samsung Galaxy Node 5 (5.1.1)
  • Samsung S7 Edge (SM-G935F) (7.0)
Phan Van Linh
fonte
Qual é o dispositivo (nome e SO)?
CoolMind 20/09/19
1
@CoolMind obrigado por sua sugestão, eu tenho problema de fonte de atualização do dispositivo rosto e dispositivo não enfrentar base de problema de fonte no meu dispositivo atual
Phan Van Linh
Obrigado por um grande teste! Eu a vim de stackoverflow.com/a/52178340/2914140 . No Samsung S4 eu usei o setTransformationMethodmétodo (onde não enfrentou um problema).
CoolMind 20/09/19
Como mencionei na minha resposta, setTransformationMethodfuncionará, mas o teclado não será exibido bem. No entanto, se você Oke com ele, ainda Oke porque apenas um pequeno problema
Phan Van Linh
4

As outras respostas são a solução certa para a maioria dos casos.

No entanto, se você estiver usando uma EditTextsubclasse personalizada para, por exemplo, aplicar uma fonte personalizada por padrão, há um problema sutil. Se você definir a fonte personalizada no construtor de sua subclasse, ela ainda será substituída pelo sistema se você definir inputType="textPassword".

Nesse caso, mova seu estilo para onAttachedToWindowapós a super.onAttachedToWindowchamada.

Exemplo de implementação:

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 [email protected]
 */
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()));
        }
    }
}
Cory Petosky
fonte
3

Sei que esse pode ser o mais antigo, mas me deparei com algo relacionado a esse problema quando usei InputTypee app:passwordToggleEnabled="true"juntos.

Então, escreva isso, pois pode ajudar alguém por aqui.

Quero usar uma fonte personalizada para o campo de senha, juntamente com a app:passwordToggleEnabledopção para o meu campo de entrada de senha. Mas na biblioteca de suporte 27.1.1 (enquanto escrevia isso), estava travando.

Então o código era como abaixo,

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

O código acima não foi inputTypedefinido em XML

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

E em Java, setTransformationMethodme ajudará a adquirir as propriedades do textPasswordtipo de entrada e também estou feliz com meu estilo de fonte personalizado.

Mas a falha mencionada abaixo ocorreu em todos os níveis da API com a biblioteca de suporte 27.1.1.

java.lang.NullPointerException: tentativa de chamar o método virtual 'void android.support.design.widget.CheckableImageButton.setChecked (boolean)' em uma referência de objeto nulo

Isso estava travando devido à classe onRestoreInstanceStateinterna TextInputLayout.

Reproduzir etapas: alterne a visibilidade da senha, minimize o aplicativo e abra-o nos aplicativos recentes. Uh, ho Crashed!

Tudo o que eu precisava é a opção de alternância de senha padrão (usando a biblioteca de suporte) e a fonte personalizada no campo de entrada de senha.

Depois de algum tempo, resolvi fazer o seguinte,

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

Em XML, adicionado 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

No código java acima,

Adquiri o tipo de letra personalizado do nome de usuário EditTexte o apliquei TextInputLayoutno campo de senha. Agora você não precisa definir o tipo de letra explicitamente para a senha, EditTextpois ela adquirirá a TextInputLayoutpropriedade.

Além disso, eu removi password.setTransformationMethod(new PasswordTransformationMethod());

Dessa maneira, passwordToggleEnabledestá funcionando, a fonte personalizada também é aplicada e adeus à falha. Espero que esse problema seja corrigido nas próximas versões de suporte.

Kavin Prabhu
fonte
2

Você também pode usar um widget personalizado. É muito simples e não bagunça seu código de Atividade / Fragmento.

Aqui está o 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);
  }
}

E seu XML ficará assim:

<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" />
Aldo Borrero
fonte
Na minha experiência, isso não funciona - internamente TextViewparece substituir o tipo de letra personalizado após a chamada do construtor. Forneceu uma solução alternativa em outra resposta.
Cory Petosky
2

use a biblioteca de caligrafia .

ainda não atualizará os campos da senha com a fonte correta. faça isso no código e não no 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); 
j2emanue
fonte
0

Recentemente, adicionei a capacidade de ativar / desativar o monoespaço em uma extensão do EditText especificamente para senhas que podem ajudar algumas pessoas. Não usa, por android:fontFamilyisso é compatível <16.

scottyab
fonte
0

Você também pode usar o

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

junto com

<android.support.v7.widget.AppCompatEditText/>
DoruChidean
fonte
0

Eu uso essa solução para alternar o tipo de letra dependendo da visibilidade da dica. É semelhante à resposta de Joe, mas estendendo 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);
    }

}
KTCO
fonte
0

Caso você esteja usando a biblioteca de caligrafia em combinação com um TextInputLayout e um EditText, o código a seguir funciona bem.

    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);
Philipp Hellmayr
fonte
Isso não modificou a minha dica fonte
Rafael Ruiz Muñoz
0

Um caso estranho, talvez, mas eu experimentei isso e descobri que:

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

alterou o tamanho da fonte da dica em vez da própria fonte! Este ainda é um efeito indesejado. Curiosamente, a operação reversa:

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

Mantém o mesmo tamanho de fonte.

MPelletier
fonte
0

Encontrei uma solução certa para esse problema

Melhor maneira de Olá, eu encontrei uma solução certa para este problema

A melhor maneira é criar um editText personalizado e salvar o valor do tipo de letra como temp e, em seguida, aplicar o método às alterações do InputType. Finalmente, atrasamos o valor do tipo de temp para o editText. igual a :

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

}
Mr.Hosseini
fonte
-1

É assim que criar uma senha de entrada com uma dica que não foi convertida em * e o tipo de letra padrão !!.

No XML:

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

Na atividade:

inputPassword.setTypeface(Typeface.DEFAULT);

agradecimentos a: manga e rjrjr pela compreensão: D.

Bhimbim
fonte
-2

como acima, mas verifique se os campos não têm o estilo negrito em xml, pois nunca terão a mesma aparência, mesmo com a correção acima!

Dori
fonte
2
Não diga "acima" ... as coisas mudam ao longo do tempo :-)
ZaBlanc