Get Key, not value, of the ListPreference selection - Possible? - android

Getting the value of the currently selected item in a ListPreference is straightforward:
String selected = sharedPrefs.getString(
getString(R.string.list_preference_array),
"default string"
);
But now I need to get the key of the currently selected item, instead. Is this possible?
To clarify, a typical ListPreference definition in the XML file has the following components:
<ListPreference
android:key="#string/list_preference_array"
android:title="Title of ENTIRE list (not seen by user?)"
android:summary="this is what the user sees in small fonts"
android:defaultValue="just in case"
android:entries="#array/user_friendly_labels"
android:entryValues="#array/code_meaningful_strings"
android:dialogTitle="User Prompt(big font)"
android:showDefault="true"
android:showSilent="true"
/>
What sharedPrefs.getString() returns is the current selection from android:entryValues. What I am interested in getting is the current selection from android:entries. I mistakenly called it "key" but really it is a "corresponding label", which must be different than actual content.

A bit of a guess:
int index = mylistpreference.findIndexOfValue(selected) // <- selected taken from your code above
String entry = mylistpreference.getEntries()[index];

just use:
mylistpreference.getEntry()
to get mylistpreference use:
mylistpreference= (ListPreference) getPreferenceScreen().findPreference(key);
key is the android:key you defined in preference.xml inside < ListPreference> tag.

The function is defined as
SharedPreferences.getString(String key, String defaultValue);
So in your example code, getString(R.string.select_string) would return the key.
When you add the SharedPreference, you need to specify the key, so the key would be the same one you used to set the value.
Edit:
using SharedPreferences.getString() with the ListPreference key as the key will return the value the user selected from the list. You don't need to create keys for each option in the ListPreference array, and these keys aren't created automatically. Use case statements that correlate to the ListPreference's entryValues.

#shai Your method lags to last selected entry
listPreference.getEntry()
Rather #Erik 's method works nicely
int index = listPreference.findIndexOfValue((String) value)
String entry = listpreference.getEntries()[index];

To properly update the summary of a ListPreference (using the label, instead of the key).
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
ListPreference listPreference = (ListPreference) preference;
int prefIndex = listPreference.findIndexOfValue(stringValue);
if (prefIndex >= 0) {
CharSequence[] labels = listPreference.getEntries();
preference.setSummary(labels[prefIndex]);
}
} else {
preference.setSummary(stringValue);
}
return true;
}

Related

Android: How to get SharedPreferences of an object dynamically?

I have an Array with the IDs of several checkboxes. In onResume I wish to check whether the booleans of those checkboxes are true or false (using a loop) in order to adapt the view. Here is my Code. It does not work as it tells me that every value is false. Could someone tell me why this is happening?
ArrayList<Integer> boxArray = new ArrayList<Integer>();
boxArray.add(R.id.boxA);
boxArray.add(R.id.boxB);
boxArray.add(R.id.boxC);
And in onReturn:
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
for (int i=0; i<boxArray.size(); i++) {
if (preferences.getBoolean
(findViewById(boxArray.get(i)).toString(), false) == true) {
//change the view of the checkbox to checked if its value is true
CheckBox currentBox = (CheckBox) findViewById(boxArray.get(i));
currentBox.setChecked(true);
}
}
How do you set the value in shared preferences?
When a box is checked do you do something like
preferences.edit().putBoolean(TheCheckedBoxId, true);
If the shared preference getBoolean() method is always defaulting to false then either the value is not there at all or it is just false. I think you can try
preferences.contains(findViewById(boxArray.get(i)).toString())
to see if that key exists at all. There's also the preferences.getAll() method.

Android JUnit testing of Preferences

A fairly normal scenario: an Android application has a preferences activity, and selecting an option from a ListPreference triggers code to change that ListPreference's summary text. ie: Selecting "Green" from a color ListPreference would change the ListPreference's summary text to "Green" through a onPreferenceChange callback.
I'd like to be able to use the Android JUnit testing to confirm that these summary changes are all being performed correctly. However, there seems to be very little information out there on how to do this.
I've tried variations of using setValue() on ListPreference, both in the test thread and through runOnUiThread(), with no success - this doesn't trigger the call to onPreferenceChange(). I've also tried getInstrumentation().waitForIdleSync() after calling setValue(), but that's also with no success.
So, my question is: how is this done?
Thanks!
A few more hours of work produced this working solution, but I'm curious if anyone else has a better solution. This code was inspired by this solution to a similar question, but this case is different in two ways:
It's intended for use by Android JUnit, which means it needs to call the ListPreference UI clicks via runOnUiThread().
It expects there to be preference categories in use, which complicate finding the position (relative to the entire preferences list) to click. The above mentioned solution only works in cases without preference categories.
This method will accept the key for a particular ListPreference item, along with the position of the item in the list to be clicked. It will then perform that list item click, and other code would do the checking I'm looking for.
Note that this requires setActivityInitialTouchMode(true); to be set before the getActivity() call in the setUp() method.
private void clickListPreference(String _listPreferenceKey, int _listItemPos){
final String listPreferenceKey = _listPreferenceKey;
final int listItemPos = _listItemPos;
mActivity.runOnUiThread(
new Runnable() {
public void run() {
// get a handle to the particular ListPreference
ListPreference listPreference= (ListPreference) mActivity.findPreference(listPreferenceKey);
// bring up the dialog box
mActivity.getPreferenceScreen().onItemClick( null, null, getPreferencePosition(), 0 );
// click the requested item
AlertDialog listDialog = (AlertDialog) listPreference.getDialog();
ListView listView = listDialog.getListView();
listView.performItemClick(listView, listItemPos, 0);
}
/***
* Finding a ListPreference is difficult when Preference Categories are involved,
* as the category header itself counts as a position in the preferences screen
* list.
*
* This method iterates over the preference items inside preference categories
* to find the ListPreference that is wanted.
*
* #return The position of the ListPreference relative to the entire preferences screen list
*/
private int getPreferencePosition(){
int counter = 0;
PreferenceScreen screen = mActivity.getPreferenceScreen();
// loop over categories
for (int i = 0; i < screen.getPreferenceCount(); i++){
PreferenceCategory cat = (PreferenceCategory) screen.getPreference(i);
counter++;
// loop over category items
for (int j = 0; j < cat.getPreferenceCount(); j++){
if (cat.getPreference(j).getKey().contentEquals(listPreferenceKey)){
return counter;
}
counter++;
}
}
return 0; // did not match
}
}
);
getInstrumentation().waitForIdleSync();
}

Android: ListPreference hide/disable value

I'm generating a listPreference dialog based on xml (entries and entryValues).
<string-array name="listArray">
<item>Title (A-Z)</item>
<item>Title (Z-A)</item>
<item>Visits (default)</item>
<item>Date</item>
<item>Manual</item>
</string-array>
<string-array name="listValues">
<item>titleASC</item>
<item>titleDESC</item>
<item>visitsSort</item>
<item>createSort</item>
<item>manualSort</item>
</string-array>
I want to hide/disable some of the entries (for example: Manual) based on some other parameters.
I understand it should be inside this scope:
Preference sorted = (Preference) findPreference(OPT_SORT);
sorted.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
if (params) {
What should i put here to hide/disable some of the entries?
}
return true;
}
});
Thank you!
EDIT:
Best solution I found is to load a different set of Entries and EntryValues.
On Preference class (onCreate):
ListPreference sortBy = (ListPreference) findPreference(OPT_SORT);
if (isTabletDevice()) {
sortBy.setEntries(getResources().getStringArray(R.array.HClistArray));
sortBy.setEntryValues(getResources().getStringArray(R.array.HClistValues));
}
Hope this helps anyone! :)
AFAIK, ListPreference does not support this. You might be able to create your own subclass of ListPreference where you use a custom Adapter and indicate which items are and are not enabled.
It's quite late answer, I hope that's will help.
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in
// the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value.
preference
.setSummary(index >= 0 ? listPreference.getEntries()[index]
: null);
// If it's sync_factory_list, enable/disable appropriate settings
if(preference.getKey().equalsIgnoreCase("sync_factory_list")){
Preference p_api_key = preference.getPreferenceManager().findPreference("ws_api_key");
Preference p_api_url = preference.getPreferenceManager().findPreference("ws_api_url");
switch ( index) {
case 0: //local
p_api_key.setEnabled(false);
p_api_url.setEnabled(false);
break;
case 1: //prestashop webservice
p_api_key.setEnabled(true);
p_api_url.setEnabled(true);
break;
case 2: //thrift
p_api_key.setEnabled(false);
p_api_url.setEnabled(false);
break;
default:
p_api_key.setEnabled(false);
p_api_url.setEnabled(false);
break;
}
}
}
...
return true;
}
}

ListPreference no selection. How to?

I have a ListPreference and want to verify if there is no selection to make some code/treatement. How can i do this ?
I have this to verify the selection:
if (Integer.valueOf(choice) == 0) {
What code to verify if not selection?
Thank you for your help.
If there is a preference selected for this ListPreference, then it will be saved in your SharedPreferences. You can test against this value by doing something like this:
private Boolean prefHasSelection(String prefId){
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
String yourPref = sp.getString(prefId, null);
return (yourPref != null);
}
prefHasSelection("yourPrefId"); // returns true if something is set
You could call this method at any point in your application lifecycle to determine if the preference has been set.

How to edit a ListPreference value from java code in Android

I know how to change the value of a CheckBoxPreference, but I can't get it to work for a ListPreference.
Here is how my preference screen is built:
one CheckBox for the default
A ListPreference to select a color other than the default.
The ListPreference is defined with the key "titleColor", as follows :
CharSequence[] entries = { "Dark grey", "Light grey", "Light red", "Red" };
CharSequence[] entryValues = { "#4c4c4c", "#b5b5b5", "#ab6a68", "#962622" };
final ListPreference color = (ListPreference) findPreference("titleColor");
color.setEntries(entries);
color.setEntryValues(entryValues);
Now, when I select a color I do this:
color.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
System.out.println("In the onClick method");
System.out.println("change title color");
Editor editor2 = defaultColor.getEditor();
editor2.putBoolean("defaultColor", false);
editor2.commit();
return true;
}
});
And this seems to work, though I'm not sure to do this properly.
Now I have been trying to do something similar when I select the default color, but I can't get the list to either uncheck everything OR check a color that would be the default.
Any idea?
In the case of the CheckBox:
If you had a default color CheckBox it would be fixed using android:dependency, but since you don't have it, I guess that's the only way.
Related with the ListPreference, is quite similar:
ListPreference lp = (ListPreference)findPreference("listPreference_key");
lp.setValue("");
You can check the docs to know which methods are available.

Categories

Resources