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


255

Коли EditText знаходиться в режимі пароля, здається, що підказка відображається іншим шрифтом (кур'єр?). Як я можу цього уникнути? Я хотів би, щоб підказка відображалася тим самим шрифтом, що коли 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
Зауважте, що не всі пристрої поводяться таким чином. "HTC One X @ 4.1.1" робить (монопростір). "Samsung GT-7510 @ 4.0.4" цього немає. (той самий шрифт)
Loda

1
Така ж поведінка в LeWa OS 4.2.2. Занадто непослідовно API ..
ruX

Досі існує у льодяника
Магтіан

Ви можете перевірити мою відповідь тут, сподіваюся, що це працює.
Дміла Рам

Відповіді:


394

Зміна шрифту в xml також не працювала для тексту підказки. Я знайшов два різні рішення, друге з яких має кращу поведінку для мене:

1) Вийміть android:inputType="textPassword"із свого файлу xml і замість цього встановіть його у java:

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

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

2) Залиште android:inputType="textPassword"у своєму xml. В ЯВІ ТАКОЖ встановіть шрифт і парольMethod:

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

Такий підхід дав мені підказку, яку я хотів, і надає мені поведінку, яку я хочу з крапками пароля.

Сподіваюся, що це допомагає!


3
Чудово, це якась дивна поведінка, якої ви не очікували б від дефолту!
Сандер Верслуйс

15
Чи password.setTransformationMethod(new PasswordTransformationMethod());потрібне? Здається, для мене це чудово працює.
loeschg

1
Мені теж не потрібно було користуватися setTransformationMethod(). Однак є деякі побічні ефекти такого підходу, які роблять його небажаним, оскільки це призводить до нестандартної поведінки порівняно з textPasswordповедінкою за замовчуванням . Для більш повного рішення дивіться клас помічників за адресою: stackoverflow.com/a/17582092/231078
Джо

10
Ще краще, подивіться на це чудове просте рішення у відповіді прямо на цій сторінці: stackoverflow.com/a/18073897
Marcin Koziński,

16
Зауважте, що використання першого рішення - це погана ідея - користувачі, які ввімкнули автоматичну пропозицію, почнуть бачити свій пароль в інших програмах, запропонованих їм, оскільки EditText не був оголошений якinputType="textPassword"
Elad Nava

193

Я знайшов цю корисну пораду з Посібника з діалогів

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


Наприклад

android:fontFamily="sans-serif"

21
Це має бути прийнятою відповіддю. Це простіше, і це з документів.
Marcin Koziński

29
Це добре, за винятком того, що він працює лише на рівні API 16 і вище
Бен Клейтон

6
Зауважте, що хоча він працює лише на рівні API 16 і вище, атрибути xml не викликають збоїв на старих пристроях, їх просто ігнорують.
Адам Джонс

Це не спрацює, якщо кілька разів натиснути показ / приховування пароля
Алі Хаббаш

32

Це я зробив, щоб виправити цю проблему. Чомусь мені не довелося встановлювати метод перетворення, щоб це було кращим рішенням:

У моєму 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 );

Я просто спробував це з textPassword в XML, і як ви це робили у файлі .java, і він працював чудово. Мені, здавалося, не потрібна трансформація
Джо Плант

2
Нагадування: Call setTypeface () ПІСЛЯ ви змінюєте InputType за кодом. setTransformationMethod не потрібен, якщо InputType включає xx_VARIATION_PASSWORD;
Лода

21

Підхід setTransformationMethod розбиває для мене android: imeOption, і дозволяє повернення каретки вводити в поле пароля. Натомість я роблю це:

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

І я не встановлюю android: password = "true" у XML.


так, для мене це спрацювало і в 6.0.1, вибрана відповідь не стала
Накт

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

Потім, щоб скористатися ним, все, що вам потрібно зробити, - це викликати register(View)статичний метод. Все інше є автоматичним (включаючи пропуск обхідного рішення, якщо перегляд цього не вимагає!):

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

1
Хороша робота. Одна невелика зміна: якщо встановити шрифт на EditText(наприклад, зробити текст підказки Roboto Light), то налаштування Typeface.DEFAULTпізніше це змінить. Я закликаю field.getTypeface()фронт і використовую цей шрифт, коли мені потрібно пізніше скинути шрифт "за замовчуванням".
Крістофер Орр

Ну, виклик field.getTypeface()не здається надійним на 100% (як часто ви просто повернете шрифт монопространства), але створити Typeface через, Typeface.create()а потім встановити налаштування, яке, здається, працює добре.
Крістофер Орр

5

Існує багато способів вирішити цю проблему, але кожен спосіб має свої плюси і мінуси. Ось моє тестування

Я зіткнувся з цією проблемою шрифту лише на якомусь пристрої (список наприкінці моєї відповіді), коли ввімкнути пароль введення

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"

  • Для якогось пристрою він буде ДРУГОМ , перевірити мою відповідь тут https://stackoverflow.com/a/52421199/5381331 . А також шрифт все ще виглядає інакше

МОЕ РІШЕННЯ

кешуйте шрифт перед тим, як 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)
  • Кіоцера (S2) (7.0)

Деякі пристрої не стикаються з проблемою шрифту

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

Що таке пристрій (ім’я та ОС)?
CoolMind

1
@CoolMind дякую за вашу пропозицію. У мене на поточному пристрої оновлено проблему з шрифтом обличчя пристрою, і пристрій не стикається з базою проблеми шрифту
Phan Van Linh

Дякую за велике тестування! Я прийшов до неї з stackoverflow.com/a/52178340/2914140 . На Samsung S4 я використовував setTransformationMethodметод (де не стикався з проблемою).
CoolMind

Як я згадую у своїй відповіді, setTransformationMethodбуде працювати, але клавіатура не відображатиметься добре. Однак, якщо ви з цим погоджуєтеся, це все одно має місце, тому що це лише невелика проблема
Фан Ван Лін

4

Інші відповіді є правильним рішенням у більшості випадків.

Однак якщо ви використовуєте спеціальний 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 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

Я знаю, що це може бути і старше, але я намагався вирішити щось, що стосується цього питання, коли я використовував 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працює, спеціальний шрифт також застосовується і до побачення до аварії. Сподіваємось, це питання буде вирішено у майбутніх випусках підтримки.


2

Ви також можете скористатися користувацьким віджетом. Це дуже просто, і це не захаращує ваш код діяльності / фрагмента.

Ось код:

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

На мій досвід, це не працює - внутрішнє TextViewздається, що замінить спеціальний шрифт після виклику конструктора. Наведено вирішення в іншій відповіді.
Cory Petosky

2

використовувати бібліотеку каліграфії .

тоді він все ще не буде оновити поля паролів правильним шрифтом. тому робіть це в коді не в 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

Ви також можете використовувати

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

разом з

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

0

Я використовую це рішення для перемикання 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);
    }

}

0

Якщо ви використовуєте бібліотеку каліграфії у поєднанні з 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);

Це не змінило мого натякового шрифту
Рафаель Руїз Муньоз

0

Дивний випадок, можливо, але я експериментував з цим і з'ясував, що:

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

змінив розмір шрифту підказки замість самого шрифту! Це все-таки небажаний ефект. Як не дивно, зворотна операція:

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

Зберігає однаковий розмір шрифту.


0

Я знайшов надійне рішення цієї проблеми

Найкращий спосіб привіт, я знайшов вірне рішення цієї проблеми

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

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

Це як зробити вхідний пароль, який має підказку, яка не перетворена на * і за замовчуванням шрифт !!.

У XML:

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

Про активність:

inputPassword.setTypeface(Typeface.DEFAULT);

дякую: манго та rjrjr за розуміння: D.


-2

як зазначено вище, але переконайтеся, що поля не мають жирного стилю у форматі xml, оскільки вони ніколи не будуть виглядати однаково навіть із наведеним вище виправленням!


2
Не кажіть "вище" ... з часом все змінюється :-)
ZaBlanc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.