Android 中的密码提示字体
-
25-09-2019 - |
题
当 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" />
解决方案
在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中,还设置了字体和passwordMethod:
EditText password = (EditText) findViewById(R.id.register_password_text);
password.setTypeface(Typeface.DEFAULT);
password.setTransformationMethod(new PasswordTransformationMethod());
此方法给我的提示字体,我想,给我我想要的行为与密码点。
希望帮助!
其他提示
我发现从对话框指南
此有用的技巧提示:在默认情况下,当你设置使用“textPassword”输入型一个EditText元素,字体系列设置为等宽,所以你应该它的字体系列变更为“无衬线”,使这两个文本字段使用匹配的字体样式。
例如
android:fontFamily="sans-serif"
这是我做过什么来解决这个问题。出于某种原因,我没有设置变换方法所以这可能是更好的解决方案:
在我的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 );
在setTransformationMethod方法场所机器人:imeOption我,并允许回车被键入到密码字段。相反,我这样做:
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
setTypeface(Typeface.DEFAULT);
,我不设置机器人:密码=在XML“真”。
提供的答案MANISHA的工作,但它比默认的叶子在一个非标准的状态密码字段。也就是说,则默认fontface也适用于密码字段,包括点替换和预览字符都与该点被替换之前出现(以及当它是“可见的密码”字段)。
要解决这个问题,使之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);
}
}
然后利用它,所有你需要做的就是调用register(View)
静态方法。一切是自动(包括跳过的解决方法如果视图不需要它!):
final EditText txtPassword = (EditText) view.findViewById(R.id.txt_password);
PasswordFontfaceWatcher.register(txtPassword);
解决这个问题的方法有很多,但每种方法都有优点和缺点。这是我的测试
我只是 脸 当启用输入密码时,某些设备中存在此字体问题(在我的答案末尾列出)
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);
测试
部分设备面临字体问题
- 小米A2 (8.0.1)
- 像素XL (8.1.0)
- 索尼 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
子类,比方说,在默认情况下应用自定义的字体,有一个微妙的问题。如果你设置你的子类的构造函数中的自定义字体,它仍然会被覆盖由系统如果你设置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()));
}
}
}
您也可以使用自定义的Widget。这是非常简单的,它不会弄乱你的活动/片段代码。
下面的代码:
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" />
我知道这可能是旧的一个,但我已隆起到与当我用InputType
and 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:尝试调用虚拟方法的空隙 android.support.design.widget.CheckableImageButton.setChecked(布尔值)” 上的空对象引用
这是崩溃由于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
工作时,自定义字体也施加和再见到崩溃。希望这个问题将在即将到来的支持版本。
使用书法库。
然后它仍然不会更新与正确的字体的口令字段。所以这样做是不代码以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);
我最近添加的能力改变肘节等宽的开/关来的EditText的延伸具体的口令它可以帮助一些人。它不使用android:fontFamily
所以兼容<16。
您还可以使用
<android.support.design.widget.TextInputLayout/>
连同
<android.support.v7.widget.AppCompatEditText/>
我使用此解决方案来切换根据提示可视性的字体。它类似于乔的答案,而是延伸的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);
保持相同的字体大小。
我发现了一个肯定的解决这个问题
要喂最好的方式,我发现了一个肯定的解决这个问题。
,最好的方法是创建一个定制EDITTEXT和保存字体的值作为一个临时然后将该方法应用到所述的inputType变化,最后,我们设置背面临时型面至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);
}
}
}
此如何使具有暗示其中未转化为*和默认字体输入密码!!
在XML:
android:inputType="textPassword"
android:gravity="center"
android:ellipsize="start"
android:hint="Input Password !."
在活动:
inputPassword.setTypeface(Typeface.DEFAULT);
由于:芒果和rjrjr为洞察:d
就像上面,但要确保领域不具备XML大胆的风格,因为他们将永远看起来是一样的,甚至与上面的修复!