Programmatically Creating ListPreference - But Entry List is Empty - android

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.

Related

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.

Android - How to hide a control in PreferenceFragment

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.

Dynamically fill a ListPreference

I am trying to fill a ListPreference with the contents of the res/anim folder but I am having a problem it keeps coming up blank, I have a static array of strings to fill it and that works but I need it to be dynamic, I can print the text out in the logcat, its just not populating the list can you help me?
PreferenceActivityMenu.java
CharSequence[] entries = null;
CharSequence[] entryValues = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
SharedPreferences prefs=getPreferences(Context.MODE_PRIVATE);
ListPreference prefListAnim = new ListPreference(this);
listAnim();
prefListAnim.setEntries(entries);
prefListAnim.setEntryValues(entryValues);
}
#Override
public boolean onPreferenceClick(Preference preference) {
// TODO Auto-generated method stub
return false;
}
public void listAnim() {
Field[] fields = R.anim.class.getFields();
entries = new String[fields.length];
entryValues = new String[fields.length];
for (int count = 0; count < fields.length; count++) {
Log.i("Raw Asset: ", fields[count].getName());
entries[count] = fields[count].getName();
entryValues[count] = Integer.toString(count);
}
}
and preference.xml
<PreferenceCategory android:title="Animation Transitions" >
<ListPreference
android:dialogTitle="#string/prefsList_dialogTitle"
android:key="prefList_animations"
android:summary="#string/prefsList_summary"
android:title="#string/prefsList_title" >
</ListPreference>
</PreferenceCategory>
Thanks for your help
You are setting the list data to a different preference than the one declared in xml. Currently you're setting the data against a newly created ListPreference:
ListPreference prefListAnim = new ListPreference(this);
However, you're displaying the (empty) one declared in xml. You should do either one or the other. For example, the easiest solution is probably to change above to inflate the preference from xml in stead:
ListPreference prefListAnim = (ListPreference) findPreference("prefList_animations");

ListPreference summary not formatting

I have a ListPreference and I want to show the current entry in the summary. According to the docs for ListPreference.getSummary(), I'm supposed to be able to do this by including %s in the summary string. Unfortunately, the activity just displays the %s in the summary.
The XML is pretty standard:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="displayMode"
android:summary="#string/display_mode_summary"
android:title="#string/display_mode"
android:defaultValue="BOTH"
android:entries="#array/displayModes"
android:entryValues="#array/displayModeValues"
/>
</PreferenceScreen>
The value of the string display_mode_summary is just %s. (The value "BOTH" is present in the displayModeValues array.) If I subclass ListPreference like this:
public final class DisplayModePreference extends ListPreference {
// ...
#Override
public CharSequence getSummary() {
return String.format(super.getSummary().toString(), getEntry());
}
}
then when the preferences activity starts, the current value is correctly interpolated into the summary. But when I click on the preference and select a different value from the dialog, when the dialog closes the summary still shows the now-old value. I need to close the preferences activity and restart it to see the change.
I've tried this in several emulators at different API levels. What do I need to so that the displayed summary always reflects the current value?
You could override "onDialogClosed" as below:
#override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
setSummary(getEntry());
}
}
This will set the summary of your preference to the text of the selected entry.
The original getSummary() in ListPreference only works when getEntries(), getEntryValues() and defaultValue are pre-populated when the Preference screen loads. So it works fine when you use a static fixed list of items, like a <string-array> resource.
But if you are dynamically generating the entries and entryValues at runtime, you need to ensure that these lists are generated when the Preference screen loads in onCreate() and also ensure that the defaultValue is set. Something like this:
SettingsFragment.java
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ListPreference listPreference = (ListPreference) findPreference("dynamiclistItems");
CharSequence[] entryDisplayNames = new CharSequence[3];
entryDisplayNames[0] = "Item A";
entryDisplayNames[1] = "Item B";
entryDisplayNames[2] = "Item C";
CharSequence[] entryValues = new CharSequence[3];
entryValues[0] = "Item A Value";
entryValues[1] = "Item B Value";
entryValues[2] = "Item C Value";
listPreference.setEntries(entryDisplayNames);
listPreference.setEntryValues(entryValues);
if (listPreference.getValue() == null ||
listPreference.getValue().equals("")) {
// There is no stored string in shared prefs.
// The user has not chosen any value. So make
// the summary display a default entry "Item A"
// display name, which is item 0 in the 'entries' list. Info:
// https://stackoverflow.com/questions/5197228/how-to-set-the-default-value-of-a-listpreference
listPreference.setValueIndex(0);
}
}
For static lists that are populated with <string-array>, just ensure that android:defaultValue="..." is defined, and that it points to a valid item in the 'values' array. For example: android:defaultValue="Item A Value"
This will ensure that the android:summary="%s" will work properly for dynamically generated and static lists.

Dynamic ListPreference in android

How to generate dynamic listPreference in android?
I want to get all wifi access points and make a list using in preference Activity(i.e. make a list using listpreference).
How to do this?
Every XML element in Android can be created programmatically as the element name is also a Java class. Hence you can create a ListPreference in code:
CharSequence[] entries = { "One", "Two", "Three" };
CharSequence[] entryValues = { "1", "2", "3" };
ListPreference lp = new ListPreference(this);
lp.setEntries(entries);
lp.setEntryValues(entryValues);
You could alternatively create it in XML then add the entries/entry values in code:
CharSequence[] entries = { "One", "Two", "Three" };
CharSequence[] entryValues = { "1", "2", "3" };
ListPreference lp = (ListPreference)findPreference("list_key_as_defined_in_xml");
lp.setEntries(entries);
lp.setEntryValues(entryValues);
For creating a dynamic list preference, u need to create a preference activity (ie to extend an activity as PreferenceActivity).
The following code can be used to create the list dynamically.
// Root
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
dialogBasedPrefCat.setTitle("Category Title");
root.addPreference(dialogBasedPrefCat); //Adding a category
// List preference under the category
ListPreference listPref = new ListPreference(this);
listPref.setKey("keyName"); //Refer to get the pref value
listPref.setEntries("Array of values");
listPref.setEntryValues("Array of item value");
listPref.setDialogTitle("Dialog Title");
listPref.setTitle("Title");
listPref.setSummary("Summary");
dialogBasedPrefCat.addPreference(listPref); Adding under the category
return root;
Hope this helps to get an !dea...
EDIT:
Create and add values to CharSequence[] like this:
CharSequence[] cs = new String[]{"myValue"};
This minimalist technique is for both environments.
In preferences.xml
<!-- NB: Dynamic array insertion for 'entries'/'entryValues' -->
<ListPreference
android:key="xyzzy"
android:title="..."
android:summary="..."
android:numeric="integer"
android:defaultValue="0"
android:layout="?PrefLayoutDtl"
/>
In PreferenceFragment.onCreate()
addPreferencesFromResource(R.xml.preferences);
expand_xyzzy((ListPreference)findPreference("xyzzy"));
Elsewhere
public static Preference expand_xyzzy (ListPreference pref) {
if (pref == null) return pref;
pref.setEntries(new String["one","two","three];
pref.setEntryValues(new String["0","1","2"]);
return pref;
}
Notes:
(a) XML is self-documenting and perhaps a better choice than dynamic preference creation.
(b) Starting your PreferenceFragment by NOT using PreferenceActivity easily lets you do this:

Categories

Resources