I'm trying to improve the user friendliness of an app by providing the user with "Select all" and "Deselect all" options in the preferences. Things seem to be working, except for one major flaw:
I'm using SharedPreferences.getAll() to retrieve all the checkboxes so I can iterate them and check/uncheck them. But it seems that getAll() doesn't quite live up to it's name. It doesn't return ALL preferences, but only the ones that have been previously altered by the user.
So, is there a way to retrieve ALL of the preferences?
The code I'm currently using:
public class ADRpreferences extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
((Preference) findPreference("searchresult_select_all")).
setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
setCheckState("searchresult", true);
return true;
}
});
((Preference) findPreference("searchresult_deselect_all")).
setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
setCheckState("searchresult", false);
return true;
}
});
}
private void setCheckState(String prefix, Boolean state) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
#SuppressWarnings("unchecked")
Map<String, Boolean> categories = (Map<String, Boolean>) settings.getAll();
for (String s : categories.keySet()) {
Preference pref = findPreference(s);
if( s.startsWith(prefix) && (pref instanceof CheckBoxPreference) ){
((CheckBoxPreference) pref).setChecked(state);
}
}
}
}
EDIT
Ok, for now I will go with MH's solution. I put all the ID's of the checkbox preferences into arrays.xml, and will use those values to iterate through all the checkboxes (there are 44 of them in case you wonder why I just don't hardcode the ID's). Works great, of course in the future I will have to remember to add/remove the ID's in the arrays if I make changes to the preferences. Here's the new setCheckState():
private void setCheckState(String category, Boolean state) {
String[] arr = null;
if( category.equals("loadlist") ){
arr = getResources().getStringArray(R.array.array_loadlist_checkboxes);
}
else if( category.equals("searchresult") ){
arr = getResources().getStringArray(R.array.array_searchresult_checkboxes);
}
else{
return;
}
for( String s : arr ){
Preference pref = findPreference(s);
if( pref instanceof CheckBoxPreference ){
((CheckBoxPreference) pref).setChecked(state);
}
}
}
Related
How can I check in my MainActivity if the on/off switch is on in the SettingsActivity. I want to check if the switch is on and if it is, I want to do something. How do I do this so that this preference is saved and will be the same when you restart the app?
Here is a part of my SettingsActivity with a switch
static int audio;
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class GeneralPreferenceFragment extends PreferenceFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.pref_general);
setHasOptionsMenu(true);
bindPreferenceSummaryToValue(findPreference("example_text"));
bindPreferenceSummaryToValue(findPreference("example_list"));
Preference switchPref = (Preference) findPreference("audio_switch");
switchPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean isOn = (boolean) o;
if (isOn) {
audio = 1;
}else{
audio = 0;
}
return true;
}
});
}
You are saving correctly the preference value, even you are returning true from your onPreferenceChangeListener to store the new value.
Preference switchPref = (Preference) findPreference("audio_switch");
switchPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
boolean isOn = (boolean) o;
if (isOn) {
audio = 1;
}else{
audio = 0;
}
//* Set true to update the state of the Preference with the new value!
return true;
}
});
}
The value is saved correctly when you close the application, if you want to check the value you can read it from the preference:
//Check the current value in preference.
SharedPreferences switchPrefStatus = PreferenceManager.getDefaultSharedPreferences(getActivity());
boolean switchPrefValue = switchPrefStatus.getBoolean("audio_switch", false);
Toast.makeText(getActivity(), "Current value: " + switchPrefValue, Toast.LENGTH_SHORT).show();
Here is a complete example of PreferenceFragment with PreferenceFragment:
I usually do the following:
To save your setting
(Put this in a save() method you call when you click a button or something in your settings activity)
SharedPreferences options =
getSharedPreferences("optionsPreference",
contextOfSettings.MODE_PRIVATE);
options.edit().putString("key", "value").apply();
In order to do this you need to add this in your settings activity
As a global variable in settings
public static Context contextOfSettings;
And this method in your onCreate of settings
#Override
protected void onCreate {
contextOfSettings = getApplicationContext();
}
And import it in your main activity by typing context of settings somewhere and then import it by pressing alt+enter
Like this:
import com.SettingsActivity.contextOfSettings;
Then you can get your saved value (which will still be saved even if you close your app) with this in your on create of your MainActivity
SharedPreferences options = getSharedPreferences("optionsPreference", contextOfSettings.MODE_PRIVATE);
String savedValue = options.getString("key", "defaultValue");
This String can have the values true and false which you can set with checkBox.isChecked() in combination with an if-statement
hello everyone i am new to android development.i want to open a alert dialog when user choose any theme in list preference in preference activity.i search lot in google but did not find any appropriate answer.here is my PrefenceActivity.
public class Setting extends PreferenceActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
Setting.setAppTheme(this);
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
String ListPreference;
public static void setAppTheme(Activity a) {
// Get the xml/preferences.xml preferences
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(a);
int ListPreference = Integer.parseInt(prefs.getString("listPref", "3"));
if(ListPreference == 0) {
a.setTheme(R.style.AppBaseThemeDark);
return;
} else if(ListPreference == 1){
a.setTheme(R.style.AppBaseThemeLight);
//Toast.makeText(getApplicationContext(),"TTS Engines not found.\n Install TTS Engins",Toast.LENGTH_LONG).show();
} else if(ListPreference == 2){
a.setTheme(R.style.AppBaseTheme);
}
}
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getActionBar().setDisplayHomeAsUpEnabled(true);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; go home
getFragmentManager().popBackStack();
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
I faced the same problem a few days ago and I implemented a custom preference class extending ListPreference to do this. This is the class I implemented:
public class LogCleanPreference extends ListPreference {
private int mClickedDialogEntryIndex;
private Context mContext;
public LogCleanPreference(Context ctxt) {
this(ctxt, null);
}
public LogCleanPreference(Context ctxt, AttributeSet attrs) {
super(ctxt, attrs);
mContext = ctxt;
setNegativeButtonText(ctxt.getString(R.string.alert_cancel));
}
#Override
protected void onPrepareDialogBuilder(Builder builder) {
if (getEntries() == null || getEntryValues() == null) {
throw new IllegalStateException(
"ListPreference requires an entries array and an entryValues array.");
}
mClickedDialogEntryIndex = findIndexOfValue(getValue());
builder.setSingleChoiceItems(getEntries(), mClickedDialogEntryIndex,
new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int which) {
// In my case I only show the AlertDialog if the user didn't select option number 2
if(which != 2){
// Show AlertDialog
}
else{
// Save preference and close dialog
mClickedDialogEntryIndex = which;
LogCleanPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
dialog.dismiss();
}
}
});
builder.setPositiveButton(null, null);
}
#Override
protected void onDialogClosed(boolean positiveResult) {
CharSequence[] mEntryValues = getEntryValues();
if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
String value = mEntryValues[mClickedDialogEntryIndex].toString();
if (callChangeListener(value)) {
setValue(value);
}
}
}
}
This is how I use the preference in my prefs.xml:
<com.timeondriver.tod.settings.LogCleanPreference
android:defaultValue="0"
android:dialogTitle="#string/dialog_title_log_clean"
android:entries="#array/log_clean"
android:entryValues="#array/log_clean_values"
android:key="log_clean_preference"
android:summary="#string/summary_log_clean_preference"
android:title="#string/title_log_clean_preference" />
1st, Create a change listener:
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);
}
return true;
}
};
2nd, Bind preference to its value:
// Set the listener to watch for value changes.
preference
.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
sBindPreferenceSummaryToValueListener.onPreferenceChange(
preference,
PreferenceManager.getDefaultSharedPreferences(
preference.getContext()).getString(preference.getKey(),
""));
3rd, in the 1st step you can insert the code to launch you dialog with the if condition.
I have an issue I have been unable to figure out. I have a spinner loaded from an ArrayList saved in SharedPreferences. I allow the users to modify the spinner names through a PreferenceActivity in a separate class that is startActivityForResult. It works but I cannot for the life of me make the spinner refresh itself with the new name(s) unless the app is closed and then reopened.
When the user uses the back key to close the Edit names window the result code and result_ok information is passed back correctly. This is where I can't figure things out. I know I need to use NotifyDataSetChanged but I can't figure out how to do it since the modifications are made in a separate class and not in the OnItemSelectedListener like so many answers to questions here on StackOverflow suggest for refreshing spinner data.
Here is my spinner code:
private ArrayAdapter<String> adapter1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
/* enable hardware acceleration on Android >= 3.0 */
final int FLAG_HARDWARE_ACCELERATED = WindowManager.LayoutParams.class
.getDeclaredField("FLAG_HARDWARE_ACCELERATED").getInt(null);
getWindow().setFlags(FLAG_HARDWARE_ACCELERATED,
FLAG_HARDWARE_ACCELERATED);
} catch (Exception e) {
}
checkPreferences();
setContentView(R.layout.main);
this.findViewById(R.id.label_mode).setOnClickListener(this);
this.findViewById(R.id.label_clear).setOnClickListener(this);
this.findViewById(R.id.label_data).setOnClickListener(this);
this.findViewById(R.id.label_wifi).setOnClickListener(this);
this.findViewById(R.id.label_roam).setOnClickListener(this);
this.findViewById(R.id.label_vpn).setOnClickListener(this);
this.findViewById(R.id.label_invert).setOnClickListener(this);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
// create the spinner
spinner = (Spinner) findViewById(R.id.spinner);
// profile names for spinner
final List<String> profilestring = new ArrayList<String>();
profilestring.add(prefs.getString("default",
getString(R.string.defaultprofile)));
profilestring.add(prefs.getString("profile1",
getString(R.string.profile1)));
profilestring.add(prefs.getString("profile2",
getString(R.string.profile2)));
profilestring.add(prefs.getString("profile3",
getString(R.string.profile3)));
profilestring.add(prefs.getString("profile4",
getString(R.string.profile4)));
profilestring.add(prefs.getString("profile5",
getString(R.string.profile5)));
profileposition = profilestring
.toArray(new String[profilestring.size()]);
// adapter for spinner
adapter1 = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, profileposition);
adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter1);
spinner.setSelection(prefs.getInt("itemPosition", 0));
spinner.post(new Runnable() {
public void run() {
spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = prefs.edit();
int index = parent.getSelectedItemPosition();
if (index == 0) {
editor.putInt("itemPosition", index);
editor.commit();
LoadDefaultProfile();
}
if (index == 1) {
editor.putInt("itemPosition", index);
editor.commit();
LoadProfile1();
}
if (index == 2) {
editor.putInt("itemPosition", index);
editor.commit();
LoadProfile2();
}
if (index == 3) {
editor.putInt("itemPosition", index);
editor.commit();
LoadProfile3();
}
if (index == 4) {
editor.putInt("itemPosition", index);
editor.commit();
LoadProfile4();
}
if (index == 5) {
editor.putInt("itemPosition", index);
editor.commit();
LoadProfile5();
}
}
public void onNothingSelected(AdapterView<?> parent) {
// do nothing
}
});
}
});
I then set my selection and run the spinner with spinner.post(New Runnable).
My preference screen is very simple.
<?xml version="1.0" encoding="utf-8"?>
<EditTextPreference
android:key="default"
android:summary="Edit name for Default Profile"
android:title="#string/defaultprofile" />
<EditTextPreference
android:key="profile1"
android:summary="Edit name for profile1"
android:title="#string/profile1" />
<EditTextPreference
android:key="profile2"
android:summary="Edit name for profile2"
android:title="#string/profile2" />
<EditTextPreference
android:key="profile3"
android:summary="Edit name for profile3"
android:title="#string/profile3" />
<EditTextPreference
android:key="profile4"
android:summary="Edit name for profile4"
android:title="#string/profile4" />
<EditTextPreference
android:key="profile5"
android:summary="Edit name for profile5"
android:title="#string/profile5" />
EditNames class
public class EditProfileNames extends PreferenceActivity implements
OnSharedPreferenceChangeListener {
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.layout.prefs);
PreferenceManager.setDefaultValues(EditProfileNames.this,
R.layout.prefs, false);
for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
initSummary(getPreferenceScreen().getPreference(i));
}
}
#SuppressWarnings("deprecation")
#Override
protected void onResume() {
super.onResume();
// Set up a listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
#SuppressWarnings("deprecation")
#Override
protected void onPause() {
super.onPause();
// Unregister the listener whenever a key changes
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
#SuppressWarnings("deprecation")
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
updatePrefSummary(findPreference(key));
}
private void initSummary(Preference p) {
if (p instanceof PreferenceCategory) {
PreferenceCategory pCat = (PreferenceCategory) p;
for (int i = 0; i < pCat.getPreferenceCount(); i++) {
initSummary(pCat.getPreference(i));
}
} else {
updatePrefSummary(p);
}
}
private void updatePrefSummary(Preference p) {
if (p instanceof ListPreference) {
ListPreference listPref = (ListPreference) p;
p.setSummary(listPref.getEntry());
}
if (p instanceof EditTextPreference) {
EditTextPreference editTextPref = (EditTextPreference) p;
p.setSummary(editTextPref.getText());
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
resultOk();
}
return super.onKeyDown(keyCode, event);
}
/**
* Set the activity result to RESULT_OK and terminate this activity.
*/
private void resultOk() {
final Intent response = new Intent(Api.PREF_PROFILES);
setResult(RESULT_OK, response);
finish();
}
}
So what do I have to do to refresh the spinner? I know I could do it if the change was made in the OnItemSelectedListener but since it is an entirely different class that makes the changes I'm lost at the moment.
Thanks!
It sounds like you are passing a reference to your array, profileposition, to another class so that it can add elements to it. You will also need to pass a reference to adapter to that class as well, so that it can call adapter.notifyDataSetChanged(); after it has updated your array.
EDIT: Now that I see that you an Acitivty that you have started for a result is doing the updating of the array, you could just call adapter.notifyDataSetChanged(); in your onActivityResult() callback.
After changing the contents , call notifyDataSetChanged on the adapter and that will solve the issue.
Try this way
adapter.notifyDataSetChanged();
i'm trying to update my list in a preference with onPreferenceClick method. But the list isn't updated. onPreferenceClick is executed, because i got the names and showed it in the log, but not updated.
public class TransferPreference extends PreferenceFragment {
private TransferHelper transferHelper = new TransferHelper();
private ArrayList<String> names = new ArrayList<String>();
private CharSequence[] charSequence;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference_transfer);
final MultiSelectListPreference preferenceTeams = (MultiSelectListPreference) findPreference("preferenceTranser_multiSelectListPreference_teams");
preferenceTeams.setPersistent(false);
preferenceTeams.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
names = transferHelper.getServerTeams(getActivity());
int size = names.size();
charSequence = names.toArray(new CharSequence[size]);
preferenceTeams.setEntries(charSequence);
preferenceTeams.setEntryValues(charSequence);
return false;
}
});
}
}
I also tried this in onPreferenceClick:
Editor editor = preference.getEditor();
editor.clear();
names = transferHelper.getServerTeams(getActivity());
for (String name : names) {
editor.putString(name, name);
}
editor.commit();
If i put the following code direct in the oncreate method (and not in the listener method), the names are displayed. But only on its creation, like the name says :)
names = transferHelper.getServerTeams(getActivity());
int size = names.size();
charSequence = names.toArray(new CharSequence[size]);
preferenceTeams.setEntries(charSequence);
preferenceTeams.setEntryValues(charSequence);
Has anyone an idea?
Sorry for my bad english and thanks for help.
edit: i alos tried to add my code additional in this method, but no update.
#Override
public void onResume()
I have four checkboxpreferences in my preferencescreen that I would like to interact like a radiobuttongroup, meaning that you can only check one of them! If lets say the first is checked, and you like to check another one, its just the desired one checked, and the other ones is unchecked.
I did like this :
public class PreferenceActivity extends PreferenceActivity {
private SharedPreferences prefs;
private Editor editor;
private int keyItemChecked;
private CheckBoxPreference item1CheckBox, item2CheckBox, ..., itemICheckBox;
#SuppressWarnings("deprecation")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
addPreferencesFromResource(R.xml.prefs);
item1CheckBox = (CheckBoxPreference) getPreferenceManager().findPreference("item1");
item2CheckBox = (CheckBoxPreference) getPreferenceManager().findPreference("item2");
...
itemICheckBox = (CheckBoxPreference) getPreferenceManager().findPreference("itemI");
item1CheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference arg0) {
manageItem(1, item1CheckBox);
return true;
}
});
....
itemICheckBox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference arg0) {
manageItem(I, itemICheckBox);
return true;
}
});
}
private void manageItem(int i ,CheckBoxPreference pref) {
keyItemChecked = prefs.getInt("keyItemChecked",1); // 1 is your default checked item
if (! pref.isChecked() && keyItemChecked == i)
// If you click on the checked item, you don't want it to be unchecked :
pref.setChecked(true);
if (pref.isChecked() && keyItemChecked != i) {
editor = prefs.edit();
editor.putInt("keyItemChecked", i);
editor.commit(); // or editor.apply() if you use API > 9
unckeckOldItem(keyItemChecked);
}
}
private void unckeckOldItem(int item) {
switch (item) {
case 1:
item1CheckBox.setChecked(false);
break;
...
case I:
itemICheckBox.setChecked(false);
break;
}
}
You don't need to declare "keyItemChecked" on your prefs.xml.
The first time you call the activity, the data doesn't exist and
keyItemChecked = prefs.getInt("keyItemChecked",1);
will return 1.
Once you click on an other item than the default, the data will exist.
Looks like you can use http://developer.android.com/reference/android/preference/CheckBoxPreference.html#setDisableDependentsState%28boolean%29 to create that functionality. I think setting dependency of preferences can be done in xml.