Android中的密码提示字体

当EditText处于密码模式时,提示似乎以不同的字体显示(courier ?)我该如何避免这种情况?我想提示出现在相同的字体,当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" />
70247 次浏览

改变xml中的字体对我的提示文本也不起作用。我找到了两种不同的解决方案,其中第二种对我来说表现更好:

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

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

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

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

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

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

希望有帮助!

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

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

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

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

这就是我解决这个问题的方法。由于某些原因,我不需要设置转换方法,所以这可能是一个更好的解决方案:

在我的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 );

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

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

我从对话框向导中找到了这个有用的技巧

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


例如

android:fontFamily="sans-serif"

这是如何使输入密码有提示,不转换为*和默认字体!!

关于XML:

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

活动介绍:

inputPassword.setTypeface(Typeface.DEFAULT);

感谢芒果和rjjr的洞察力:D。

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

然而,如果你正在使用自定义EditText子类,比如说,在默认情况下应用自定义字体,就会有一个微妙的问题。如果你在子类的构造函数中设置了自定义字体,如果你设置了inputType="textPassword",它仍然会被系统覆盖。

在这种情况下,在调用super.onAttachedToWindow后将样式移到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()));
}
}
}

我最近添加了一种能力,可以专门为密码更改切换单空格开关到EditText扩展,这可能会帮助一些人。它不使用android:fontFamily,所以是兼容的<16。

你也可以使用

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

在一起

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

使用书法图书馆

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

我使用这个解决方案来切换字体取决于提示可见性。它与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);
}


}

如果你将书法图书馆与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);

也许是一个奇怪的例子,但我已经做过实验,并发现:

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

改变了提示的字体大小而不是字体本身!这仍然是一种不受欢迎的效果。奇怪的是,相反的操作:

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

保持相同的字体大小。

我知道这可能是较老的一个,但当我一起使用__abc0和__abc1时,我遇到了与此问题相关的问题。

写这个,可能会对在座的人有所帮助。

我想使用自定义字体密码字段和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级别上。

< p > . lang。尝试调用虚方法void android.support.design.widget.CheckableImageButton.setChecked(布尔) 在空对象引用

这是由于TextInputLayout类中的onRestoreInstanceState导致的崩溃。

重现步骤:切换密码可见性和最小化应用程序,并从最近的应用程序打开。呃,何鸿燊坠毁!

我所需要的是默认密码切换选项(使用支持库)和自定义字体在密码输入字段。

过了一段时间后,通过如下方法计算出,

<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正在工作,自定义字体也被应用,并与崩溃说拜拜。希望这个问题将在即将发布的支持版本中得到解决。

解决这个问题有很多方法,但每种方法都有优缺点。下面是我的测试

我只有这个字体问题在某些设备(列表在我的答案的末尾)时启用输入密码由

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

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

我曾经尝试过

1)使用setTransformationMethod代替inputType

edtPassword.setTransformationMethod(PasswordTransformationMethod.getInstance());
  • Font将工作得很好
  • 键盘显示不太好(它只显示文本,不显示文本顶部的数字)

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"

我的解决方案

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

Typeface cache = edtPassword.getTypeface();
edtPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
edtPassword.setTypeface(cache);
< p > 测试 < br > 某些设备遇到字体问题

  • 小米A2 (8.0.1)
  • Pixel XL (8.1.0)
  • Sony Xperia Z5 Au (SOV32) (6.0)
  • 箭NX (F-04G) (6.0.1)
  • 京瓷(S2) (7.0)

一些设备不面临字体问题

  • 三星S4 (SC-04E) (5.0.1)
  • 三星Galaxy Node 5 (5.1.1)
  • 三星S7 Edge (SM-G935F) (7.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);
}
}


}