Android中的密码提示字体

问题描述 投票:238回答:18

当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" />
android fonts passwords android-edittext
18个回答
379
投票

更改xml中的字体对我来说也不适用于提示文本。我找到了两种不同的解决方案,其中第二种解决方案对我有更好的行为:

1)从你的xml文件中删除android:inputType="textPassword",而不是在java中设置它:

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

使用这种方法,提示字体看起来不错,但是当您在该编辑字段中键入时,在转换为密码点之前,您不会看到纯文本中的每个字符。此外,在全屏输入时,不会出现点,但密码以明文形式显示。

2)将android:inputType="textPassword"留在xml中。在Java中,ALSO设置了字体和passwordMethod:

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

这种方法给了我想要的提示字体,并通过密码点给出了我想要的行为。

希望有所帮助!


1
投票

使用calligraphy library

那么它仍然不会用正确的字体更新密码字段。所以在不在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
投票

我最近添加了将切换等宽开关切换到extension of EditText的功能,专门用于密码,它可以帮助一些人。它不使用android:fontFamily所以兼容<16。


0
投票

你也可以使用

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

和...一起

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

0
投票

我使用此解决方案根据提示可见性切换字体。它与Joe的答案类似,但改为扩展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
投票

如果您将calligraphy library与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更改。最后,我们将temp类型face的值设置为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);
        }
    }

}

-1
投票

这个如何使输入密码具有未转换为*和默认字体!!的提示。

他CML:

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

活动:

inputPassword.setTypeface(Typeface.DEFAULT);

感谢:芒果和rjrjr的见解:D。


-2
投票

像上面这样但确保字段在xml中没有粗体样式,因为即使使用上面的修复它们也看起来不一样!


188
投票

我从Dialogs Guide找到了这个有用的提示

提示:默认情况下,当您将EditText元素设置为使用“textPassword”输入类型时,字体系列将设置为等宽字体,因此您应将其字体系列更改为“sans-serif”,以便两个文本字段都使用匹配的字体样式。


例如

android:fontFamily="sans-serif"

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

21
投票

setTransformationMethod方法为我打破了android:imeOption,并允许在密码字段中输入回车符。相反,我这样做:

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

而且我没有在XML中设置android:password =“true”。


5
投票

提供的答案manisha确实有效,但与默认状态相比,它使密码字段处于非标准状态。也就是说,默认字体也适用于密码字段,包括点替换和在用点替换之前出现的预览字符(以及当它是“可见密码”字段时)。

要解决此问题并使其1)看起来和行为完全类似于默认的textPassword输入类型,而且2)允许提示文本以默认(非等宽)字体显示,你需要在字段上有一个TextWatcher可以根据Typeface.DEFAULTTypeface.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);

5
投票

有很多方法可以解决这个问题,但每种方式都有利有弊。这是我的测试

当启用输入密码时,我只在某些设备(我的答案结尾处的列表)中遇到此字体问题

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

如果我使用android:inputType="textPassword",这个问题不会发生

Something I have tried

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"

MY SOLUTION

setInputType之前缓存字体,然后重复使用它

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

测试 某些设备面临字体问题

  • ξ奥秘A2 (8.0.1)
  • Pixel XL(8.1.0)
  • 索尼Xperia Z5 Au(SOV32)(6.0)
  • Arrow NX(F-04G)(6.0.1)
  • 京瓷(S2)(7.0)

有些设备没有遇到字体问题

  • 三星S4(SC-04E)(5.0.1)
  • 三星Galaxy Note 5(5.1.1)
  • 三星S7 Edge(SM-G935F)(7.0)

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

2
投票

您还可以使用自定义窗口小部件。它非常简单,它不会使您的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" />

2
投票

我知道这可能是较旧的但是当我使用InputTypeand app:passwordToggleEnabled="true"together时,我已经讨论了与此问题相关的问题。

所以,写这个,因为它可能会帮助这里的人。

我想为我的密码输入字段使用自定义字体到密码字段以及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>

上面的代码没有在XML中定义的inputType

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

在Java中,setTransformationMethod将帮助我获取textPassword输入类型的属性,而且我很高兴我的自定义字体样式。

但是下面提到的崩溃发生在具有27.1.1支持库的所有API级别中。

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工作,自定义字体也应用和崩溃的再见。希望在即将发布的支持版本中修复此问题。

© www.soinside.com 2019 - 2024. All rights reserved.