I have a preference activity that has a language
as ListPreference
which displays the available language list. I can fill the list when onCreate is called, but I want to fill the list when the user clicks on it.
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;
}
}
and this is the settings.xml
(preference) :
<?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:titl开发者_如何学Ce="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>
I searched but found no result! An exception occurs every time I click on that list.
You are getting the exception because your ListPreference object is not initialized - you either need to set entries
and entryValues
attributes in your XML or do it programatically in onCreate()
.
If if you need to change the items in the list dynamically after the initial ListPreference object has been initialized then you will need to attach the OnPreferenceClickListener
directly to the ListPreference object. Use the key you have specified in the XML to get a handle to the preference.
Since the code to populate the entries
and entryValues
arrays will have to be run both in onCreate()
and in onPreferenceClick
, it makes sense to extract it to a separate method - setListPreferenceData()
in order to avoid 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);
}
}
Here is another example from google's DeskClock app:
Using PreferenceFragment & JAVA set key rather than PreferenceActivity & XML as shown in https://stackoverflow.com/a/13828912/1815624, which this answer is based on:
If what you want is to be able to change the items in the list dynamically after the initial ListPreference object has been initialized then you will need to attach the OnPreferenceClickListener
directly to the ListPreference object. Use the key you have specified in the JAVA source (as CUSTOM_LIST
) to get a handle to the preference.
Since the code to populate the entries
and entryValues
arrays will have to run both in onCreate()
and in onPreferenceClick
, it makes sense to extract it to a separate method - setListPreferenceData()
in order to avoid 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);
}
}
XML layout:
<?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>
I solved the problem my extending the ListPreference. It was very 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);
}
}
And then I just changed the name to my class in the XML.
<my.company.DListPref
android:defaultValue="-1"
android:key="damn"
android:title="vegetables"/>
And then I simply did this at the 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");
}
});
Worked right away. Actually, I never expected it would be done so easily.
This is what I had to do to make mine work
public static class MyPreferenceFragment extends PreferenceFragment
{
@Override
public void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
PreferenceCategory targetCategory = (PreferenceCategory) findPreference("CUSTOM_FRAG");
//final Preference pref;
//pref = findPreference("example_list1");
final ListPreference lp = setListPreferenceDataSocieties((ListPreference) findPreference("custom1"), getActivity());
final ListPreference lp2 = setListPreferenceDataRoutes((ListPreference) findPreference("custom2"), getActivity());
final ListPreference lp3 = setListPreferenceDataCoolers((ListPreference) findPreference("custom3"), getActivity());
setHasOptionsMenu(true);
targetCategory.addPreference(lp);
targetCategory.addPreference(lp2);
targetCategory.addPreference(lp3);
bindPreferenceSummaryToValue(targetCategory);
bindPreferenceSummaryToValue(lp);
bindPreferenceSummaryToValue(lp2);
bindPreferenceSummaryToValue(lp3);
}
protected ListPreference setListPreferenceDataSocieties(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("Origin Society");
lp.setSummary(lp.getEntry());
lp.setDialogTitle("Registered Societies");
lp.setKey("society_list");
return lp;
}
protected ListPreference setListPreferenceDataRoutes(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("Designated Route");
lp.setSummary(lp.getEntry());
lp.setDialogTitle("Available Routes");
lp.setKey("route_list");
return lp;
}
protected ListPreference setListPreferenceDataCoolers(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("Destination Cooler");
lp.setSummary(lp.getEntry());
lp.setDialogTitle("Available Coolers");
lp.setKey("cooler_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);
}
}
boolean first_run = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyPreferenceFragment frag = new MyPreferenceFragment();
getFragmentManager().beginTransaction().replace(android.R.id.content, frag).commit();
}
精彩评论