Android - How to hide a control in PreferenceFragment - android

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.

Related

Add footerview to PreferenceFragment List

I'm using a PreferenceFragment and want the version of my app to appear below the List that holds all the settings. I know for a normal ListView I could just do addFooterView(theTextView), but the PreferenceFragment doesn't provide access to doing this (no access to the ListView that is populated from preferences xml). Anyone have a slick way of doing this?
George's answer (Option 1) was on the right track, but I found it better to take it one step further than simply adding a preference. I created a custom preference by using the layout in the accepted answer here, and then was able to totally customize what I wanted to show by centering text, and even making the preference only appear under certain circumstances (for example, if the user has the most recent version, don't show the preference, etc.).
I used the Android docs on Settings to create a class that extends Preference to do the dynamic work needed.
You can add an empty preference item in the end of xml, then give it an custom layout.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- other preferences -->
<Preference app:layout="#layout/place_holder" />
</PreferenceScreen>
In your PreferencesFragment, just new a custom PreferenceCategory, then add it to PreferenceScreen. you can do your things in the onCreateView part of the custom PreferenceCategory.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
initPrefs();
PreferenceCategory preferenceCategory = new PreferenceCategory(getActivity()) {
#Override
protected View onCreateView(ViewGroup parent) {
super.onCreateView(parent);
View view =
getActivity().getLayoutInflater().inflate(R.layout.layout_infos, null);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getActivity(), "thanks", Toast.LENGTH_SHORT).show();
}
});
return view;
}
};
getPreferenceScreen().addPreference(preferenceCategory);
}

Inflating preferences dynamically in PreferenceFragmentCompat

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.

Get rid of extra padding above in PreferenceFragment

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.

Is it possible to create a preference screen with PreferenceFragment without using an XML resource?

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(),""));
}
}

how to show selected data into summary of list preferences

i am new to android programming .well in my application i have added the preference class and i am calling the xml preference which is stored in the xml folder of my application.this is the code for it
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference android:title="colors" android:key="colors"
android:summary="list of colors to choose from " android:entries="#array/list"
android:entryValues="#array/lvalues"></ListPreference>
</PreferenceScreen>
and in the java class i had written only one line that is this
addPreferencesFromResource(R.xml.prefs);
now i am able to show the preference class and also the list some colors data.
my question is on selecting the list preference it should show me the selected preference in to the summary attribute .currently it is showing me as 'list of colors to choose from'
what i want is to show the selected color say i have selected white the summary should show me as white.
please help me .
Thank you,
maddy.
you can actually do it in xml. Try this:
<ListPreference
android:key="pref_list"
android:title="A list of preferences"
android:summary="%s"
android:entries="#array/pref_list_entries"
android:entryValues="#array/pref_list_entries_values"
android:defaultValue="0" />
your selected value would replace "%s".
For further clarification read this post
In the other code example there is a little bug which causes that the old value is displayed and not the new one.
Here is a working version:
ListPreference splashList = (ListPreference) findPreference("splash");
splashList.setSummary(splashList.getEntry());
splashList.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
String nv = (String) newValue;
if (preference.getKey().equals("splash")) {
ListPreference splashList = (ListPreference) preference;
splashList.setSummary(splashList.getEntries()[splashList.findIndexOfValue(nv)]);
}
return true;
}
});
You need to extend ListPreference class and specify that in the xml file
class MyListPref extends ListPreference {
public void onClick (DialogInterface dialog, int which) {
this.setSummary(MyListPref.this.getEntry());
}
}
If your Custom Preference class name is com.sample.MyListPref the xml entry will be
<com.sample.MyListPref
android:key="pref_list"
android:title="List Preference"
android:dialogTitle="List Pref Dialog"
android:entries="#array/pref_items"
android:entryValues="#array/pref_items_values"/>
You dont need to do the extend listPreferences. in your PreferencesActivity file put as per my example:
final ListPreference defaultTown=(ListPreference)findPreference(getString(R.string.pref_default_town_key));
Log.i("try",defaultTown.getKey());
defaultTown.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
Log.i("theApp", "Selected = " + defaultTown.getValue());
defaultTown.setTitle(defaultTown.getValue());
return true;
}
});
on change the value will update the title
when you enter the application you will need to populate the title with your current preference though instead of colors which is set at default in your xml

Categories

Resources