I'm using the PreferenceFragmentCompat from the support library (preference-v14:23.0.1 - although I've also tried it with 23.1.1). I have all my preference settings in an XML file and inflate them in onCreatePreferences as normal:
#Override
public void onCreatePreferences(final Bundle bundle, final String s) {
addPreferencesFromResource(R.xml.fragment_settings);
When the fragment is first shown I want to hide some of the preferences until I get the results of a network call back where I may want to show those preferences again.
I tried setting the visibility on various preferences to false in the hope that I would then be able to set them visible again later but it looks like :
Preference preference = findPreference(getString(R.string.settings_key_value));
preference.setVisible(false);
Effectively removes the preference from the list and when I try the find on the Preference again later it returns null.
As an alternative, I then created a method to create preference that I could then add to the relevant screen/position in the adapter:
private Preference createPreference(#StringRes int title, #StringRes int key, #StringRes int summary, int order) {
final Preference preference = new Preference(getContext());
preference.setTitle(title);
preference.setKey(getString(key));
if (summary > 0) {
preference.setSummary(summary);
}
preference.setOrder(order);
return preference;
}
I then use it as follows:
final PreferenceCategory category = (PreferenceCategory) findPreference(getString(R.string.settings_category_name));
preference = createPreference(R.string.pref_title, R.string.settings_pref_key, R.string.pref_summary, 0);
category.addPreference(preference);
However, when I do this the font size of the preference title is incorrect (and possibly other stylings within the Preference). This is presumably because the attribute set of the preference is not set and it's not inheriting the preference style from my app theme. Is there a way to either inflate an individual preference correctly from xml so that it has the correct styling and add it to my preferences list or to modify the createPreference method so that it will use the correct styling?
My AppTheme is defined with the following pertinent attribute:
<item name="preferenceTheme">#style/PreferenceThemeOverlay.v14.Material</item>
Use themed context created by addPreferencesFromResource for you dynamic properties. Get and keep it the following way:
Context styledContext;
#Override
public void onCreatePreferences(Bundle bundle, String s) {
addPreferencesFromResource(R.xml.preferences);
styledContext=getPreferenceScreen().getContext();
....
}
In case you hide (removes) some properties and need to back them from XML use th following code line:
setPreferenceScreen(
getPreferenceManager().inflateFromResource(
styledContext,
R.xml.preferences,
null)
);
You can just keep a reference to the Preference in a field and setVisible(true) later.
setVisible(false) removes the Preference from the hierarchy but setVisible(true) will re-add it to the hierarchy.
Related
I am trying to build a preference screen for my app. I have created a class called SettingsFragment which extends from PreferenceFragment. I am not loading preference items from xml because I need to load some data dynamically. That's why I am building everything programmatically. Everything is showing as expected. But there is some extra padding at the top. See the image below:
I am not sure why it's happening. Here is the code below I wrote in the SettingsFragment class:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
root.setTitle("Hello World");
PreferenceCategory cat1 = new PreferenceCategory(root.getContext());
root.addPreference(cat1);
ListPreference lang = new ListPreference(root.getContext());
lang.setEntries(new CharSequence[]{"English", "Bangla"});
lang.setEntryValues(new CharSequence[]{"en", "bn"});
lang.setTitle("Choose Language");
lang.setSummary("English");
cat1.addPreference(lang);
CheckBoxPreference check = new CheckBoxPreference(root.getContext());
check.setTitle("Title Check");
cat1.addPreference(check);
setPreferenceScreen(root);
}
FYI, I am using NavigationDrawer in my app. This SettingsFragment loads when a navigation item is clicked from the drawer.
You are trying to add a PreferenceCategory with no title, which is causing the empty space.
The following line is the problem:
PreferenceCategory cat1 = new PreferenceCategory(root.getContext());
root.addPreference(cat1);
So you can add title to your preference category like this :
PreferenceCategory cat1 = new PreferenceCategory(root.getContext());
cat1.setTitle("Category");
root.addPreference(cat1);
If you don't want a preference category, you can modify your code like below:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
root.setTitle("Hello World");
ListPreference lang = new ListPreference(root.getContext());
lang.setEntries(new CharSequence[] { "English", "Bangla" });
lang.setEntryValues(new CharSequence[] { "en", "bn" });
lang.setTitle("Choose Language");
lang.setSummary("English");
root.addPreference(lang);
CheckBoxPreference check = new CheckBoxPreference(root.getContext());
check.setTitle("Title Check");
root.addPreference(check);
setPreferenceScreen(root);
}
Check your layout file for the Fragment and its parent Activity, usually when you create a new project or layout/screen, there will be an automatic padding provided on your android layout file.
Go into your layout of Fragment. You will see below tags in Main/Parent Layout.
like this android:paddingBottom or android:paddingTop remove these.
Alternatively if you want to remove this padding from every fragments/activitys/layouts. go to the dimen.xml and make activity_vertical_margin as 0. It gets default value as 16dp.
In my preferences UI, I need to hide a preference based on certain conditions.
public class MyFragment extends PreferenceFragment {
public void onCreate(Bundle state) {
addPreferencesFromResource(...);
ListPreference myList = (ListPreference) findPreference("myid");
...
if (condition) {
// hide myList
}
}
}
I cannot seem to find any method either on ListPreference or on PreferenceFragment to hide it from being shown in the UI. Would appreciate if you can point me in the right direction.
After much debugging, turns out it was quite simple. Here is what you need to do:
First, obtain the PreferenceCategory the item belongs to. Next, just call removePreference on it.
PreferenceCategory myCategory = (PreferenceCategory) findPreference("myPrefCategory");
myCategory.removePreference(myList);
For those wondering how to remove item that has no parent category - you should name your root like this:
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="root_preferences">
<PreferenceCategory
android:title="Developer tools"
android:key="dev_tools_category">
Then for example:
if (!BuildConfig.DEBUG) {
PreferenceScreen rootPreferences = (PreferenceScreen) findPreference("root_preferences");
PreferenceCategory devCategory = (PreferenceCategory) findPreference("dev_tools_category");
rootPreferences.removePreference(devCategory);
}
In example above "dev_tools_category" could be any preference widget or like I showed - a category.
You can just use the inherited methods from the Preference superclass.
myList.setShouldDisableView(true);
myList.setEnabled(false);
The first will make the backing view of the preference disappear when the preference is disabled, the second will actually disable the preference.
I am currently able to create a preference screen with a PreferenceFragment, in which I assign my preferences using:
addPreferencesFromResource(R.xml.preferences);
Instead of using the resource 'R.xml.preferences', I would like to use my SharedPreferences i have already saved, for example:
SharedPreferences prefs = this.getActivity().getSharedPreferences("preferences", 0);
addPreferencesFromResource(prefs);
However, this does not work. Is it possible to do this? If so, How? Or is it required that I use an xml document?
I happen to had exactly the same problem but I figured it out, hope this helps.
You need to do the following steps in order to add a Custom Preference without using an XML Reouser
First:
You need to create a Preference Screen, this is as it says a "screen" which can containt several Preferences and must be linked to your PreferenceFragment or PreferenceActivity.
Consider the Following PreferenceFragment for example (and consider it is contained in a superior Activity..)
public static class YourPreferenceFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceScreen p = createPreferences();
this.setPreferenceScreen(p);//Set the PreferenceScreen as the current one on this fragment
//now bind values, notice we use p.findPreference which means whe look into the preferenceScreen Associated with the PreferenceFragment/Activity
bindPreferenceSummaryToValue(p.findPreference("some_key"));
}
}
Now Consider that createPreferences is a method that will return a PreferenceScreen with your custom preferences such as a ListPreference or CheckboxPreference. This is how you really create the preferences and add them into a PreferenceScreen
private PreferenceScreen createPreferences()
{
PreferenceScreen p =
getPreferenceManager().createPreferenceScreen(getActivity());
ListPreference listPref = new ListPreference(getActivity());
listPref.setKey("some_key"); //Refer to get the pref value
CharSequence[] csEntries = new String[]{"Item1","Item2"};
CharSequence[] csValues = new String[]{"1","2"};
listPref.setDefaultValue(-1);
listPref.setEntries(csEntries); //Entries(how you display them)
listPref.setEntryValues(csValues);//actual values
listPref.setDialogTitle("Dialog title");
listPref.setTitle("Title");
listPref.setSummary("Some summary");
p.addPreference(listPref);
return p;
}
Please let me know if this helps
best,
EDIT: Code for bindPreferenceSummaryToValue
private static void bindPreferenceSummaryToValue(Preference preference) {
// Set the listener to watch for value changes.
preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
// Trigger the listener immediately with the preference's
// current value.
if (preference instanceof CheckBoxPreference) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager.
getDefaultSharedPreferences(preference.getContext()).
getBoolean(preference.getKey(),false));
} else {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, PreferenceManager.
getDefaultSharedPreferences(preference.getContext()).
getString(preference.getKey(),""));
}
}
I am trying to change the entryvalue of a listpreference depending on wether a checkbox is ticked or not...
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);{
if(sharedPrefs.getBoolean("french", false))
{
Preference newsPref = (Preference) findPreference("news_feed");
newsPref.setDefaultValue("#array/newsfeedfr");
}
else
{
Preference newsPref = (Preference) findPreference("news_feed");
newsPref.setEntryValues("#array/newsfeed");
}
}
i get errors on the .setEntryValue with this:
The method setEntryValues(String) is undefined for the type Preference
One issue that you have is in how you're referencing your array values. #array/newsfeed is used in XML files, not Java!
You probably want to use getResources().getStringArray(R.array.newsfeed) or similar. Source.
Another issue is that setEntryValues() isn't defined for Preferences, you need to initialise as a ListPreference instead.
I'm new at android. I have a little idea over sharedPreference. Some tutorials say to add preferences in a xml file, but I need to add preferences dynamically. So I done that from a java class(my settings page).
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
CheckBoxPreference checkboxPref = new CheckBoxPreference(this);
checkboxPref.setKey("1");
checkboxPref.setTitle("SomeRandomStuff");
root.addPreference(checkboxPref);
Now, Now I need to get title of all selected checkbox (true) from that settings page to show which option been selected.
How can I do that?
thank you.
you can use a regular checkbox and sharedPreferences. Just add it's state like this
// global variables
SharedPreferences data;
public static String filename = "prefs";
// setup the SharedPreferences in onCreate()
data = getSharedPreferences(filename, 0);
// set the SharedPreference based on checkbox state
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
switch (arg0) {
case R.id.checkBox1:
boolean checked = checkBox1.isChecked();
SharedPreferences.Editor e = dataAddHS.edit();
e.putBoolean("preferenceName", checked);
e.commit();
break;
}
then when you need to pull the preference state, just do
boolean checked = data.getBoolean("preferenceName", false);
then you can use an if statement to see if checked is true or false, etc.
From what you're saying, it sounds like all you need is a default value for the preferences you will be working with. To be specific, you may have a bunch of checkbox-preferences that you want to use. When you read them, you can use the getBoolean method to get their values.
Note that the getBoolean method takes a second argument, which is the default value to return.
This means that you don't have to set the preferences dynamically. You use getBoolean to read the preferences and if the preferences have not been set by the user, a default value that you specify will be returned.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.getBoolean("whether_user_wants_setting1", false);