PreferenceActivity , PreferenceFragment and headers (Part 3)

In previous posts we described how to use Preference Activity,Preference Fragment and Preference Header.
As we have seen, the example described in Scenario 3 doesn't work on older device (API Level<11).
The Preference Fragment and associated Preference Headers are not supported on Android platforms prior to Android 3.0 (API level 11). As a result, if you want to create applications with headers that support devices running on both pre- and post-Honeycomb devices you have same alternatives:
  • you need to create an additional preferences XML file that uses basic elements that behave like the header items
  • you need to implement separate Preference Activities to support both, and launch the appropriate Activity at run time

PreferenceFragment and Headers with older versions 
As the first alternative:
  1. Step 1: Define the preferences_headers_scenario3.xml
    We can use the same file used in scenario3. This file lists each settings group and declares which fragment contains the corresponding list of settings.The file is placed in the res\xml folder.
    <preference-headers
        xmlns:android="http://schemas.android.com/apk/res/android">
    
      <header
     android:fragment="it.gmariotti.android.examples.preference.UpdatePreferenceFragment"
           android:title="@string/settings_update"
           android:summary="@string/settings_updateSummary" >
      </header>
      <header
     android:fragment="it.gmariotti.android.examples.preference.DisplayPreferenceFragment"
           android:title="@string/settings_display"
           android:summary="@string/settings_displaySummary">
      </header>
     <header
     android:fragment="it.gmariotti.android.examples.preference.NotifyPreferenceFragment"
           android:title="@string/settings_notify">
      </header>
     
    </preference-headers>
    
  2. Step 2: Define additional preferences_headers_legacy_scenario4.xml
    
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    
        <Preference 
            android:title="@string/settings_update"
            android:summary="@string/settings_updateSummary"  >
            <intent 
                android:targetPackage="it.gmariotti.android.examples.preference"
                android:targetClass="it.gmariotti.android.examples
                                         .preference.PreferencesActivityABSScenario4"
                android:action="prefs_update" >
             </intent>
        </Preference>
        
        <Preference 
            android:title="@string/settings_display"
            android:summary="@string/settings_displaySummary"  >
            <intent 
                android:targetPackage="it.gmariotti.android.examples.preference"
                android:targetClass="it.gmariotti.android.examples
                                        .preference.PreferencesActivityABSScenario4"
                android:action="prefs_display">
            </intent>
        </Preference>
        
        <Preference 
            android:title="@string/settings_notify">
            <intent 
                android:targetPackage="it.gmariotti.android.examples.preference"
                android:targetClass="it.gmariotti.android.examples
                                       .preference.PreferencesActivityABSScenario4"
                android:action="prefs_display">
            </intent>
        </Preference>
     
    </PreferenceScreen>
    
    Instead of opening a new PreferenceScreen, each of the elements sends an Intent to the PreferencesActivityABSScenario4.
    We have to identify which preference file to load, and we can do it with intent's action.

  3. Step 3: Modify PreferenceActivity
    The only thing left to do is call onBuildHeaders() only when running on Androd 3.0 or higher in our PreferenceActivityABSScenario4 and call addPreferencesFromResource() in older version.
    
    public class PreferencesActivityABSScenario4 extends SherlockPreferenceActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            
            //LEGACY METHOD FOR OLDER DEVICES --------------------------------------
            
            String action = getIntent().getAction();
            int preferenceFile_toLoad=-1;
            //Manage single fragment with action parameter
            if (action != null && action.equals(Constants.SETTING_UPDATE)) {
             preferenceFile_toLoad=R.xml.preference_update;
            }else if (action != null && action.equals(Constants.SETTING_DISPLAY)) {  
             preferenceFile_toLoad=R.xml.preference_display;
            }else if (action != null && action.equals(Constants.SETTING_NOTIFY)) {  
             preferenceFile_toLoad=R.xml.preference_notify;
            } else{
             //Inflate main preference file for Android<3.0
             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
                 // Load the legacy preferences headers
              preferenceFile_toLoad=R.xml.preference_headers_legacy_scenario4;
             }
            }
             
            if (preferenceFile_toLoad>-1){
             addPreferencesFromResource(preferenceFile_toLoad);
            }
        
            //--------------------------------------------------------------------
        }
     
        /**
         * Populate the activity with the top-level headers.
         */
        @Override
        public void onBuildHeaders(List<Header> target) {
         loadHeadersFromResource(R.xml.preference_headers_scenario3, target);
        }
    }

And that’s all! Just execute the app in Android emulator or real device and see following output.
Single-pane layout in older device with "headers" :


As alternative , you need to implement separate Preference Activities to support both, and launch the appropriate Activity at run time, as shown
  1. Step 1: Use preferences_headers_scenario3.xml and PreferenceActivityABSScenario3
  2. Step 2:Define alternative preference xml file and PreferenceActivity
    
    public class OtherPreferencesActivity extends PreferenceActivity {
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ddPreferencesFromResource(R.xml.otherPreferences);
        }
    }
    
  3. Step 3: Launch the appropriate Activity
    Class c = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ?
                OtherPreferenceActivity.class : PreferenceActivityABSScenario3.class;
    
       Intent i = new Intent(this, c);
       startActivityForResult(i, SHOW_PREFERENCES);
    

You can get code from GitHub:

Comments

Popular posts from this blog

AntiPattern: freezing a UI with Broadcast Receiver

NotificationListenerService and kitkat

How to centralize the support libraries dependencies in gradle