51 votes

PreferenceActivity: enregistrer la valeur en tant qu'entier

Utiliser un simple EditTextPreference dans mon activité de préférences :

Y a-t-il un moyen pour que cette valeur de configuration soit enregistrée en tant qu'entier ? Il semble que pour le moment, il permet juste de saisir des nombres, mais la valeur est toujours enregistrée en tant que chaîne de caractères :

Appel :

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = preferences.getInt("SomeKey", -1);

me renvoie une java.lang.ClassCastException: java.lang.String, et :

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String value = preferences.getString("SomeKey", "-1");

récupère la valeur avec succès.

Comment faire en sorte que PreferenceActivity enregistre la valeur en tant qu'entier par défaut ?

71voto

broot Points 2295

Vous pourriez étendre EditTextPreference :

public class IntEditTextPreference extends EditTextPreference {

    public IntEditTextPreference(Context context) {
        super(context);
    }

    public IntEditTextPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public IntEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected String getPersistedString(String defaultReturnValue) {
        return String.valueOf(getPersistedInt(-1));
    }

    @Override
    protected boolean persistString(String value) {
        return persistInt(Integer.valueOf(value));
    }
}

Il serait préférable de remplacer les méthodes onSetInitialValue() et setText(), mais vous devriez alors copier du code d'une classe de base. La solution ci-dessus est plus simple, mais elle est assez délicate - les méthodes "string" font quelque chose avec des entiers. Essayez de ne pas étendre davantage cette classe ;-)

Vous pourriez l'utiliser depuis XML en :

0 votes

@Brutall, je voudrais te remercier d'avoir amélioré le code. Mais quelqu'un m'a dit que le nouveau code est... trop long, et qu'il l'a rejeté. Oh, mais que font les gens si l'ancien code est mauvais, et doit être remplacé, mais ils ne le font pas parce que le nouveau est... long? Même s'il est meilleur. Oh mon Dieu, c'est SUPER! C'est l'endroit pour les programmeurs? J'ai quelques projets open source, et je suis ouvert à tout changement dans mon code. Quelle honte pour lui! Quoi qu'il en soit, merci beaucoup, Brutall.

0 votes

Au fait, tout ce que je fais c'est : définir le type d'entrée sur nombre ; ajouter un TextWatcher, pour m'assurer que le texte que l'utilisateur entre n'est pas vide, et la valeur par défaut est 0.

3 votes

Je reçois une erreur d'exécution sur return String.valueOf(getPersistedInt(-1));, impossible de démarrer l'activité à cause de cette ligne.

6voto

broot Points 2295

Même si vous définissez android:numérique="entier", ce sera une préférence de texte - comme son nom l'indique. Vous pouvez facilement convertir une valeur de chaîne en entier en utilisant Integer.valueOf(). Vous pourriez également écraser PreferenceActivity pour effectuer la conversion automatiquement à la sortie.


Je pense que la meilleure solution est d'écrire une méthode simple pour obtenir cette valeur des préférences. Quelque chose comme :

public static int getSomePref(Context context) {
    SharedPreferences prefs =
        PreferenceManager.getDefaultSharedPreferences(context);
    String value = prefs.getString("SomeKey", null);
    return value == null ? -1 : Integer.valueOf(value);
}

Ensuite, vous pourriez très facilement l'utiliser dans votre code.

0 votes

Où puis-je remplacer cela? Par défaut PreferenceActivity enregistre automatiquement, dois-je remplacer une méthode pour obtenir la valeur ou tout enregistrer moi-même à la place?

0 votes

D'accord, changer le type de préférence n'est pas bon, car vous pourriez rencontrer des problèmes de ClassCastException. J'ai mis à jour ma réponse.

0 votes

Oui, j'ai pensé à wrapper moi-même, mais je n'aime toujours pas vraiment cette solution... SharedPreferences a déjà une méthode getInt, donc j'espère toujours trouver un moyen de dire à PreferenceActivity de sauvegarder la valeur en tant qu'entier - toute la fonctionnalité est là... cela ne fonctionne tout simplement pas comme souhaité...

3voto

Arnab Jain Points 247

Même si une réponse a déjà été acceptée, je tiens à partager une manière plus courte d'y parvenir :

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = Integer.parseInt(preferences.getString("SomeKey", "-1"));

Comme vous avez déjà défini que seuls des nombres peuvent être saisis, cela ne provoquera aucune exception. Il reste à compléter ma réponse :

3voto

Iogui Points 341

Je sais que c'est une vieille question avec une réponse déjà acceptée mais je pense que ma solution peut être utile pour quelqu'un cherchant une réponse plus complète. J'ai juste amélioré la réponse de @broot un peu et voici ma solution :

Remplacez EditTextPreference pour fournir une conversion de texte en int :

public class IntEditTextPreference extends EditTextPreference implements EditTextPreference.OnBindEditTextListener {
    private String mText;

    public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setOnBindEditTextListener(this);
    }

    public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setOnBindEditTextListener(this);
    }

    public IntEditTextPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnBindEditTextListener(this);
    }

    public IntEditTextPreference(Context context) {
        super(context);
        setOnBindEditTextListener(this);
    }

    /**
     * Enregistre le texte dans le stockage de données actuel.
     *
     * @param text Le texte à enregistrer
     */
    public void setText(String text) {
        final boolean wasBlocking = shouldDisableDependents();

        mText = text;

        int value = Integer.parseInt(text);

        persistInt(value);

        final boolean isBlocking = shouldDisableDependents();
        if (isBlocking != wasBlocking) {
            notifyDependencyChange(isBlocking);
        }

        notifyChanged();
    }

    /**
     * Récupère le texte à partir du stockage de données actuel.
     *
     * @return La valeur de préférence actuelle
     */
    public String getText() {
        return mText;
    }

    @Override
    protected void onSetInitialValue(Object defaultValue) {
        int value;
        if (defaultValue != null) {
            String strDefaultValue = (String) defaultValue;

            int defaultIntValue = Integer.parseInt(strDefaultValue);
            value = getPersistedInt(defaultIntValue);
        } else {
            value = getPersistedInt(0);
        }

        setText(Integer.toString(value));
    }

    @Override
    public boolean shouldDisableDependents() {
        return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
    }

    @Override
    public void onBindEditText(@NonNull EditText editText) {
        editText.setInputType(InputType.TYPE_CLASS_NUMBER);
    }
}

Dans le fichier de préférences xml :

Remarque : Ne pas utiliser android:numérique ni android:inputType. Comme EditTextPreference n'est pas un EditText lui-même, définir ces attributs ne fera rien. Pour obtenir l'effet souhaité sur l'EditText de la boîte de dialogue ouverte par EditTextPreference, définissez simplement le type d'entrée dans votre custom EditTextPreference en implémentant EditTextPreference.OnBindEditTextListener comme vous pouvez le voir dans le code ci-dessus.

C'est ce qui a fonctionné pour moi.

0voto

cartok Points 9

J'avais le même problème. (Je voulais que SharedPreferences me donne un numéro de port que j'avais stocké dans un fichier xml de préférences comme valeur par défaut).

Implémenter toutes les méthodes de SharedPreferences demanderait beaucoup d'efforts, donc écrire une méthode personnalisée dans la classe qui a instancié les SharedPreferences, comme broot l'a suggéré, serait selon moi la meilleure solution.

Vous pouvez également simplement utiliser la méthode statique d'Integer à la ligne où vous en avez besoin:

int number = Integer.valueOf(settings.getString("myNumberString", "0"));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X