Шрифт подсказки пароля в Android

Когда EditText находится в режиме пароля, кажется, что подсказка отображается другим шрифтом (courrier?). Как я могу избежать этого? Я хотел бы, чтобы подсказка отображалась в том же шрифте, что и при редактировании EditText в режиме пароля.

Мой текущий xml:

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

Ответ 1

Изменение шрифта в xml также не сработало для текста подсказки. Я нашел два разных решения, второе из которых имеет лучшее поведение для меня:

1) Удалите android:inputType="textPassword" из вашего xml файла и вместо этого установите его в java:

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

При таком подходе шрифт подсказки выглядит хорошо, но когда вы печатаете в этом поле редактирования, вы не видите каждый символ в виде простого текста, пока он не превратится в точку пароля. Также при вводе в полноэкранном режиме не будут отображаться точки, кроме пароля в виде открытого текста.

2) Оставьте android:inputType="textPassword" в вашем xml. В Java ТАКЖЕ установить гарнитуру и passwordMethod:

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

Этот подход дал мне шрифт подсказки, который я хотел И дал мне поведение, которое я хочу с точками пароля.

Надеюсь, это поможет!

Ответ 2

Я нашел этот полезный совет из Диалоговое окно

Совет. По умолчанию, когда вы устанавливаете элемент EditText для использования типа ввода "textPassword", семейство шрифтов устанавливается в моноширинное, поэтому вы должны изменить его семейство шрифтов на "sans-serif", чтобы использовать оба текстовых поля соответствующий стиль шрифта.


Например

android:fontFamily="sans-serif"

Ответ 3

Вот что я сделал, чтобы исправить эту проблему. По какой-то причине мне не нужно было устанавливать метод преобразования, чтобы это могло быть лучшим решением:

В моем xml:

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

В моем Activity:

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

Ответ 4

Метод setTransformationMethod разбивает android: imeOption для меня и позволяет вводить данные каретки в поле пароля. Вместо этого я делаю это:

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

И не устанавливаю android: password = "true" в XML.

Ответ 5

Предоставленный ответ manisha работает, но он оставляет поле пароля в нестандартном состоянии по сравнению со значением по умолчанию. То есть шрифт по умолчанию затем применяется также к полю пароля, включая как замены точек, так и символы предварительного просмотра, которые появляются перед заменой точками (а также в поле "видимый пароль" ).

Чтобы исправить это и сделать это 1) посмотрите и действуйте точно так же, как и тип ввода по умолчанию textPassword, но также и 2) разрешите текст подсказки в шрифте по умолчанию (не моноширинный), вам нужно иметь TextWatcher в поле, которое может правильно переключать шрифт назад и вперед между Typeface.DEFAULT и Typeface.MONOSPACE в зависимости от того, пуст он или нет. Я создал вспомогательный класс, который можно использовать для этого:

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

Затем, чтобы использовать его, все, что вам нужно сделать, это вызвать статический метод register(View). Все остальное автоматическое (в том числе пропустить обходной путь, если представление его не требует!):

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

Ответ 6

Другие ответы - правильное решение для большинства случаев.

Однако, если вы используете собственный подкласс EditText, чтобы, скажем, применить собственный шрифт по умолчанию, есть тонкая проблема. Если вы установите пользовательский шрифт в конструкторе вашего подкласса, он все равно будет перезаписан системой, если вы установите inputType="textPassword".

В этом случае переместите свой стиль на onAttachedToWindow после вашего вызова super.onAttachedToWindow.

Пример реализации:

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

Ответ 7

Есть много способов решения этой проблемы, но у каждого есть свои плюсы и минусы. Вот мое тестирование

Я сталкиваюсь с этой проблемой шрифтов только на каком-то устройстве (список в конце моего ответа) при включении ввода пароля

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

Если я использую android:inputType="textPassword", эта проблема не возникла

Что-то я пробовал

1) Используйте setTransformationMethod вместо inputType

edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
  • Шрифт будет работать хорошо
  • Клавиатура отображается не очень хорошо (она отображает только текст, но не отображает число поверх текста)

2) Используйте Typeface.DEFAULT

setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
  • Клавиатура хорошо отображается,
  • Шрифт может работать не очень хорошо. Пример sans-serif-light является шрифтом по умолчанию для всех View в моем приложении => после setTypeface(Typeface.DEFAULT), шрифт EditText прежнему выглядит по- другому на некоторых устройствах

3) Используйте android:fontFamily="sans-serif"

  • Для некоторых устройств это будет CRASH, проверьте мой ответ здесь fooobar.com/questions/538978/.... А также шрифт по-прежнему выглядит по- другому

МОЕ РЕШЕНИЕ

кэшировать гарнитуру перед setInputType затем использовать ее

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

тестирование
Некоторое устройство сталкивается с проблемой шрифта

  • Xiaomi A2 (8.0.1)
  • Пиксель XL (8.1.0)
  • Sony Xperia Z5 Au (SOV32) (6,0)
  • Стрелка NX (F-04G) (6.0.1)
  • Kyocera (S2) (7,0)

Некоторые устройства не сталкиваются с проблемой шрифтов

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

Ответ 8

Вы также можете использовать собственный виджет. Это очень просто и не загромождает ваш код Activity/Fragment.

Здесь код:

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

И ваш XML будет выглядеть так:

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

Ответ 9

используйте библиотеку каллиграфии.

то он по-прежнему не будет обновлять поля пароля правильным шрифтом. поэтому сделайте это в коде не в 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); 

Ответ 10

Я знаю, что это может быть старая InputType но я столкнулся с чем-то связанным с этой проблемой, когда я использовал InputType и app:passwordToggleEnabled="true".

Итак, пишите это, так как это может помочь кому-то здесь.

Я хочу использовать пользовательский шрифт для поля пароля вместе с опцией app:passwordToggleEnabled для моего поля ввода пароля. Но в 27.1.1 (при написании этой) библиотеки поддержки она вылетала.

Таким образом, код был как ниже,

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

Выше кода не имеют inputType определенный в XML

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

А в Java setTransformationMethod поможет мне получить свойства типа ввода textPassword а также я доволен своим собственным стилем шрифта.

Но нижеупомянутый сбой произошел на всех уровнях API с библиотекой поддержки 27.1.1.

java.lang.NullPointerException: попытка вызвать виртуальный метод 'void android.support.design.widget.CheckableImageButton.setChecked(boolean)' для ссылки на пустой объект

Это происходит сбой из-за onRestoreInstanceState внутри класса TextInputLayout.

Воспроизвести шаги. Переключите видимость пароля, сверните приложение и откройте его из последних приложений. Ой, хо Разбился!

Все, что мне нужно, это опция переключения пароля по умолчанию (с помощью библиотеки поддержки) и пользовательский шрифт в поле ввода пароля.

Через некоторое время разобрался, сделав, как показано ниже,

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

В XML добавлен 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

В приведенном выше коде Java,

Я получил пользовательскую гарнитуру от имени пользователя EditText и применил ее к TextInputLayout поля пароля. Теперь вам не нужно явно устанавливать гарнитуру для пароля EditText как он получит свойство TextInputLayout.

Также я удалил password.setTransformationMethod(new PasswordTransformationMethod());

Таким образом, passwordToggleEnabled работает, пользовательский шрифт также применяется и до свидания до сбоя. Надеюсь, что эта проблема будет исправлена в следующих выпусках поддержки.

Ответ 11

Недавно я добавил возможность изменять/отключать моноширину в режиме расширение EditText специально для паролей, это может помочь некоторым людям. Он не использует android:fontFamily, поэтому совместим < 16.

Ответ 12

Вы также можете использовать

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

вместе с

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

Ответ 13

Я использую это решение для переключения Typeface в зависимости от видимости подсказки. Он похож на ответ Джо, но вместо этого расширяет 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);
    }

}

Ответ 14

Если вы используете библиотеку каллиграфии в сочетании с TextInputLayout и EditText, следующий код работает хорошо.

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

Ответ 15

Возможно, странный случай, но я экспериментировал с этим и узнал, что:

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

изменил размер шрифта подсказки вместо самого шрифта! Это по-прежнему является нежелательным эффектом. Как ни странно, обратная операция:

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

Сохраняет одинаковый размер шрифта.

Ответ 16

Я нашел верное решение этой проблемы

Лучший способ Привет, я нашел верное решение этой проблемы

Лучший способ - создать собственный editText и сохранить значение гарнитуры как темп, а затем применить метод к изменениям InputType. Наконец, мы возвращаем значение шрифта типа temp к editText. вот так:

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

}

Ответ 17

Это как сделать пароль ввода с подсказкой, которая не была преобразована в * и шрифт по умолчанию!!.

В XML:

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

В действии:

inputPassword.setTypeface(Typeface.DEFAULT);

благодаря: mango и rjrjr для понимания: D.

Ответ 18

как и выше, но убедитесь, что у полей нет жирного стиля в xml, так как они никогда не будут выглядеть одинаково даже с вышеупомянутым исправлением!