I have a PreferenceScreen:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:id="#+id/checkBoxHighlightWeekends"
android:key="checkBoxHighlightWeekends"
android:summary="Weekends are different"
android:title="Highlight weekends" />
<MultiSelectListPreference
android:id="#+id/multiSelectListSelectWeekends"
android:key="multiSelectListSelectWeekends"
android:dialogTitle="Select weekends"
android:entries="#array/weekends"
android:entryValues="#array/weekends_values"
android:summary="Saturday, Sunday"
android:title="Select weekends"/>
</PreferenceScreen>
I'm trying to use only the "view" part of this and not make it write to it's default SharedPreferences. When user changes the preference, I manually check the changed data and send it to a MVVM repo, when then writes to my own custom SharedPreference. I plan to use LiveData to update the settings screen when it's opened. All this hassle because I'm trying to learn the MVVM architecture and Android in general.
Inside MainPreferenceFragment:
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings_main);
CheckBoxPreference checkBoxHighlightWeekends = getPreferenceManager().findPreference("checkBoxHighlightWeekends");
MultiSelectListPreference multiSelectListPreference = getPreferenceManager().findPreference("multiSelectListSelectWeekends");
checkBoxHighlightWeekends.setOnPreferenceChangeListener(changeListener);
multiSelectListPreference.setOnPreferenceChangeListener(changeListener);
}
Preference.OnPreferenceChangeListener changeListener = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object o) {
// Call method in ViewModel which will save settings state to SharedPrefs
Logger.alert("Something changed! " + preference.getKey());
return true;
}
};
Any change to settings triggers the function, however the checkbox stops working - It doesn't change to the "tick" state anymore.
How can I strip out all the default click/change functionality from the PreferenceScreen and make it into a dumb view?
Related
Okay so I'm trying to make sense of how Shared Preference works with Preference.
Below is part of an app that works, but I do not understand how it works for the part of Shared Preference.
I have a UserPrefActivity.java containing the following code
public class UserPrefActivity extends PreferenceActivity {
//a preference value change listener that updates the preference summary
//to reflect its new value
private static Preference.OnPreferenceChangeListener
sBindPreferenceSummaryToValueListerner = new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
//gets string value of object
String value = newValue.toString();
Log.e("in sBind Listener", value);
//if the preference is a list preference, get the value at a given index
if (preference instanceof ListPreference) {
//for list preference look up the correct display value
//in the preference entries array
ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(value);
//set the summary to reflect the new value
preference.setSummary(index >= 0 ? listPreference.getEntries()[index] : null);
} else {
//set summary to only value
preference.setSummary(value);
}
return true;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//call the deprecated method to load the preference screen
addPreferencesFromResource(R.xml.user_pref);
//get default Shared preference from preference screen
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
Preference saveNumPizza = findPreference("saveNumPizza");
//set the preference change listener to saveNumPizza
saveNumPizza.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListerner);
sBindPreferenceSummaryToValueListerner.onPreferenceChange(saveNumPizza,
PreferenceManager
.getDefaultSharedPreferences(this)
.getString(saveNumPizza.getKey(), ""));
}
}
In the MainActivity.java, I have the following as part of a bigger piece of code
//gets the default shared preference instance and assign to sharedPrefs for enabled save
// data
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences
(MainActivity.this);
//checks if save order status is true
if (sharedPrefs.getBoolean("saveOrder", false)) {
//do stuff..
}
I have the following UserPref.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:defaultValue="false"
android:key="saveOrder"
android:summary="for quick loading of favourite order"
android:title="Enable Saving Order"/>
<PreferenceCategory android:title="ORDER HISTORY">
<CheckBoxPreference
android:defaultValue="false"
android:key="keepHistory"
android:summary="of pizza orders"
android:title="Keep History"/>
<ListPreference
android:defaultValue="3"
android:dialogTitle="Choose how many to save"
android:entries="#array/number_of_pizza"
android:entryValues="#array/number_of_pizza_values"
android:summary="3 pizza orders"
android:key="saveNumPizza"
android:title="Number of Orders"/>
</PreferenceCategory>
</PreferenceScreen>
I know that in the UserPrefsActivity, I believe in the PreferenceManager.getDefaultSharedPreferences(this) call, the shared preferences is created and obtained if it does not exist, if it does its just obtained.
From what I've noticed with the app, is that on first launch when I get to the settings and launch the UserPrefActivity via intent, the shared preference of the UserPrefActivity is created, containing only the saveNumPizza key. However the minute I click on the other preferences (Checkbox preference) when I look at the shared preference file, I immediately see that the saveOrder key and keepHistory key are automatically saved.
I would just like to know how this automatic saving is exactly done since I am not using an editor to save it to the shared preference, nor am I calling apply or commit.
Thank you,
So I am trying to implement a preferences menu in my app. I used the standard generated template in android studio. THe issue is that now I can't figure out how save the values the user specifies. I thought about using a click listener to determine when a user clicked a checkbox and then getting the actual value of the checkbox and saving that to sharedpreferences, but I can't figure out how to do it.
Does anyone have any suggestions on how use onClick in a preference activity?
OK, we seem to be on the right track about the system storing the values automatically, but whenever I try to reference them from my main class, it always returns null. Here is my code:
boolean trueorfalse = PreferenceManager.getDefaultSharedPreferences(getActivity())
.getBoolean("my_key", false)
;
So I assume you've already defined your Preferences in res --> xml and it looks something like this:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="my_key"
android:summary="#string/desc_string"
android:title="#string/title_string" />
</PreferenceScreen>
As soon as the user checks or unchecks the CheckBox the systen will automatically create an entry in the default Preference-file which you can access like this:
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("my_key", false);
But back to your initial question: If you want to assign an onClick-Listener to your preference you have to do something like this:
Preference myPreference = (Preference) findPreference("my_key");
myPreference .setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
// do something
}
});
Note: In this example it isn't a CheckBoxPreference, it's just a simple Preference
I tried the same in my SettingsMenu by implementing OnSharedPreferenceChangeListener
public class SettingsMenu extends PreferenceActivity implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
Context context = getApplicationContext();
SharedPreferences menu_settings = PreferenceManager.getDefaultSharedPreferences(context);
menu_settings.registerOnSharedPreferenceChangeListener(this);
...
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// check the checkboxes
}
}
Hope it helps :)
In this preferenceScreen the user unlinks the device from his account. At the moment I just have it as Unlink device, once the user clicks it, the unlinking happens.
But I would like to add a piece text like this:
Joe Foo's Device (joefoo#gmail.com) - Unlink Device
Hoe would I do this? I also need to add the user name dynamically from settingsActivity.
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference android:title="#string/pref_title_advanced_unlink" >
<TextView somehow must be in here
android:id="#id/user_name_and_email" />
<intent android:action="android.intent.action.VIEW"
android:targetPackage="com.example.tvrplayer"
android:targetClass="com.example.tvrplayer.UnlinkActivity"
android.setflags="FLAG_ACTIVITY_CLEAR_TOP"/>
</Preference>
</PreferenceScreen>
preferences.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="pref_title_advanced"
android:title="Advanced" >
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_title_advanced_link"
android:title="Link Device" />
</PreferenceCategory>
</PreferenceScreen>
PrefsActivity.java
private SharedPreferences mPreferences;
private SharedPreferences.OnSharedPreferenceChangeListener mPrefListener;
private CheckBoxPreference mCheckBoxPref;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
mCheckBoxPref = (CheckBoxPreference) getPreferenceScreen().findPreference(
"pref_title_advanced_link");
/*
* set initial summary as you desire. For example, userIdCurrent can be:
* "No Devices linked."
*/
mCheckBoxPref.setSummary(userIdCurrent);
mPrefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
if (key.equals("pref_title_advanced_link")) {
/*
* set post-click summary as you desire. For example,
* userIdPost can be:
* "Joe Foo's Device (joefoo#gmail.com)".
*/
mCheckBoxPref.setSummary(userIdPost);
}
}
};
mPreferences.registerOnSharedPreferenceChangeListener(mPrefListener);
}
Preferences have a subtitle called summary. Give your preference a key, then you can use findPreference(CharSequence key) in your PreferenceFragment to get a reference to your preference object, sort of like calling findViewById to get references to Views. Then call setSummary(int) or setSummary(CharSequence) on the preference object.
Alternatively, you could do something entirely more complex by providing a custom layout for your preference objects and/or subclass Preference and implement some custom data binding. But I think the above should do what you want.
I'm use Android ICS SDK and I would like to do a PreferenceScreen which use MultiSelectListPreference (avalaible for API Level 11&+.
I just want to persist the value in SharedPref, refresh the summary of the MultiSelectListPreference and refresh the dialog list.
Here's my code :
Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.newgame);
mMultiCharacters.setOnPreferenceChangeListener(this);
}
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor settingsEditor = settings.edit();
settingsEditor.putStringSet( preference.getKey() , (Set<String>) newValue);
settingsEditor.commit();
//display new summary
initChar();
return false;
}
XML part :
<MultiSelectListPreference
android:entries="#array/characterNames"
android:entryValues="#array/characterNames"
android:key="pref_characters"
android:persistent="true"
android:title="Chars :" />
The behavior is quite strange. The dialog list doesn't refresh… some ideas ? Thanks!
Well.. I used MultiSelectListPreference once, and here is what I "think" ..
You are returning false in the onPreferenceChange listener, which I think it doesn't only NOT commit the changes, but also may be reverting to the previous values. I'm aware that you are committing the changes through settingsEditor but may be the false return is reverting back the old values, so I suggest returning true.
One more thing, the newValue object is actually a HashSet which contains the newly selected values, so you can use it to do whatever you want but you don't have to use it to commit changes if you are returning true.
Good Luck.
This question has been asked many times in this forum. But I feel it still need to be cleared for me .
public class PrefTest extends Activity {
public Button bt_start= null;
SharedPreferences mSharedPreferences;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.main);
bt_start = (Button) findViewById(R.id.button1);
bt_start.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.d("TEST","");
PreferenceManager.setDefaultValues(getApplicationContext(),
R.xml.settings_org, true);
mSharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
Boolean test = false;
test = mSharedPreferences.getBoolean("auto_launch_key", true);
Log.d("TEST","test = "+test);
}
});
super.onCreate(savedInstanceState);
}
#Override
protected void onStart() {
super.onStart();
}
}
In the above code
Log.d("TEST","test = "+test);
always prints true , though I have set default value in xml as false(as below)
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="settings" >
<CheckBoxPreference android:key="auto_launcvh_key"
android:summaryOn="..."
android:summaryOff="---"
android:title="auto_launch_string" android:defaultValue="false" />
</PreferenceCategory>
</PreferenceScreen>
Am expecting the setDefaultValues to take the defaults values form the XML and initialize the preference.
Am I wrong in my understanding?
UPDATE
On closer inspection I can see you probably aren't correctly retrieving the SharedPreference object. although I have not tried it, to make this test work I assume you would have to call getSharedPreferences (String name, int mode) with the name of your XML file to get the object which stores the values defined in your XML file.
getDefaultSharedPreferences (Context context) states:
Gets a SharedPreferences instance that points to the default file that
is used by the preference framework in the given context. Parameters
context The context of the preferences whose values are wanted.
Returns
A SharedPreferences instance that can be used to retrieve and listen
to values of the preferences.
Your file doesn't seem to be the default file and thus the preferences you are trying to call don't exist.
Generally the way to deal with preferences is to sub class a PreferenceActivity which will create a preferences interface but I appreciate you are just trying to write a simple test.
Also I assume the CheckBoxPreference android:key="auto_launcvh_key"is a typo when writing the question. I think I checked the key when first writing this answer and it was CheckBoxPreference android:key="auto_launch_key"
ORIGINAL
Firstly I would change test = mSharedPreferences.getBoolean("auto_launch_key", true); to test = mSharedPreferences.getBoolean("auto_launch_key", false); if it now returns false then the preference doesn't exist in the system so there is a problem with your environment. Try cleaning the project and re-installing.
Secondly in the docs it states
readAgain - Whether to re-read the default values. Note: this will NOT
reset preferences back to their default values. For that
functionality, use getDefaultSharedPreferences(Context) and clear it
followed by a call to this method with this parameter set to true.
Therefore if the preference already exists in the system as true this will not overwrite and so a re-installation should sort this out as well. or you could try calling clear() on mSharedPreferences and then calling PreferenceManager.setDefaultValues(getApplicationContext(), R.xml.settings_org, true);
If this doesn't work can you post complete XML.
The answer is actually very simple.
Boolean values in a preference file are only present when they are true so when reading the boolean value you need to set default value to false:
test = mSharedPreferences.getBoolean("auto_launch_key", false);
So when the preferences in xml is true it reads true and otherwise uses the default of getBoolean. I noticed while debugging there aren't any Boolean preferences with false as the value.