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.
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:
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>
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.