如何将EditTextPreference用作掩码密码文本字段?

49

我有一个非常简单的问题:
我有一个EditTextPreference对话框,我想用它来获取用户的密码并且希望隐藏显示。

我应该如何做?

6个回答

116

以下是一个使用xml的简短示例:

<EditTextPreference
    android:key="@string/key"
    android:title="@string/title"
    android:summary="@string/summary"   
    android:inputType="textPassword" />

或者您可以使用 numberPassword 替代 textPassword


太棒了!我知道它应该很简单,但我没想到它会这么简单... - Avi Shukron
1
我需要一个类似的选项,但是在我的对话框首选项中,我需要3个编辑文本框,而不是单个编辑文本框。一个用于旧密码,一个用于新密码和一个用于确认密码。你能给我一个如何实现这个的示例吗?Android示例apidemo中只有一个编辑文本框首选项在对话框中。我不知道如何更改它以适应同一对话框中的3个文本框。 - Vinod
3
你应该创建一个自定义的Preference类,继承DialogPreference并带有自定义的对话框。 - inazaruk
谢谢!很高兴这么容易做到。 - Brian Reinhold
1
但是当屏幕方向变为横向时,EditText 将显示在全屏上,并且密码不会被隐藏 :( - void
但是如何安全地存储密码或密码哈希呢?代码 android:key="@string/key" 将其以明文形式存储。 - Dmitry

6

对于 androidx 库,您应该以编程方式执行它。例如,您可以按照以下方式执行它,根据密码长度,我选择使用星号设置摘要:

[...]
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;

import androidx.annotation.NonNull;

import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

import static androidx.preference.EditTextPreference.*;

public class MySettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);

        final EditTextPreference preference = findPreference("password");

        if (preference != null) {
            preference.setSummaryProvider(new SummaryProvider() {
                @Override
                public CharSequence provideSummary(Preference preference) {

                    String getPassword = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("password", "not set");

                    //we assume getPassword is not null
                    assert getPassword != null;

                    //return "not set" else return password with asterisks
                    if (getPassword.equals("not set")) {
                        return getPassword;
                    } else {
                        return (setAsterisks(getPassword.length()));
                    }
                }
            });

            //set input type as password and set summary with asterisks the new password
            preference.setOnBindEditTextListener(
                    new OnBindEditTextListener() {
                        @Override
                        public void onBindEditText(@NonNull final EditText editText) {
                            editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                            preference.setSummaryProvider(new SummaryProvider() {
                                @Override
                                public CharSequence provideSummary(Preference preference) {
                                    return setAsterisks(editText.getText().toString().length());
                                }
                            });
                        }
                    });
        }
    }

    //return the password in asterisks
    private String setAsterisks(int length) {
        StringBuilder sb = new StringBuilder();
        for (int s = 0; s < length; s++) {
            sb.append("*");
        }
        return sb.toString();
    }
}

在 XML 中,你应该有类似以下的内容:
<EditTextPreference
    android:dialogMessage="Enter your password"
    android:dialogTitle="Password"
    android:key="password"
    android:title="Password" />

更多信息请查看developer.android


当点击“确定”时,我该如何获取文本? - Conta
很好用。我已经创建了一个包含常见代码的Gist,将其分离到外部文件中: https://gist.github.com/mjfryc/3cb8518e19794dd9ba894eef3daca1d6 - Michał Jaroń

4

android:inputType="numberPassword"对我无效。Eclipse告诉我,此属性不允许使用字符串值。因此,我使用了以下内容:

<EditTextPreference
    android:key="@string/key"
    android:title="@string/title"
    android:summary="@string/summary"   
    android:inputType="number"
    android:password="true" />

这使我得到了一个带有点状文本显示和数字键盘输入的EditTextPreference。

2
对于AndroidX Preferences,请执行以下操作:
password.setOnBindEditTextListener(editText -> {
    editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
});

inputType XML属性在androidx中未被使用。


这将仅更改首选项“对话框”以编辑值。首选项摘要将保持可见,其值为纯文本。要自定义首选项摘要,请查看此处https://developer.android.com/guide/topics/ui/settings/customize-your-settings#use_a_custom_summaryprovider - Gionata

1
你可以使用下面的代码来实现。然而,我仍然没有弄清楚如何进行密码切换。仅定义 app:endIconMode="password_toggle" 无法正常工作。有人能帮忙吗?
答案是: "EditTextPreference"字段 "db_pwd" 定义如下:
android:inputType="textPassword"

最新的Kotlin代码版本:

class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    setPreferencesFromResource(com.unified.helloworld.R.xml.my_preferences, rootKey)
    val pwdPref =
        findPreference<EditTextPreference>("db_pwd")
    if (pwdPref != null) {
        pwdPref.summaryProvider = SummaryProvider<Preference?> {
            val getPassword: String =
                PreferenceManager.getDefaultSharedPreferences(context)
                    .getString("db_pwd", "Not set")!!

            // Return "Not set" else return password with asterisks
            if (getPassword == "Not set") {
                getPassword } else { setAsterisks(getPassword.length) }
        }

        // Set type as password and set summary with asterisks
        pwdPref.setOnBindEditTextListener(
            OnBindEditTextListener { editText ->
                editText.inputType =
                    InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
                pwdPref.summaryProvider = SummaryProvider<Preference> { setAsterisks(editText.text.toString().length) }
            })
    }
}

// Return the password in asterisks
private fun setAsterisks(length: Int): String {
    val sb = java.lang.StringBuilder()
    for (s in 0 until length) {
        sb.append("*") }
    return sb.toString() }
}

0
如果您希望在设备旋转后密码掩码仍然存在,只需添加以下imeOption即可:
在编辑文本布局中: android:imeOptions="flagNoExtractUi" 或者以编程方式实现: yourEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);

如何从“EditTextPreference”中访问编辑文本布局? - Dmitry
请查看EditTextPreference文档:链接 - Paolo Moschini
在 'EditTextPreference' 中无法解决方法 'setImeOptions'! - Conta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接