I have a ListPreference and I want to show the current entry in the summary. According to the docs for ListPreference.getSummary(), I'm supposed to be able to do this by including %s in the summary string. Unfortunately, the activity just displays the %s in the summary.
The XML is pretty standard:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="displayMode"
android:summary="#string/display_mode_summary"
android:title="#string/display_mode"
android:defaultValue="BOTH"
android:entries="#array/displayModes"
android:entryValues="#array/displayModeValues"
/>
</PreferenceScreen>
The value of the string display_mode_summary is just %s. (The value "BOTH" is present in the displayModeValues array.) If I subclass ListPreference like this:
public final class DisplayModePreference extends ListPreference {
// ...
#Override
public CharSequence getSummary() {
return String.format(super.getSummary().toString(), getEntry());
}
}
then when the preferences activity starts, the current value is correctly interpolated into the summary. But when I click on the preference and select a different value from the dialog, when the dialog closes the summary still shows the now-old value. I need to close the preferences activity and restart it to see the change.
I've tried this in several emulators at different API levels. What do I need to so that the displayed summary always reflects the current value?
You could override "onDialogClosed" as below:
#override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
setSummary(getEntry());
}
}
This will set the summary of your preference to the text of the selected entry.
The original getSummary() in ListPreference only works when getEntries(), getEntryValues() and defaultValue are pre-populated when the Preference screen loads. So it works fine when you use a static fixed list of items, like a <string-array> resource.
But if you are dynamically generating the entries and entryValues at runtime, you need to ensure that these lists are generated when the Preference screen loads in onCreate() and also ensure that the defaultValue is set. Something like this:
SettingsFragment.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListPreference listPreference = (ListPreference) findPreference("dynamiclistItems");
CharSequence[] entryDisplayNames = new CharSequence[3];
entryDisplayNames[0] = "Item A";
entryDisplayNames[1] = "Item B";
entryDisplayNames[2] = "Item C";
CharSequence[] entryValues = new CharSequence[3];
entryValues[0] = "Item A Value";
entryValues[1] = "Item B Value";
entryValues[2] = "Item C Value";
listPreference.setEntries(entryDisplayNames);
listPreference.setEntryValues(entryValues);
if (listPreference.getValue() == null ||
listPreference.getValue().equals("")) {
// There is no stored string in shared prefs.
// The user has not chosen any value. So make
// the summary display a default entry "Item A"
// display name, which is item 0 in the 'entries' list. Info:
// https://stackoverflow.com/questions/5197228/how-to-set-the-default-value-of-a-listpreference
listPreference.setValueIndex(0);
}
}
For static lists that are populated with <string-array>, just ensure that android:defaultValue="..." is defined, and that it points to a valid item in the 'values' array. For example: android:defaultValue="Item A Value"
This will ensure that the android:summary="%s" will work properly for dynamically generated and static lists.
Related
Let's say I have 10 buttons whose ID's are 1,2,...,10. I have an XML file called preferences.xml that contains a checkbox:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="applicationPreference" android:title="#string/config">
<CheckBoxPreference
android:key="checkbox" />
</PreferenceScreen>
My buttons all call the same function which calls for the intent to start the PreferenceActivity.
What I want to do is to call the same model with every button but save the values of the checkbox for each button. Currently, every time I click on a button, it launches the activity, but, for example, the value of my button 1 will be found in the value of my button 5.
Should I use SharedPreferences or something else?
I know it's possible but as I am still unfamiliar with many concepts, I just don't find it.
This is your problem: The PreferenceActivity automatically saves settings for you in the shared preferences of your application. For each setting, you define a key in your preferences.xml. In your case this is
android:key="checkbox"
so the value "checkbox" in your SP gets set to true, when you open your preferences with button 5. When you open the preferences with button 1 again, the PreferencesActivity looks up the SPs, sees that "checkbox" is true and therefore sets the checkbox to checked.
To avoid this issue, like Adrian said, you have to pass information to your PreferenceActivity about what button get clicked. In your PreferenceActivity you have to get a reference to your checkbox preference and add your passed button id to the key.
Preference checkboxPreference = findPreference("checkbox");
checkboxPreference.setKey(checkboxPreference.getKey() + buttonId);
Now there are 10 uniquely named boolean values ("checkbox1","checkbox2",..) saved in your SP for each of your buttons.
have fun
If I understood correctly, you have to tell the PreferenceActivity which button was press. You can achieve this by setting the button id as a parameter when starting the activity.
/*
* This is the common method used by all the buttons after the click
* was done in order to start the PreferenceActivity and pass
* the button id as a parameter
* #param sender - Button which was pressed and will start the
* PreferenceActivity
*/
private void startPreferenceActivity(Button sender)
{
// create the intent
Intent intent=new Intent(context, PreferenceActivity.class);
// add button id as a parameter
intent.putExtra("buttonID", sender.getId());
// start activity
startActivity(intent);
// or you can start it to way for a result
// startActivityForResult(intent, 0);
}
Now, in the PreferenceActivity you have to get the parameter which you have sent:
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get the extras where the parametrs are stored
Bundle bundle = getIntent().getExtras();
if(bundle.getInt("buttonID") != null)
{
// get id as int with default value as 0
int id= intent.getInt("buttonID", 0);
}
if(bundle.getString("buttonID") != null)
{
// get id as string with default value as ""
string id= intent.getString("buttonID", "");
}
// other code here ...
}
Hope this will help you.
I'm trying to programmatically create a ListPreference, which I can do but when I select it, it's list of entries is empty. I believe I am correctly setting the setEntries() and setEntryValues() with CharSequence arrays, but it's just empty when I select it.
Please find below the ActivitySetting class. Please note I'm using PreferenceFragments as to not use deprecated methods. But I only have one PreferenceFragment which is currently set as default
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit();
}
public static class PrefsFragment extends PreferenceFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.settings);
// Create the new ListPref
ListPreference customListPref = new ListPreference(getActivity());
// Get the Preference Category which we want to add the ListPreference to
PreferenceCategory targetCategory = (PreferenceCategory) findPreference("TARGET_CATEGORY");
CharSequence[] entries = new CharSequence[]{"One", "Two", "Three"};
CharSequence[] entryValues = new CharSequence[]{ "1", "2", "3" };
// IMPORTANT - This is where set entries...looks OK to me
customListPref.setEntries(entries);
customListPref.setEntryValues(entryValues);
customListPref.setTitle("Title");
customListPref.setSummary("This is the summary");
customListPref.setDialogMessage("Dialog Message");
customListPref.setPersistent(true);
// Add the ListPref to the Pref category
targetCategory.addPreference(customListPref);
}
}
}
Here is the Setting.xml it just has the single PreferenceCategory which the ListPreference is added to:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Some Options" android:key="TARGET_CATEGORY">
</PreferenceCategory>
</PreferenceScreen>
Here is what I get. The ListPreference has been successfully but when I select it.... No entries :( I'm expecting the options: "One", "Two", "Three"
Found it if you set the setDialogMessage() then this overwrites the contents so by removing this line, it works now.
You might want to replace setDialogMessage() by setDialogTitle() to get the title back.
I am currently able to create a preference screen with a PreferenceFragment, in which I assign my preferences using:
addPreferencesFromResource(R.xml.preferences);
Instead of using the resource 'R.xml.preferences', I would like to use my SharedPreferences i have already saved, for example:
SharedPreferences prefs = this.getActivity().getSharedPreferences("preferences", 0);
addPreferencesFromResource(prefs);
However, this does not work. Is it possible to do this? If so, How? Or is it required that I use an xml document?
I happen to had exactly the same problem but I figured it out, hope this helps.
You need to do the following steps in order to add a Custom Preference without using an XML Reouser
First:
You need to create a Preference Screen, this is as it says a "screen" which can containt several Preferences and must be linked to your PreferenceFragment or PreferenceActivity.
Consider the Following PreferenceFragment for example (and consider it is contained in a superior Activity..)
public static class YourPreferenceFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen p = createPreferences();
this.setPreferenceScreen(p);//Set the PreferenceScreen as the current one on this fragment
//now bind values, notice we use p.findPreference which means whe look into the preferenceScreen Associated with the PreferenceFragment/Activity
bindPreferenceSummaryToValue(p.findPreference("some_key"));
}
}
Now Consider that createPreferences is a method that will return a PreferenceScreen with your custom preferences such as a ListPreference or CheckboxPreference. This is how you really create the preferences and add them into a PreferenceScreen
private PreferenceScreen createPreferences()
{
PreferenceScreen p =
getPreferenceManager().createPreferenceScreen(getActivity());
ListPreference listPref = new ListPreference(getActivity());
listPref.setKey("some_key"); //Refer to get the pref value
CharSequence[] csEntries = new String[]{"Item1","Item2"};
CharSequence[] csValues = new String[]{"1","2"};
listPref.setDefaultValue(-1);
listPref.setEntries(csEntries); //Entries(how you display them)
listPref.setEntryValues(csValues);//actual values
listPref.setDialogTitle("Dialog title");
listPref.setTitle("Title");
listPref.setSummary("Some summary");
p.addPreference(listPref);
return p;
}
Please let me know if this helps
best,
EDIT: Code for bindPreferenceSummaryToValue
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
if (preference instanceof CheckBoxPreference) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager.
getDefaultSharedPreferences(preference.getContext()).
getBoolean(preference.getKey(),false));
} else {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager.
getDefaultSharedPreferences(preference.getContext()).
getString(preference.getKey(),""));
}
}
I am trying to fill a ListPreference with the contents of the res/anim folder but I am having a problem it keeps coming up blank, I have a static array of strings to fill it and that works but I need it to be dynamic, I can print the text out in the logcat, its just not populating the list can you help me?
PreferenceActivityMenu.java
CharSequence[] entries = null;
CharSequence[] entryValues = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
SharedPreferences prefs=getPreferences(Context.MODE_PRIVATE);
ListPreference prefListAnim = new ListPreference(this);
listAnim();
prefListAnim.setEntries(entries);
prefListAnim.setEntryValues(entryValues);
}
#Override
public boolean onPreferenceClick(Preference preference) {
// TODO Auto-generated method stub
return false;
}
public void listAnim() {
Field[] fields = R.anim.class.getFields();
entries = new String[fields.length];
entryValues = new String[fields.length];
for (int count = 0; count < fields.length; count++) {
Log.i("Raw Asset: ", fields[count].getName());
entries[count] = fields[count].getName();
entryValues[count] = Integer.toString(count);
}
}
and preference.xml
<PreferenceCategory android:title="Animation Transitions" >
<ListPreference
android:dialogTitle="#string/prefsList_dialogTitle"
android:key="prefList_animations"
android:summary="#string/prefsList_summary"
android:title="#string/prefsList_title" >
</ListPreference>
</PreferenceCategory>
Thanks for your help
You are setting the list data to a different preference than the one declared in xml. Currently you're setting the data against a newly created ListPreference:
ListPreference prefListAnim = new ListPreference(this);
However, you're displaying the (empty) one declared in xml. You should do either one or the other. For example, the easiest solution is probably to change above to inflate the preference from xml in stead:
ListPreference prefListAnim = (ListPreference) findPreference("prefList_animations");
i am new to android programming .well in my application i have added the preference class and i am calling the xml preference which is stored in the xml folder of my application.this is the code for it
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference android:title="colors" android:key="colors"
android:summary="list of colors to choose from " android:entries="#array/list"
android:entryValues="#array/lvalues"></ListPreference>
</PreferenceScreen>
and in the java class i had written only one line that is this
addPreferencesFromResource(R.xml.prefs);
now i am able to show the preference class and also the list some colors data.
my question is on selecting the list preference it should show me the selected preference in to the summary attribute .currently it is showing me as 'list of colors to choose from'
what i want is to show the selected color say i have selected white the summary should show me as white.
please help me .
Thank you,
maddy.
you can actually do it in xml. Try this:
<ListPreference
android:key="pref_list"
android:title="A list of preferences"
android:summary="%s"
android:entries="#array/pref_list_entries"
android:entryValues="#array/pref_list_entries_values"
android:defaultValue="0" />
your selected value would replace "%s".
For further clarification read this post
In the other code example there is a little bug which causes that the old value is displayed and not the new one.
Here is a working version:
ListPreference splashList = (ListPreference) findPreference("splash");
splashList.setSummary(splashList.getEntry());
splashList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
String nv = (String) newValue;
if (preference.getKey().equals("splash")) {
ListPreference splashList = (ListPreference) preference;
splashList.setSummary(splashList.getEntries()[splashList.findIndexOfValue(nv)]);
}
return true;
}
});
You need to extend ListPreference class and specify that in the xml file
class MyListPref extends ListPreference {
public void onClick (DialogInterface dialog, int which) {
this.setSummary(MyListPref.this.getEntry());
}
}
If your Custom Preference class name is com.sample.MyListPref the xml entry will be
<com.sample.MyListPref
android:key="pref_list"
android:title="List Preference"
android:dialogTitle="List Pref Dialog"
android:entries="#array/pref_items"
android:entryValues="#array/pref_items_values"/>
You dont need to do the extend listPreferences. in your PreferencesActivity file put as per my example:
final ListPreference defaultTown=(ListPreference)findPreference(getString(R.string.pref_default_town_key));
Log.i("try",defaultTown.getKey());
defaultTown.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.i("theApp", "Selected = " + defaultTown.getValue());
defaultTown.setTitle(defaultTown.getValue());
return true;
}
});
on change the value will update the title
when you enter the application you will need to populate the title with your current preference though instead of colors which is set at default in your xml