260

When an EditText is in password mode, it seems that the hint is shown in a different font (courrier?). How can I avoid this? I would like the hint to appear in the same font that when the EditText is not in password mode.

My current xml:

<EditText 
android:hint="@string/edt_password_hint"
android:layout_width="fill_parent"
android:layout_height="wrap_content" 
android:password="true"
android:singleLine="true" />
hpique
  • 119,096
  • 131
  • 338
  • 476

18 Answers18

400

Changing the typeface in xml didn't work on the hint text for me either. I found two different solutions, the second of which has better behavior for me:

  1. Remove android:inputType="textPassword" from your xml file and instead, in set it in java:

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

With this approach, the hint font looks good but as you're typing in that edit field, you don't see each character in plain text before it turns into a password dot. Also when making input in fullscreen, the dots will not appear, but the password in clear text.

  1. Leave android:inputType="textPassword" in your xml. In Java, ALSO set the typeface and passwordMethod:

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

This approach gave me the hint font I wanted AND gives me the behavior I want with the password dots.

starball
  • 20,030
  • 7
  • 43
  • 238
manisha
  • 4,454
  • 2
  • 18
  • 10
  • 3
    Great, this is some strange behavior, you would not expect from default! – Sander Versluys Sep 27 '11 at 08:47
  • I used the standard password field type in XML and set the typeface in code. Worked great. Super annoying that this is set this way and can't overridden in XML. – profexorgeek Oct 05 '12 at 22:30
  • 15
    Is the `password.setTransformationMethod(new PasswordTransformationMethod());` necessary? Seems to work fine for me without. – loeschg Dec 14 '12 at 21:15
  • Yes worked for me too. Thanks. The `setTransformationMethod()` call is not really necessary if `android:password="true"` is defined in the xml file. – Sileria Apr 03 '13 at 13:11
  • 1
    I did not need to use the `setTransformationMethod()` either. However, there are some side-effects of this approach that make it undesirable because it results in a non-standard behavior compared to the default `textPassword` behavior. For a more complete solution, see the helper class at: http://stackoverflow.com/a/17582092/231078 – Joe Jul 10 '13 at 22:34
  • @Joe: are the side-effects when using setTransformationMethod() or without? If I don't use that method, I have the desired styling. – bplayer Feb 10 '14 at 16:29
  • This answer as a whole results in undesired behavior (see the answer linked from my comment for more information). The problem is that setting the font family impacts both the hint *and* the password bullets. My answer linked above has a solution that will override the font family while it's empty (so the hint appears in the correct style), and set it back to the monospace font when it is not empty (so the bullets appear uniform). – Joe Feb 13 '14 at 19:59
  • 10
    Better yet, look at this great simple solution in an answer right on this page: http://stackoverflow.com/a/18073897 – Marcin Koziński Apr 03 '14 at 06:55
  • 16
    Please be aware that using the first solution is a bad idea - users that have auto-suggest enabled will start seeing their password in other apps, suggested to them, because the EditText was not declared as `inputType="textPassword"` – Elad Nava Nov 24 '14 at 20:32
  • 1
    This doesn't work with AppCompat - android.support.v7.widget.AppCompatEditText :( – Bharathwaaj Jan 02 '16 at 11:16
  • Both the option works but as contradictory to comment by @loeschg if I don't set PasswordTransformation then it renders default typeface. Now if I set the TransformationMethod then Editor IME actions don't work.:( – VishalKale Nov 30 '16 at 08:04
  • Setting `inputType=textPassword` seems to have a side effect: The keyboard offers an uppercase for the first letter, `textPassword` being shorthand for `TYPE_TEXT_VARIATION_PASSWORD | TYPE_CLASS_TEXT` (128 + 1). Setting it to `TYPE_TEXT_VARIATION_PASSWORD` only prevents that. – MPelletier Sep 01 '17 at 03:41
  • With these settings, I can see the password text on top of the keyboard. – us2956 Sep 29 '17 at 08:28
  • Don't remove android:inputType="textPassword" in first solution, use android:inputType="textVisiblePassword" instead, it will fix issues with non-default behavior and will disable text suggestions – Pavlo28 Mar 26 '19 at 17:44
197

I found this useful tip from Dialogs Guide

Tip: By default, when you set an EditText element to use the "textPassword" input type, the font family is set to monospace, so you should change its font family to "sans-serif" so that both text fields use a matching font style.


For example

android:fontFamily="sans-serif"
aysonje
  • 2,595
  • 1
  • 14
  • 16
32

This is what I did to fix this problem. For some reason I didn't have to set the transformation method so this may be a better solution:

In my xml:

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

In my Activity:

EditText password = (EditText) findViewById( R.id.password_edit_field );
password.setTypeface( Typeface.DEFAULT );
Akram
  • 7,548
  • 8
  • 45
  • 72
James McCracken
  • 15,488
  • 5
  • 54
  • 62
  • I just tried it with textPassword in XML and as you were doing in the .java file, and it worked just fine. For me, it didn't seem to need the transformation – Joe Plante Sep 21 '12 at 13:43
  • 2
    Reminder: Call setTypeface() AFTER you change the InputType by code. setTransformationMethod not needed if InputType include xx_VARIATION_PASSWORD; – Loda Jun 25 '13 at 10:51
22

The setTransformationMethod approach breaks android:imeOption for me, and allows carriage returns to be typed into the password field. Instead I'm doing this:

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

And am not setting android:password="true" in XML.

rjrjr
  • 3,892
  • 1
  • 22
  • 18
5

The answer manisha provided does work, but it leaves the password field in a nonstandard state compared to the default. That is, the default fontface then applies also to the password field, including both the dot replacements and the preview characters that appears before being replaced with the dots (as well as when it is a "visible password" field).

To fix this and make it 1) look and act exactly like the default textPassword input type, but also 2) allow the hint text to appear in a default (non-monospace) font, you need to have a TextWatcher on the field that can toggle the fontface properly back and forth between Typeface.DEFAULT and Typeface.MONOSPACE based on whether it is empty or not. I created a helper class that can be used to accomplish that:

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

Then to make use of it, all you need to do is call the register(View) static method. Everything else is automatic (including skipping the workaround if the view does not require it!):

    final EditText txtPassword = (EditText) view.findViewById(R.id.txt_password);
    PasswordFontfaceWatcher.register(txtPassword);
Joe
  • 42,036
  • 13
  • 45
  • 61
  • 1
    Nice work. One small change: if you set a font on the `EditText` (e.g. making the hint text Roboto Light), then setting `Typeface.DEFAULT` later will override this. I call `field.getTypeface()` up front and use that typeface whenever I need to reset to the "default" font later. – Christopher Orr Sep 28 '13 at 22:35
  • Well, calling `field.getTypeface()` doesn't seem to be 100% reliable (as often you'll just get back the monospace font), but creating a Typeface via `Typeface.create()` and then setting that seems to work well. – Christopher Orr Sep 29 '13 at 00:03
5

There are many way for solving this problem but each way have pros and cons. Here is my testing

I only face this font problem in some device (list at the end of my answer) when enable input password by

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

If I use android:inputType="textPassword", this problem don't happened

Something I have tried

1) Use setTransformationMethod instead inputType

edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
  • Font will working well
  • Keyboard display not very well (it only display text, don't display number on top of text)

2) Use Typeface.DEFAULT

setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
  • Keyboard display well,
  • Font may working not well. Example sans-serif-light is a default font for all View in my application => after setTypeface(Typeface.DEFAULT), the EditText font still look different in some device

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

MY SOLUTION

cache the typeface before setInputType then reuse it

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

Testing
Some device face font problem

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

Some device not face font problem

  • Samsung S4 (SC-04E) (5.0.1)
  • Samsung Galaxy Node 5 (5.1.1)
  • Samsung S7 Edge (SM-G935F) (7.0)
Linh
  • 57,942
  • 23
  • 262
  • 279
  • What is the device (name and OS)? – CoolMind Sep 20 '18 at 07:55
  • 1
    @CoolMind thank you for your suggestion, I have update device face font problem and device not face font problem base on my current device – Linh Sep 20 '18 at 09:09
  • Thank you for a large testing! I came her from https://stackoverflow.com/a/52178340/2914140. On Samsung S4 I used `setTransformationMethod` method (where not faced a problem). – CoolMind Sep 20 '18 at 09:35
  • As I mention in my answer, `setTransformationMethod` will working but keyboard will not display well. However, if you oke with it, it still oke because it just a small problem – Linh Sep 20 '18 at 09:36
4

The other answers are the right solution for most cases.

However, if you're using a custom EditText subclass to, say, apply a custom font by default, there's a subtle issue. If you set the custom font in the constructor of your subclass, it will still be overwritten by the system if you set inputType="textPassword".

In this case, move your styling to onAttachedToWindow after your super.onAttachedToWindow call.

Example implementation:

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()));
        }
    }
}
Cory Petosky
  • 12,458
  • 3
  • 39
  • 44
3

I know this may be the older one but I have humped into something related to this issue when I used InputTypeand app:passwordToggleEnabled="true"together.

So, writing this, as it may help someone over here.

I want to use a custom font to password field along with app:passwordToggleEnabled option for my password input field. But in 27.1.1 (while writing this) support library, it was crashing.

So the code was like below,

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

Above code do not have inputType defined in XML

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

And in Java, setTransformationMethod will help me acquire the properties of textPassword input type and also I'm happy my custom font style.

But the below-mentioned crash happened in all API levels with 27.1.1 support library.

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.design.widget.CheckableImageButton.setChecked(boolean)' on a null object reference

This was crashing due to the onRestoreInstanceState inside TextInputLayout class.

Reproduce Steps: Toggle the password visibility and minimize the app and open from the recent apps. Uh,ho Crashed!

All I needed is default password toggle option (using support library) and custom font in the password input field.

After some time, figured out by doing as below,

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

In XML, added 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

In above java code,

I acquired the custom typeface from username EditText and applied it to TextInputLayout of the password field. Now you don't need to set the typeface explicitly to the password EditText as it will acquire the TextInputLayout property.

Also, I removed password.setTransformationMethod(new PasswordTransformationMethod());

By doing this way, passwordToggleEnabled is working, the custom font is also applied and bye-bye to the crash. Hope this issue will be fixed in upcoming support releases.

Kavin Prabhu
  • 2,307
  • 2
  • 17
  • 36
2

You can also use a custom Widget. It's very simple and it doesn't clutter your Activity/Fragment code.

Here's the code:

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

And your XML will look like this:

<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
  • 547
  • 4
  • 11
  • In my experience this doesn't work -- internally `TextView` seems to overwrite the custom typeface after the constructor call. Provided a workaround in another answer. – Cory Petosky Feb 26 '15 at 20:08
2

use the calligraphy library.

then it still wont update the password fields with the right font. so do this in code not in 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
  • 60,549
  • 65
  • 286
  • 456
0

I recently added the ability to change toggle monospace on/off to a extension of EditText specifically for passwords it may help some people. It doesn't use android:fontFamily so is compatible <16.

scottyab
  • 23,621
  • 16
  • 94
  • 105
0

You can also use the

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

together with

<android.support.v7.widget.AppCompatEditText/>
DoruChidean
  • 7,941
  • 1
  • 29
  • 33
0

I use this solution to toggle the Typeface depending on hint visibility. It's similar to Joe's answer, but extending EditText instead:

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
  • 2,115
  • 23
  • 21
0

In case you are using the calligraphy library in combination with a TextInputLayout and an EditText, the following code works well.

    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
  • 312
  • 2
  • 11
0

A weird case perhaps, but I have experimented with this and found out that:

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

changed the size of the font of the hint instead of the font itself! This is still an undesired effect. Strangely enough, the reverse operation:

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

Keeps the same font size.

MPelletier
  • 16,256
  • 15
  • 86
  • 137
0

I found a sure solution to this problem

Best way to Hello ,I found a sure solution to this problem

The best way is to create a custom editText and save value of typeface as a temp and then apply the method to the InputType changes , Finally, we set back the value of temp type face to the editText. like so :

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

}
smarteist
  • 1,331
  • 12
  • 15
-1

This how to make input password that has hint which not converted to * and default typeface !!.

On XML :

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

On Activity :

inputPassword.setTypeface(Typeface.DEFAULT);

thanks to : mango and rjrjr for the insight :D.

Bhimbim
  • 1,348
  • 2
  • 19
  • 15
-2

like the above but make sure the fields do not have the bold style in xml as they will never look the same even with the above fix!

Dori
  • 18,283
  • 17
  • 74
  • 116