I am currently building out a list of rows with checkboxes dynamically using content from a web service. However, this ListView will need to do pretty much what a PreferenceActivity would accomplish.
I don't know the number of rows as the content is dynamic so I can't create each CheckBoxPreference in XML. How do I go about building a PreferenceActivity that will display an unknown number rows with a CheckBoxPreference dynamically?
I think you're looking for something like this:
public class MyPreferenceActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.my_preference_activity);
//fetch the item where you wish to insert the CheckBoxPreference, in this case a PreferenceCategory with key "targetCategory"
PreferenceCategory targetCategory = (PreferenceCategory)findPreference("targetCategory");
//create one check box for each setting you need
CheckBoxPreference checkBoxPreference = new CheckBoxPreference(this);
//make sure each key is unique
checkBoxPreference.setKey("keyName");
checkBoxPreference.setChecked(true);
targetCategory.addPreference(checkBoxPreference);
}
}
Well #Jodes, actually both of you are right, but the correct way of doing this would be using a ListPreference.
I would use a entire programmatic approach, from my experience it's easier to be consistent; either create an entire XML layout via code, or via XML, but mixing the 2 can be weird and you cannot alter everything set via XML...
onCreate(){
this.setPreferenceScreen(createPreferenceHierarchy());
}
public PreferenceScreen createPreferenceHierarchy(){
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
// category 1 created programmatically
PreferenceCategory cat1 = new PreferenceCategory(this);
cat1.setTitle("title");
root.addPreference(cat1);
ListPreference list1 = new ListPreference(this);
list1.setTitle(getResources().getString(R.string.some_string_title));
list1.setSummary(getResources().getString(R.string.some_string_text));
list1.setDialogTitle(getResources().getString(R.string.some_string_pick_title));
list1.setKey("your_key");
CharSequence[] entries = calendars.getCalenders(); //or anything else that returns the right data
list1.setEntries(entries);
int length = entries.length;
CharSequence[] values = new CharSequence[length];
for (int i=0; i<length; i++){
CharSequence val = ""+i+1+"";
values[i] = val;
}
list1.setEntryValues(values);
cat1.addPreference(list1);
return root;
}//end method
However, using this approach you will run into the platform's limitations of not having a multiple select ListPreference, and you'll probably want to implement something else.
I found this solution, which works great. You'll have to read the comments to find clues about how to debug the code though...
You need a ListView for that, a PreferenceActivity. As discussed in this link, PreferenceActivity should only be used for actually saving preferences.
Instead you could either create a simple dialog with single or multiple choice options:
http://developer.android.com/guide/topics/ui/dialogs.html
Or use a ListView as in the API examples Google provides, they give a simple example:
http://hi-android.info/docs/resources/samples/ApiDemos/src/com/example/android/apis/view/List10.html
Use PreferenceFragmentCompat from Preference Compat Library
compile 'com.android.support:preference-v7:23.4.0'
Check this article for the implementation details https://medium.com/#arasthel92/dynamically-creating-preferences-on-android-ecc56e4f0789#.71ssvjses
Related
Hi I want to create preferences in my application but I cannot use resources at all due to some dependency issues.
I am able to do this using the below code:
public class DTMainActivity extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setPreferenceScreen(defaultPref());
setDependencies();
}
// The first time application is launched this should be read
private PreferenceScreen defaultPref() {
PreferenceScreen root = getPreferenceManager().createPreferenceScreen(this);
SwitchPreference dLogTracingEnablePref = new SwitchPreference(this);
dLogTracingEnablePref.setTitle(R_Class.R_String.dLogTracingEnablePrefString);
dLogTracingEnablePref.setDisableDependentsState(false);
dLogTracingEnablePref.setChecked(true);
dLogTracingEnablePref.setKey(R_Class.R_String.dLogTracingEnablePrefKey);
root.addPreference(dLogTracingEnablePref);
}
I would want to do this using the new fragment based approach, without using the deprecated APIs like getPreferenceManager etc.. I can create all the other UI layout elements like linearlayout etc.. without any resources, but when it comes to preferences and PreferenceFragment class, all that is available is addPreferencesFromResource() which would need an XML. Can any one help me here please?
I managed to made it using a PreferenceFragment, without addPreferencesFromResource(),
Instead I just created the PreferenceScreen like you just did and used
try using the bindPreferenceSummaryToValue, consider "p" being a PreferenceScreen with Preferences already added into it, (and also that has been created and configured previously)
PreferenceScreen p = createPreferences();//a method that creates a PreferenceScreen and add some preferences into it
this.setPreferenceScreen(p);
bindPreferenceSummaryToValue(p.findPreference("preference_key"));
I responded to someone with a similar problem here .. perhaps you can check it out
i wish to show a listView on a PreferenceActivity similar to what the android OS wifi-settings has for the list of networks (example here , on the bottom area of the image) .
however , such a thing isn't availabe , so i've created a new class that extends Preference , and what i returned in the onCreateView is just a ListView instance .
it worked , but the listView has a constant size of about a single item no matter what i do to its layoutParams and no matter what i do to the adapter . even if i set the adapter inside the onCreateView , it has the exact same size .
not only that , but the listView cannot be scrolled , even though it is clear that it has multiple items within it .
i would , of course, want to use the same text size standard as on all of the preferences , to give a native feeling.
can anyone please tell me what can be done in order to make it work well?
btw, the app should work for android API 10+ (minimum 10) .
In case you are going for the same appearance / behavior, you should stay with the plain PreferenceActivity implementation, and add the new preference items into the "list" dynamically from code (eventually with custom renderers).
A basic implementation of such display would be:
/**
* This variable stands for the items with which you want to populate the list
*/
final HashMap<String, String> networks = new HashMap<String, String>();
final PreferenceCategory cat = new PreferenceCategory(getApplicationContext());
cat.setTitle(R.string.wifinetworks); // holding "Wi-fi networks"
for (final String networkTitle : networks.keySet())
{
final Preference pref = new Preference(getApplicationContext());
pref.setTitle(networkTitle);
pref.setSummary(networks.get(networkTitle));
cat.addPreference(pref);
}
Edit: For adding custom components to an existing PreferenceActivity, you should give a try to the addContentView method. From within onCreate:
final LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
addContentView(buttonBar, params);
ok , the answer would be to use setContentView to whatever layout you wish (including any views you wish) , add there a listView for the preferences , and for this listView , call bind and setAdapter.
i've found this solution by looking at other solutions, like this one:
http://kmansoft.com/2011/08/29/implementing-long-clickable-preferences/
I have PreferenceActivity with plenty of PreferenceCategories defined in it. If I have the android:key of a given category.
Is it possible programmatically to scroll the Activity to this category?
I know this is an old answered question, but I found a better way than iterating through all the categories.
PreferenceCategory myCat = (PreferenceCategory) findPreference("myKey");
int position = myCat.getOrder();
getListView().setSelection(position);
You can iterate through the preferences in the activity like this:
PreferenceScreen screen = getPreferenceScreen();
int i;
for(i = 0; i < screen.getPreferenceCount(); i++) {
String key = screen.getPreference(i).getKey();
// be careful, because key will be null if no android:key is specified
// (as is often the case for PreferenceCategory elements)
if("myKey".equals(key))
break;
}
// PreferenceActivity extends ListActivity, so the ListView is accessible...
getListView().setSelection(i);
Tested out with Android SDK 14 and it works fine.
Caution though, calling getListView().setSelection(i) inside onCreate or onResume has no effect. It has to be called after the activity is drawn.
The getPreferenceCount() method counts all PreferenceCategories and their nested preferences. Not sure what it does for PreferenceScreens, although I'm sure a little experimentation there would be revealing.
In my setting page I have a preference which fetches a list of toggle-able settings that I wanted to display as individual checkbox preferences.
I know that preferences.xml supports generating lists of preferences (looking at wi-fi settings page) but ListPreference only allows you to select one from the list.
I've been searching for how to generate preferences programmatically but have only managed to find how to change attributes of preferences that are already in the XML.
Here is a short example (assuming you are extending PreferenceActivity):
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(this);
PreferenceCategory category = new PreferenceCategory(this);
category.setTitle("category name");
screen.addPreference(category);
CheckBoxPreference checkBoxPref = new CheckBoxPreference(this);
checkBoxPref.setTitle("title");
checkBoxPref.setSummary("summary");
checkBoxPref.setChecked(true);
category.addPreference(checkBoxPref);
setPreferenceScreen(screen);
}
Programatically add a preference, with other preferences in xml file:
Other solutions didn't work for me because I ALSO had an xml with preferences. I'm not sure all these calls are necessary/redundant, but this works.
onCreate() method, class extends PreferenceActivity:
setContentView(R.layout.preferences);
addPreferencesFromResource(R.xml.preferences);
PreferenceScreen pScreen = getPreferenceManager().createPreferenceScreen(this);
CheckBoxPreference cb = new CheckBoxPreference(this);
cb.setKey("cb");
cb.setTitle("BLAH");
cb.setOrder(99); //not working...
pScreen.addPreference(cb);
setPreferenceScreen(pScreen);
addPreferencesFromResource(R.xml.preferences);
Sidenote: Since I needed to generate a dynamic checkbox list, it was best suited inside an inner PreferenceScreen. So I created this PreferenceScreen inside the xml, then dynamically generated the checkboxes inside this. This way the ordering didn't matter since all the 'new' dynamica checkboxes were inside this screen.
Try the below code.
CheckBoxPreference checkBoxPref = findPreference("your_key");
if (checkBoxPref != null)
{
checkBoxPref.setChecked(false);
}
Android app has some very long preference screens, which always open at the top of the preference menu. I have some idea where the user wants to be in the preference menu. How can I force the preference screen to open scrolled to a specific preference item?
I know this is an old one, so this answer is just for reference.
To auto-select a given screen, all you have to do is setPreferenceScreen() (this is for a pre-Honeycomb non-Fragment PreferenceActivity).
Once you're on the correct PreferenceScreen, you can indeed use getListView().smoothScrollToPosition(position) (but this is a Froyo+ method), or you can use getListView.setSelection(position).
But how to get the position?
First, watch out for the trap: PreferenceActivity.getListAdapter() does not return the actual ListAdapter, but a local instance variable which is disconcertingly not in sync with PreferenceActivity.getListView().getAdapter() (and usually null).
Second, trying to use Preference.getOrder() returns the order of the Preference object within its parent, which is what you want to use for the position only if you're not using PreferenceCategories since what you need is its order within the PreferenceScreen.
If you are using PreferenceCategories, you need to iterate over the items in the adapter (for (int i = 0; i < adapter.getCount(); i++)until you find the right one, and use its position.
Another corner of the Android SDK that is in dire need of some attention…
You can just use scrollToPreference :
https://developer.android.com/reference/androidx/preference/PreferenceFragmentCompat#scrollToPreference(androidx.preference.Preference)
Example:
scrollToPreference(preferenceKey)
or:
scrollToPreference(preference)
Add this function to your PreferenceFragment
public void scrollToItem(String preferenceName) {
ListView listView = ButterKnife.findById(getView(),android.R.id.list);
Preference preference = findPreference(preferenceName);
if (preference != null && listView != null) {
for (int i = 0; i < listView.getAdapter().getCount(); i++) {
Preference iPref = (Preference) listView.getAdapter().getItem(i);
if (iPref == preference) {
listView.setSelection(i);
break;
}
}
}
}
Lets say you have settings.xml with this
<Preference
android:icon="#drawable/ic_action_email"
android:key="emailSupport"
android:title="#string/email_support" />
You can call
scrollToItem("emailSupport");
Note: You may need to replace listView.setSelection(i) with listView.smoothScrollToPosition(i)
Since PreferenceActivity extends ListActivity, you can call getListView() to get the ListView containing your preferences, and then use listView.smoothScrollToPosition() to scroll to a specific row in the list. I haven't actually tried this before, but it should work.