web-dev-qa-db-fra.com

Comment remplir ListPreference dynamiquement lorsque onPreferenceClick est déclenché?

J'ai une activité de préférence qui a un language comme ListPreference qui affiche la liste des langues disponibles. Je peux remplir la liste lorsque onCreate est appelé, mais je veux remplir la liste lorsque l'utilisateur clique dessus.

this is the Java code:

public class SettingsActivity extends PreferenceActivity implements OnPreferenceClickListener {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

    }

    @Override
    public boolean onPreferenceClick(Preference preference) {

        if((preference instanceof ListPreference) && (preference.getKey().equals("language"))){
            ListPreference lp = (ListPreference)preference;
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
            return true;
        }
        return false;

    }
}

et c'est le settings.xml (préférence) :

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
  xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <PreferenceCategory Android:title="General Settings">
        <CheckBoxPreference Android:key="enabled"  Android:title="Application Status" Android:summary="Enable or disable the application" />
         <ListPreference 
         Android:key="language" 
         Android:title="Language"
         Android:dialogTitle="Application language" 
         Android:summary="Select the Application language"
         />
    </PreferenceCategory>
</PreferenceScreen>

J'ai cherché mais je n'ai trouvé aucun résultat! Une exception se produit chaque fois que je clique sur cette liste.

30
Abdullah

Vous obtenez l'exception parce que votre objet ListPreference n'est pas initialisé - vous devez soit définir les attributs entries et entryValues dans votre XML, soit le faire par programme dans onCreate().

Si vous voulez pouvoir modifier dynamiquement les éléments de la liste après l'initialisation de l'objet ListPreference initial, vous devrez attacher le OnPreferenceClickListener directement à l'objet ListPreference. Utilisez la clé que vous avez spécifiée dans le XML pour obtenir un descripteur de la préférence.

Étant donné que le code pour remplir les tableaux entries et entryValues devra être exécuté à la fois dans onCreate() et dans onPreferenceClick, il est logique de l'extraire dans une méthode distincte - setListPreferenceData() afin d'éviter la duplication.

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            addPreferencesFromResource(R.xml.settings);
        } catch (Exception e) {

        }

        final ListPreference listPreference = (ListPreference) findPreference("language");

        // THIS IS REQUIRED IF YOU DON'T HAVE 'entries' and 'entryValues' in your XML
        setListPreferenceData(listPreference);

        listPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(listPreference);
                return false;
            }
        });
    }

    protected static void setListPreferenceData(ListPreference lp) {
            CharSequence[] entries = { "English", "French" };
            CharSequence[] entryValues = {"1" , "2"};
            lp.setEntries(entries);
            lp.setDefaultValue("1");
            lp.setEntryValues(entryValues);
    }
}

Ici est un autre exemple de l'application DeskClock de Google:

49
ccpizza

Utilisation de PreferenceFragment & Java set key plutôt que PréférenceActivité et XML comme indiqué dans https://stackoverflow.com/a/13828912/1815624 , sur lequel cette réponse est basée:

Si vous voulez pouvoir modifier dynamiquement les éléments de la liste après l'initialisation de l'objet ListPreference initial, vous devrez attacher le OnPreferenceClickListener directement à l'objet ListPreference. Utilisez la clé que vous avez spécifiée dans le Java (comme CUSTOM_LIST) Pour obtenir un handle à la préférence.

Étant donné que le code pour remplir les tableaux entries et entryValues devra s'exécuter à la fois dans onCreate() et dans onPreferenceClick, il est logique de l'extraire dans un méthode séparée - setListPreferenceData() afin d'éviter la duplication.

/**
 * This fragment shows data and sync preferences only. It is used when the
 * activity is showing a two-pane settings UI.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class myCustomPreferenceFragment extends PreferenceFragment {

    final private String CUSTOM_LIST= "custom_list";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref_custom_frag);

        PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");

        final ListPreference lp = setListPreferenceData((ListPreference) findPreference(CUSTOM_LIST), getActivity());

        lp.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {

                setListPreferenceData(lp, getActivity());
                return false;
            }
        });
        setHasOptionsMenu(true);
        targetCategory.addPreference(lp);

        bindPreferenceSummaryToValue(targetCategory);
        bindPreferenceSummaryToValue(lp);
    }

    protected ListPreference setListPreferenceData(ListPreference lp, Activity mActivity) {
        CharSequence[] entries = { "One", "Two", "Three" };
        CharSequence[] entryValues = { "1", "2", "3" };
        if(lp == null)
            lp = new ListPreference(mActivity);
        lp.setEntries(entries);
        lp.setDefaultValue("1");
        lp.setEntryValues(entryValues);
        lp.setTitle("Number Of blahs");
        lp.setSummary(lp.getEntry());
        lp.setDialogTitle("Number of Blah objects");
        lp.setKey(CUSTOM_LIST);
        return lp;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == Android.R.id.home) {
            startActivity(new Intent(getActivity(), SettingsActivity.class));
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Disposition XML:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <PreferenceCategory
        Android:key="CUSTOM_FRAG"
        Android:title="Some Options">

    </PreferenceCategory>
</PreferenceScreen>
6
CrandellWS

J'ai résolu le problème en étendant ListPreference. C'était très simple.

public class DListPref extends ListPreference
{
    public interface LoadingListener
    {
        void setData(ListPreference lp);
    }

    LoadingListener TheLL;

    public void setLoadingListener(LoadingListener l)
    {
        TheLL = l;
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
    {
        if(TheLL!=null)
        {
            TheLL.setData(this);
        }
        super.onPrepareDialogBuilder(builder);
    }

    //Do not mind the rest of this class, as they are auto-generated boilerplate code.
    public DListPref(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public DListPref(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

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

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

Et puis je viens de changer le nom de ma classe dans le XML.

<my.company.DListPref
    Android:defaultValue="-1"
    Android:key="damn"
    Android:title="vegetables"/>

Et puis j'ai simplement fait ça à onCreate.

        DListPref lp = (DListPref) findPreference("damn");

        lp.setLoadingListener(new DListPref.LoadingListener()
        {
            @Override
            public void setData(ListPreference lp)
            {
                lp.setEntries(new String[]{"doge", "wow"});
                lp.setEntryValues(new String[] {"1", "2"});
                lp.setDefaultValue("1");
            }
        });

J'ai tout de suite travaillé. En fait, je ne m'attendais pas à ce que cela se fasse si facilement.

1
Damn Vegetables