Android中的密码提示字体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3406534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:03:49  来源:igfitidea点击:

Password hint font in Android

androidfontspasswordsandroid-edittext

提问by hpique

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.

当 EditText 处于密码模式时,提示似乎以不同的字体(信使?)显示。我怎样才能避免这种情况?我希望提示以与 EditText 未处于密码模式时相同的字体显示。

My current xml:

我当前的 xml:

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

回答by manisha

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:

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

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

1)android:inputType="textPassword"从您的xml文件中删除,而是在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.

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

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

2)留android:inputType="textPassword"在你的xml中。在 Java 中,还可以设置字体和密码方法:

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.

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

Hope that helps!

希望有帮助!

回答by aysonje

I found this useful tip from Dialogs Guide

我从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.

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



For example

例如

android:fontFamily="sans-serif"

回答by James McCracken

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:

在我的 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:

在我的Activity

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

回答by rjrjr

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

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

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

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

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

回答by Joe

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

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

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

要解决此问题并使其 1) 外观和行为与默认textPassword输入类型完全相同,但 2) 允许提示文本以默认(非等宽)字体显示,您需要TextWatcher在字段上有一个可以切换fontface正确来回之间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);
    }
}

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!):

然后要使用它,您需要做的就是调用register(View)静态方法。其他一切都是自动的(包括跳过解决方法,如果视图不需要它!):

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

回答by Phan Van Linh

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

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

I only facethis 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

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

Something I have tried

我尝试过的东西

1) Use setTransformationMethodinstead inputType

1)setTransformationMethod改用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

2) 使用 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-lightis a default font for all Viewin my application => after setTypeface(Typeface.DEFAULT), the EditTextfont still look differentin some device
  • 键盘显示很好
  • 字体可能无法正常工作。示例sans-serif-lightView我的应用程序中所有人的默认字体=> 之后setTypeface(Typeface.DEFAULT)EditText字体在某些设备中看起来仍然不同

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

3) 使用 android:fontFamily="sans-serif"

MY SOLUTION

我的解决方案

cache the typeface before setInputTypethen reuse it

setInputType重用之前缓存字体

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)
  • 小米 A2 (8.0.1)
  • 像素 XL (8.1.0)
  • 索尼 Xperia Z5 Au (SOV32) (6.0)
  • Arrow NX (F-04G) (6.0.1)
  • 京瓷 (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)
  • 三星 S4 (SC-04E) (5.0.1)
  • 三星 Galaxy Node 5 (5.1.1)
  • 三星 S7 Edge (SM-G935F) (7.0)

回答by Cory Petosky

The other answers are the right solution for most cases.

其他答案是大多数情况下的正确解决方案。

However, if you're using a custom EditTextsubclass 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".

但是,如果您使用自定义EditText子类来默认应用自定义字体,则存在一个微妙的问题。如果您在子类的构造函数中设置自定义字体,如果您设置inputType="textPassword".

In this case, move your styling to onAttachedToWindowafter your super.onAttachedToWindowcall.

在这种情况下,移动你的造型给onAttachedToWindow你后super.onAttachedToWindow调用。

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

回答by Kavin Prabhu

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.

我知道这可能是旧的一个,但我已隆起到当我用与此问题有关的东西InputTypeapp:passwordToggleEnabled="true"在一起。

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

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

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

我想对密码字段使用自定义字体以及app:passwordToggleEnabled密码输入字段的选项。但是在 27.1.1(在编写本文时)支持库中,它崩溃了。

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 inputTypedefined in XML

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

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

And in Java, setTransformationMethodwill help me acquire the properties of textPasswordinput type and also I'm happy my custom font style.

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

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

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

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

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void android.support.design.widget.CheckableImageButton.setChecked(boolean)”

This was crashing due to the onRestoreInstanceStateinside TextInputLayoutclass.

这是由于onRestoreInstanceState内部TextInputLayout课程而崩溃 。

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"

在 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

In above java code,

在上面的java代码中,

I acquired the custom typeface from username EditTextand applied it to TextInputLayoutof the password field. Now you don't need to set the typeface explicitly to the password EditTextas it will acquire the TextInputLayoutproperty.

我从用户名中获取了自定义字体EditText并将其应用于TextInputLayout密码字段。现在您不需要将字体显式设置为密码EditText,因为它将获得TextInputLayout属性。

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

另外,我删除了 password.setTransformationMethod(new PasswordTransformationMethod());

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

通过这样做,passwordToggleEnabled工作正常,自定义字体也被应用,再见崩溃。希望此问题将在即将发布的支持版本中得到解决。

回答by j2emanue

use the calligraphy library.

使用书法图书馆

then it still wont update the password fields with the right font. so do this in code not in xml:

那么它仍然不会用正确的字体更新密码字段。所以在代码中而不是在 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); 

回答by Aldo Borrero

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

您还可以使用自定义小部件。它非常简单,不会使您的 Activity/Fragment 代码混乱。

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:

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