studio programacion herramientas fundamentos con avanzado aplicaciones android preferenceactivity

programacion - PreferenceActivity Android 4.0 y versiones anteriores



manual de android en pdf (6)

@Mef Tu respuesta se puede simplificar aún más para que no necesites ambas PreferencesActivity y OtherPreferencesActivity (tener 2 PrefsActivities es un PITA).

Descubrí que puede poner el método onBuildHeaders () en su PreferencesActivity y que las versiones de Android no arrojarán errores antes de la v11. Tener loadHeadersFromResource () dentro de onBuildHeaders no arrojó y excepción en 2.3.6, pero lo hizo en Android 1.6. Sin embargo, después de algunos retoques, encontré que el siguiente código funcionará en todas las versiones, por lo que solo se requiere una actividad (lo que simplifica enormemente las cosas).

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 esta forma, solo necesita una actividad, una entrada en su AndroidManifest.xml y una línea cuando invoca sus preferencias:

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

ACTUALIZACIÓN Oct 2013: Eclipse / Lint le advertirá sobre el uso del método obsoleto, pero simplemente ignore la advertencia. Estamos usando el método solo cuando tenemos que hacerlo, que es siempre que no tengamos preferencias de estilo v11 + y debemos usarlo, lo cual está bien. No se preocupe por el código obsoleto cuando lo haya contabilizado, Android no eliminará los métodos en desuso en el corto plazo. Si alguna vez ocurrió, ya no necesitarás esta clase, ya que te obligarían a apuntar solo a dispositivos más nuevos. El mecanismo Desaprobado está ahí para advertirle que hay una forma mejor de manejar algo en la versión más reciente de la API, pero una vez que la haya contabilizado, puede ignorar la advertencia a partir de ese momento. La eliminación de todas las llamadas a métodos en desuso solo obligaría a su código a ejecutarse solo en dispositivos más nuevos, lo que anularía la necesidad de ser compatible con versiones anteriores.

Probando las diferentes actividades de preferencia en el ApiDemos para Android 4.0, veo en el código que algunos métodos están en desuso en PreferencesFromCode.java, por ejemplo.

Entonces mi pregunta es: si uso PreferenceFragment, ¿funcionará para todas las versiones o solo 3.0 o 4.0 y superiores?

Si es así, ¿qué debería usar que funcione también para 2.2 y 2.3?


El problema con las respuestas anteriores es que apilará todas las preferencias en una sola pantalla en dispositivos pre-Honecomb (debido a múltiples llamadas de addPreferenceFromResource() ).

Si necesita la primera pantalla como lista y luego la pantalla con preferencias (como el uso de encabezados de preferencia), debe usar la developer.android.com/guide/topics/ui/…


Estoy usando esta biblioteca , que tiene un AAR en mavenCentral para que pueda incluirlo fácilmente si está usando Gradle .

compile ''com.github.machinarius:preferencefragment:0.1.1''


Hay una nueva versión que podría ayudar.

UnifiedPreference es una biblioteca para trabajar con todas las versiones del paquete Android Preference de API v4 en adelante.


Quería señalar que si comienzas en http://developer.android.com/guide/topics/ui/settings.html#PreferenceHeaders y vas hacia la sección de "Compatibilidad con versiones anteriores con encabezados de preferencia", tiene más sentido La guía es muy útil y funciona bien. Aquí hay un ejemplo explícito siguiendo su guía:

Comience con el archivo preference_header_legacy.xml para sistemas Android antes de HoneyComb

<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>

A continuación, cree el archivo preference_header.xml para sistemas Android con HoneyComb +

<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>

Luego crea un archivo preferences.xml para mantener tus preferencias ...

<?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>

Luego crea el archivo 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); } }

Luego crea la clase 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 , agregó este bloque entre mis etiquetas <application>

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

y finalmente, para la etiqueta <wallpaper> ...

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


PreferenceFragment no funcionará en 2.2 y 2.3 (solo API de nivel 11 y superior). Si desea ofrecer la mejor experiencia de usuario y aún admite versiones anteriores de Android, la mejor práctica aquí parece ser implementar dos clases de actividad de PreferenceActivity y decidir en el tiempo de ejecución cuál invocar. Sin embargo, este método aún incluye la invocación de API en desuso, pero no se puede evitar eso.

Entonces, por ejemplo, tienes 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>

y un preferences.xml estándar (que no ha cambiado mucho desde niveles inferiores de API):

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

Entonces necesitas una implementación de PreferenceFragment :

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

Y, por último, necesita dos implementaciones de PreferenceActivity , para niveles de API que admiten o no admiten PreferenceFragments :

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

y:

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

En el punto donde desea mostrar la pantalla de preferencias al usuario, usted decide cuál iniciar:

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

Entonces, básicamente, usted tiene un archivo xml por fragmento, carga cada uno de estos archivos xml manualmente para niveles de API <11, y ambas actividades usan las mismas preferencias.