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.
Related
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);
}
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.
I'm trying to programmatically create a ListPreference, which I can do but when I select it, it's list of entries is empty. I believe I am correctly setting the setEntries() and setEntryValues() with CharSequence arrays, but it's just empty when I select it.
Please find below the ActivitySetting class. Please note I'm using PreferenceFragments as to not use deprecated methods. But I only have one PreferenceFragment which is currently set as default
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Display the fragment as the main content.
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefsFragment()).commit();
}
public static class PrefsFragment extends PreferenceFragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.settings);
// Create the new ListPref
ListPreference customListPref = new ListPreference(getActivity());
// Get the Preference Category which we want to add the ListPreference to
PreferenceCategory targetCategory = (PreferenceCategory) findPreference("TARGET_CATEGORY");
CharSequence[] entries = new CharSequence[]{"One", "Two", "Three"};
CharSequence[] entryValues = new CharSequence[]{ "1", "2", "3" };
// IMPORTANT - This is where set entries...looks OK to me
customListPref.setEntries(entries);
customListPref.setEntryValues(entryValues);
customListPref.setTitle("Title");
customListPref.setSummary("This is the summary");
customListPref.setDialogMessage("Dialog Message");
customListPref.setPersistent(true);
// Add the ListPref to the Pref category
targetCategory.addPreference(customListPref);
}
}
}
Here is the Setting.xml it just has the single PreferenceCategory which the ListPreference is added to:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Some Options" android:key="TARGET_CATEGORY">
</PreferenceCategory>
</PreferenceScreen>
Here is what I get. The ListPreference has been successfully but when I select it.... No entries :( I'm expecting the options: "One", "Two", "Three"
Found it if you set the setDialogMessage() then this overwrites the contents so by removing this line, it works now.
You might want to replace setDialogMessage() by setDialogTitle() to get the title back.
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(),""));
}
}