Reputation: 1701
I want to display different preference options in my app depending on the device SDK and screen size, but certain preferences will be displayed on all devices. I could accomplish this by creating a full preferences.xml file for each possible device, like this:
xml/preferences.xml
:
<PreferenceScreen>
<!-- Preference 1 (all devices) -->
<!-- Preference 2 (all devices) -->
</PreferenceScreen>
xml-v21/preferences.xml
:
<PreferenceScreen>
<!-- Preference 1 (all devices) -->
<!-- Preference 2 (all devices) -->
<!-- Preference 3 (SDK 21 only) -->
</PreferenceScreen>
But this will get unwieldy very quickly given the number of possible combinations of screen sizes and SDKs. What I'd really like to do would be to use the same basic list of preferences on all devices and dynamically mix in additional preferences that are specific to certain screen sizes and SDKs. I've gone through the Android Providing Resources guide, but it seems that using alternative resources in the manner described there would still require me to create a separate resource directory for every screen-size-and-SDK combination and would require a lot of code duplication. Is there a nice, elegant solution to this problem that I'm missing?
Upvotes: 1
Views: 1009
Reputation: 2377
Have you read the Settings guide? My app also has a lot of changes dynamically, both in 1) which headers / fragments to show, and 2) which prefs each fragment contains. For both issues you can use different resource versions, as you describe, or you can implement the differences in code.
For issue #1, you can either call loadHeadersFromResource directly, and have different headers resource files, or you can have code that does something similar. For example, my PreferencesActivity uses a separate PreferenceFragment subclass for each prefs section, and makes a decision at run time about which fragments (headers) to show:
@Override
public void onBuildHeaders(List<Header> targets) {
// Build a list of PreferenceFragment class objects to show now
List<Class<? extends PreferenceFragment>> fragmentClasses = ...;
// Create a Header for each fragment to return to Android
for (Class<? extends PreferenceFragment> fragmentClass: fragmentClasses) {
try {
PreferenceFragment fragment = fragmentClass.newInstance();
Header header = new Header();
header.fragment = fragmentClass.getName();
header.titleRes = fragment.getTitleId();
targets.add(header);
this.headers = targets;
} catch (Exception e) {
}
}
}
For issue #2, you can start with preferences from a common resource file, and then add the conditional ones in code:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Load common prefs from an XML resource
addPreferencesFromResource(R.xml.preferences);
// Add conditional prefs in code
PreferenceScreen prefScreen = getPreferenceScreen();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Preference pref = ...; // create condition pref
prefScreen.addPreference(pref);
}
}
I actually add all prefs in code, common and conditional. However, I didn't see a way to create a PreferenceScreen from scratch, so I actually have an empty XML file that I load from resources, and then add all preferences in code. It works really well.
Upvotes: 2