36 votes

PreferenceActivity Android 4.0 et versions antérieures

En essayant les différents préférence activités dans le ApiDemos pour Android 4.0, je vois dans le code que certaines méthodes sont déconseillés dans PreferencesFromCode.java, par exemple.

Donc ma question est: si j'utilise PreferenceFragment, ça va marcher pour toutes les version ou seulement 3.0 ou 4.0 et jusqu'?

Si oui, que dois-je utiliser qui fonctionne pour 2.2 et 2.3 ainsi?

59voto

Mef Points 15230

PreferenceFragment ne fonctionnera pas sur 2.2 et 2.3 (uniquement l'API de niveau 11 et ci-dessus). Si vous voulez offrir la meilleure expérience d'utilisateur et de toujours prendre en charge les anciennes versions d'Android, la meilleure pratique semble être ici de mettre en œuvre deux PreferenceActivity des classes et de décider au moment de l'exécution qui l'invoque. Cependant, cette méthode inclut toujours l'appel Api obsolète, mais vous ne pouvez pas l'éviter.

Ainsi, par exemple, vous avez un preference_headers.xml:

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" > 
    <header android:fragment="your.package.PrefsFragment" 
        android:title="...">
        <extra android:name="resource" android:value="preferences" />
    </header>
</preference-headers>

et un écart - preferences.xml (ce qui n'a pas beaucoup changé depuis le bas de l'API de niveau):

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="...">
    ...
</PreferenceScreen>

Ensuite, vous avez besoin d'une mise en œuvre de l' PreferenceFragment:

public static class PrefsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }
}

Et enfin, vous avez besoin de deux implémentations de l' PreferenceActivity, pour les API niveaux supportant ou non PreferenceFragments:

public class PreferencesActivity extends PreferenceActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        addPreferencesFromResource(R.xml.other);
    }
}

et:

public class OtherPreferencesActivity extends PreferenceActivity {
    @Override
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.preference_headers, target);
    }
}

Au point où vous souhaitez afficher l'écran de préférences de l'utilisateur, à vous de décider lequel commencer:

if (Build.VERSION.SDK_INT < 11) {
    startActivity(new Intent(this, PreferencesActivity.class));
} else {
    startActivity(new Intent(this, OtherPreferencesActivity.class));
}

Donc, fondamentalement, vous avez un fichier xml par fragment, vous charge de chacun de ces fichiers xml manuellement pour API niveaux < 11, et les deux utilisent les mêmes préférences.

18voto

Uncle Code Monkey Points 1276

@Mef réponse à Votre question peut être simplifié encore plus de sorte que vous n'avez pas besoin à la fois de la PreferencesActivity et OtherPreferencesActivity (2 PrefsActivities est un pain PITA).

J'ai trouvé que vous pouvez mettre le onBuildHeaders() la méthode dans votre PreferencesActivity et aucune erreur ne sera générée par les versions d'Android antérieures à v11. Avoir la loadHeadersFromResource() à l'intérieur de la onBuildHeaders ne pas les jeter et d'exception sur 2.3.6, mais n'sur Android 1.6. Après quelques retouches si, j'ai trouvé le code suivant fonctionne dans toutes les versions de sorte qu'une seule activité est nécessaire (en simplifiant les questions).

public class PreferencesActivity extends PreferenceActivity {
    protected Method mLoadHeaders = null;
    protected Method mHasHeaders = null;

    /**
     * Checks to see if using new v11+ way of handling PrefFragments.
     * @return Returns false pre-v11, else checks to see if using headers.
     */
    public boolean isNewV11Prefs() {
        if (mHasHeaders!=null && mLoadHeaders!=null) {
            try {
                return (Boolean)mHasHeaders.invoke(this);
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            }
        }
        return false;
    }

    @Override
    public void onCreate(Bundle aSavedState) {
        //onBuildHeaders() will be called during super.onCreate()
        try {
            mLoadHeaders = getClass().getMethod("loadHeadersFromResource", int.class, List.class );
            mHasHeaders = getClass().getMethod("hasHeaders");
        } catch (NoSuchMethodException e) {
        }
        super.onCreate(aSavedState);
        if (!isNewV11Prefs()) {
            addPreferencesFromResource(R.xml.preferences);
            addPreferencesFromResource(R.xml.other);
        }
    }

    @Override
    public void onBuildHeaders(List<Header> aTarget) {
        try {
            mLoadHeaders.invoke(this,new Object[]{R.xml.pref_headers,aTarget});
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {
        }   
    }
}

De cette façon, vous avez seulement besoin d'une activité, d'une entrée dans votre AndroidManifest.xml et une ligne lorsque vous appelez de vos préférences:

startActivity(new Intent(this, PreferencesActivity.class);

Mise à JOUR octobre 2013: Eclipse/Peluches vais vous mettre en garde sur l'utilisation de la méthode dépréciée, mais il suffit de les ignorer l'avertissement. Nous sommes à l'aide de la méthode que lorsque nous avons, qui est à chaque fois que nous n'avons pas v11+ préférences de style et doit l'utiliser, ce qui est OK. Ne soyez pas effrayés par Obsolète code quand vous avez compté pour elle, Android ne supprimera pas des méthodes obsolètes de sitôt. Si jamais, il ne se produire, vous n'aurez même pas besoin de cette classe plus que vous serions obligés de ne cibler que les appareils récents. Le Obsolète mécanisme est là pour vous avertir qu'il y a une meilleure façon de gérer quelque chose sur la dernière version de l'API, mais une fois que vous avez compté pour elle, vous pouvez ignorer l'avertissement à partir de là. Suppression de tous les appels à des méthodes obsolètes aurait seulement pour effet de forcer votre code à exécuter uniquement sur les appareils récents - ainsi en niant la nécessité d'être compatible à tous.

6voto

scottyab Points 6760

Il y a un newish lib qui pourrait vous aider.

UnifiedPreference est une bibliothèque pour travailler avec toutes les versions de la Android Préférence d'un package à partir de l'API v4 et.

5voto

Destil Points 3673

Problème avec les réponses précédentes, c'est qu'il va pile de toutes les préférences d'un seul écran, sur la pré-Honecomb dispositifs (en raison de la multiplication des appels d' addPreferenceFromResource()).

Si vous avez besoin d'abord de l'écran sous forme de liste et puis l'écran avec les préférences (par exemple en utilisant de préférence les en-têtes de), vous devez utiliser le guide Officiel pour compatible préférences

2voto

EnzoAtari Points 11

Je tenais à préciser que si vous commencez à http://developer.android.com/guide/topics/ui/settings.html#PreferenceHeaders et de travailler votre chemin vers le bas à la section "support des anciennes versions de préférence pour les en-têtes" il aura plus de sens. Le guide est très utile et fonctionne bien. Voici un exemple explicite à la suite de leur guide:

Donc, commencer avec un fichier preference_header_legacy.xml pour android systèmes d'avant en Nid d'abeille

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference 
    android:title="OLD Test Title"
    android:summary="OLD Test Summary"  >
    <intent 
        android:targetPackage="example.package"
        android:targetClass="example.package.SettingsActivity"
        android:action="example.package.PREFS_ONE" />
</Preference>

Créez ensuite le fichier preference_header.xml pour android systèmes avec Nid d'abeille+

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header 
    android:fragment="example.package.SettingsFragmentOne"
    android:title="NEW Test Title"
    android:summary="NEW Test Summary" />
</preference-headers>

Créez ensuite un preferences.xml fichier pour stocker vos préférences...

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
        <CheckBoxPreference
        android:key="pref_key_auto_delete"
        android:summary="@string/pref_summary_auto_delete"
        android:title="@string/pref_title_auto_delete"
        android:defaultValue="false" />
</PreferenceScreen>

Créez ensuite le fichier SettingsActivity.java

package example.project;
import java.util.List;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceActivity;

public class SettingsActivity extends PreferenceActivity{
final static String ACTION_PREFS_ONE = "example.package.PREFS_ONE";

@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String action = getIntent().getAction();
    if (action != null && action.equals(ACTION_PREFS_ONE)) {
        addPreferencesFromResource(R.xml.preferences);
    }
    else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        // Load the legacy preferences headers
        addPreferencesFromResource(R.xml.preference_header_legacy);
    }
}

@SuppressLint("NewApi")
@Override
public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.xml.preference_header, target);
}
}

Créez ensuite la classe SettingsFragmentOne.java

package example.project;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.preference.PreferenceFragment;

@SuppressLint("NewApi")
public class SettingsFragmentOne extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);
}
}

AndroidManifest.xml, a ajouté ce bloc entre mes <application> tags

<activity 
   android:label="@string/app_name"
   android:name="example.package.SettingsActivity"
   android:exported="true">
</activity>

et enfin, pour l' <wallpaper> balise...

<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/description"
android:thumbnail="@drawable/ic_thumbnail"
android:settingsActivity="example.package.SettingsActivity"
/>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X