I want to have an element in my preference menu that does the following:
Show a list of options.
Many are selectable
Maximum amount of options to be chosen 2.
Possibilities I thought of:
Doing a separated PreferenceScreen and showing options as checkBoxes, but I don't know where to place the logic of max 2 options.
Extending DialogPreference and doing it by hand.
What's the best way?
Extending DialogPreference would get you the closest in terms of look-and-feel; the Preference classes are fairly unflexible and un-extendable in my experience.
I can't remember too much about PreferenceScreen, but I imagine it's similar.
In an app I worked on, we ended up using separate activities, launched via Intent from a Preference item onClick. This allowed us to easily develop preference screens that require validation logic a bit more complex than the usual.
You can put the logic of maximum two options in a OnSharedPreferenceChangeListener.
So you just listen to all the preferences as they change and update them if an invalid combination is selected.
So your code would be something like the following:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) {
//Code to calcuate how many are selected
int code = numberSelected();
if (count > 2) {
sharedPreferences.edit().putBoolean(key,false).commit();
Toast.makeText(this,"Can't select more than two!",Toast.LENGTH_LONG).show();
}
}
If you create your own PreferenceActivity that implements OnSharedPreferenceChangeListener you can enable the listener to be listening only when required doing something like this:
#Override
protected void onResume() {
super.onResume();
//Register the listener
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
#Override
protected void onPause() {
super.onPause();
// Unregister the listener
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
Related
Here's my use case.
The PreferenceActivity provides a selectable list of themes. When a user selects a particular theme from the list, I want the effect to take place immediately.
As of now, the change of theme affects all new activities that are launched but it does not affect the currently visible PreferenceActivity and activities on back stack.
To overcome this, I decided to implement a Sharedpreference change listener which on change would clear all old activities from the backstack and restart the same class with the modified theme.
Here's what I tried.
SharedPreferences.OnSharedPreferenceChangeListener spChanged = new
SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Intent newIntent = new Intent(Settings.this,Settings.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
}
};
I tried simple log message like Log.e("change", "pref changed");
But it seems, this listener is simply not listening for changes.
Register it with SharedPreferences.registerOnSharedPreferenceChangeListener.
Also, keep in mind that the listener is kept in a WeakHashMap. This means that you cannot use an anonymous inner class as a listener, as it will become the target of garbage collection as soon as you leave the current scope. So make your listener an instance variable of your activity or make the activity itself implement the listener.
Is there a way to find out when the user closes a particular preference screen? I need to do some updating when the user has changed the preferences in one of my preference screens. Not when the user clicks an actual checkbox, but rather when they press the back button and are done editing the preferences.
So far, all I've been able to find is that I can override my PreferenceActivity's onPause() event, which seems to happen when the user closes the preferences. It works, but I'm not sure this is the best way of going about it. Any suggestions?
EDIT
I couldn't figure out how to actually call a method of my main activity from within the PreferenceActivity. Tried playing around with putExtra() and all sorts of stuff. Eventually i figured - why not do the completely opposite? So instead I implemented the onResume() method in my main activity. Works great for doing stuff when the user closes the preferences, and I can live with the fact that my update method runs every time I resume my app as well.
Well I have been searching for a solution of this issue for weeks up to 2 min ago...
i think i found the way.
Preference myPrefScreen = findPreference("myPrefScreen");
myPrefScreen
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference prefScreen) {
// TODO Auto-generated method stub
Dialog prefScreenDialog = ((PreferenceScreen) prefScreen)
.getDialog();
prefScreenDialog
.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface arg0) {
// TODO Auto-generated method stub
///HERE YOU CAN EXECUTE WHATEVER YOU WANT...
}
});
return false;
}
});
You need OnPreferenceClickListener to correctly instantiate the PreferenceScreen Dialog generated only once the PreferenceScreen entry has been tapped on the screen and the new window with the preference children are shown. Otherwise you always getDialog() returns null and there's no way to attach the OnDismissListener to it.
Once you set the OnDismissListener the trick is done!!
I hope this could help.
Happy coding to all!!
That's the best way to go about it: overriding the onPause() method. It's called right before your activity leaves the foreground.
onPause is the right place to handle and update.
Can anyone give me an example or explain me how i subscribe to the
onDialogClosed method of an EditTextPreference?
http://developer.android.com/reference/android/preference/EditTextPreference.html#onDialogClosed%28boolean%29
I want to know when a dialog had its OK button clicked
and then retrive the information from the EditTextPreference.
Is there any examples/tutorials of this available or can anyone point
me in the right direction?
Thank you.
Just for completion: Since EditTextPreference is a Preference, you can use a OnPreferenceChangeListener. That will be called when the preference is changed. Check for the EditTextPreferences key in the callback and retrieve the new value to act on it. This is especially useful when the preference can be changed in more than one place or will be changed in the background by your app (e.g. writing defaults back when clicking a "default settings" button), since every change will trigger that callback (when your register it global on your SharedPreferences). The onDialogClosed will only be triggered when the user closed the actual dialog.
If you want to watch the single preference you can also use the EditTextPreference.setOnPreferenceChangedListener() function to assign a listener to that preference only.
OnPreferenceChangeListener documentation
You can make something like that :
#Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
String text=MyEditText.getText();
}
else {
// cancel hit
}
}
I have a PreferencesActivity with a nested PreferenceScreen, so the PreferenceScreen has its own line in the list of preferences, and when you click on it, you're presented with a few more options.
When the user changes one of those options, I update that option's summary to show what the user has selected.
I also want to change the summary of the PreferenceScreen on the main list to show the values of its sub-settings. I'm using an OnSharedPreferenceChangeListener to update both summaries at once. However, only the summary of the preference gets changed, not the summary of the preference screen.
Here is simplified code:
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(SUB_PREFERENCE)){
updateSubPreferenceSummary(); //works
updatePreferenceScreenSummary(); //doesn't work
} else if (key.equals(SOME_OTHER_PREF_IN_ROOT_OF_PREFERENCEACTIVITY) {
updatePreferenceScreenSummary(); //works. (not what I want--just illustrating issue)
}
}
My theory is that Android is ignoring the first screen when it's not visible, so it doesn't get updated. I tried overriding onBackPressed(), but that doesn't work either.
I found a work-around. Apparently, the summary was getting updated, but the view from the parent screen was not getting invalidated/redrawn.
So I do this after updating the summary:
mHandler.post(new Runnable(){
public void run(){onContentChanged();
}});
I put it in the Handler just as a precaution, because I'm not sure what thread the onSharedPreferenceChanged() gets called from.
I'm making a fairly basic game. In my preferences, there's an option to change the difficulty setting. I'd like to be able to somehow, in the main activity that called it, sense if they've changed the difficulty. (And then restart the game)
I'm having difficulty because of how the preference activity is handled asynchronously. If I add logic to check the value before and after sending the intent to my PreferenceActivity (from a menu selection), it really doesn't work...
Can someone point me in a proper direction as to either how to serialize a chunk of code normally handled asynchronously, or have an idea of how to sense preferences changed? Is there a listener class hidden somewhere?
For posterity's sake, here's the code handling the intent and how I'm failing. (snippet, from inside menu onOptionsItemSelected, inside a switch)
case R.id.menuOptions:
String currentDifficulty = preferences.getString("difficulty","problem!");
Intent i = new Intent(this, prefs.class);
startActivity(i);
if (currentDifficulty.equals(preferences.getString("difficulty","problem!")))
return true;
else doNewGame();
return true;
Android allows you to register a preference changed listener. Here's a quick example:
public class myClass implements OnSharedPreferenceChangeListener
{
private SharedPreferences settings;
settings = PreferenceManager.getDefaultSharedPreferences(this);
settings.registerOnSharedPreferenceChangeListener(this);
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
// Process it here
}
}
OnPreferenceChangeListener You can use it to very easily listen for preference changes.
The OnPreferenceChangeListener is a good idea, but you could also start your preference activity using startActivityForResult(). Your activity is then notified in onActivityResult() after the preference activity returns (you should override it to handle preference changes).