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.
Related
I am just trying to change the value of a Preference when the PreferenceActivity has been opened. As there is no "setValue" or similar on a Preference, I try
My code:
long value = System.currentTimeMillis()/1000;
PreferenceManager.getDefaultSharedPreferences(getActivity()).edit().putString("test",""+value).apply();
getPreferenceScreen().findPreference("test").setSummary(""+value);
My XML:
<EditTextPreference
android:key="test" />
What I expect:
When clicking on my Preference, it should display the value of time (same than summary) and let me edit it.
What happen:
The value is only changed after I closed the Activity. Next time I open the screen, the value is correct (but as in fact already changed to the next one)
First attempt:
Let s say value is 1521143527. Correctly written in the summary, but when I click on the Preference, the popup display an empty value.
Second attemp:
Summary has changed to 1521143540. When I click on Preference, I can edit the previous value (1521143527)
Third attempt:
New Summary, but Preference value is not changed and is still: 1521143540
etc...
Any idea what is wrong?
DIRTY WORKAROUND:
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences);
Will now force the preference to update, but that's really dirty, and I still don't understand...
If you look into the PreferenceFragment source code ,you can see that there is a method called bindPreferences() which binds the preference values to Views . Only in 2 scenarios this method is called,
When Activity created onActivityCreated(#Nullable Bundle savedInstanceState)
When addPreferencesFromResource() called. there is a handler which triggers the bindPreferences()
Other than this there is no way the views are updated. bindPreferences() is a private method , so you can't call this method outside of the class. So you should update your preferences before either those events.
You mentioned, As a workaround solution, you should update your preference first then call addPreferencesFromResource() . Like below
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
long value = System.currentTimeMillis()/1000;
getPreferenceManager().getSharedPreferences().edit().putString("test",""+value).commit();
addPreferencesFromResource(R.xml.pref_general);
getPreferenceScreen().findPreference("test").setSummary(""+value);
}
The first time my android app is launched I bring up a preferencefragment because the user needs to initially make a selection from a list of items and their selection needs to be saved. I extend ListPreference to display the list of items.
The way it should work is the user selects an item from the presented list. This selection
gets saved in SharedPreferences and the app transitions to another fragment. All of this is
working, but for some reason the ListPrefence gets display a second time.
I've put in some logging and discovered that for some reason two ListPreference object are
being constructed...but I know of only one call to create it. I'm somehow missing where/why
the ListPreference constructor is called a second time.
My PreferenceFragment code is simple. It looks like
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("INIT", "ONCREATE");
addPreferencesFromResource(R.xml.inititems); // load from XML
There's only the addPreferencesFromResource() call. No other place in my fragment code
should (as far as I understand) cause the ListPreference to be instancitated, but
the logging tells me the ListPreference constructor is called twice and the fragment's
onCreate is called just once.
I'm going to try to do a stack trace from the ListPreference constructor, but I wanted to
see if anyone here has thoughts or suggestions beyond the stack trace. Why would the
constructor be called twice ?
Thanks!
-Mar
You possibly have referenced the fragment in your layout resource file using android:name="yourfragment" as well as at run-time in onCreate(). That would cause it to be loaded twice.
I have a strange problem, I have a few different items in my ListView, which are enabled/disabled based on a preference. They show up in their enabled/disabled state correctly based on the preference, but if they were visible in the list when you open up the preference activity, they wont go to their correct state until they move off screen and back
I've tried calling getListView().refreshDrawableState() onResume of the main activity that the ListView is in, but it didn't seem to do anything.
#Override
public void onResume(){
super.onResume();
getListView().refreshDrawableState();
}
I can't solve this problem. I have preference screen and there is sub-preference that opens up another screen. On that another screen change of items can be caught with OnSharedPreferenceChangeListener and I change summary in parent preference screen, but when I go back to that parent preference screen, summary did not changed.
Same question was asked here, but conclusion was not clear, and I could not solve this problem. It seems a common problem to me and I guess there is good solution for this.
Dose anyone know a solution for this problem?
There is one thing I like to keep: sub-preference is standard one, not custom.
I've solved this by adding OnPreferenceClickListener to the preferences which will change the summary in the main screen.
OnPreferenceClickListener viewUpdater = new OnPreferenceClickListener() {
#Override
public boolean onPreferenceClick(Preference preference) {
updateView();
return false;
}
};
Within the updateView() method I'm setting the summary to a new value and then I'm using the invalidateViews method of the preferences listview to trigger an update of the displayed summary
private void updateView() {
preference.setSummary(newSummary);
getListView().invalidateViews();
}
Check the answer of #jmbouffard that's work for me
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);
}