Icono del sitio Develou

Tipos De Preferencias En Android

Construir una pantalla de ajustes/configuración es soportado por una variedad de tipos de preferencias en Android. Verás que tienes a disposición varios patrones que usarán los controles de UI de Android para permitirte especificar el valor de la preferencia.

Con el fin de cubrir esta gama de herramientas, en este tutorial aprenderás sobre:

Nota: Este es el segundo tutorial de la guía de ajustes de usuario en Android, por lo que asumiré que ya leíste Crear Fragmento De Preferencias.


Ejemplo De Tipos De Preferencias En Android

Para materializar el uso de los tipos de preferencias que existen, extenderemos la jerarquía de preferencias del proyecto actual de esta forma:

Como ves, tendremos. Puedes descargar el proyecto en Android Studio desde el siguiente enlace. El módulo correspondiente a este tutorial será P2_Tipos_De_Preferencias:


Tipos De Preferencias

Iniciemos por conocer las diferentes subclases de la clase Preference que aportan nuevas funcionalidades desde la interfaz y selección del valor de configuración:

Cada uno de estos bloques está asociado a un patrón que brinda una forma diferente para configurar los comportamientos del aplicativo. Los siguientes son los propósitos de cada componente.


EditTextPreference

En nuestro ejemplo tenemos una situación hipotética donde necesitamos recibir el nombre del negocio del usuario. Para ello usaremos EdiTextPreference:

EditTextPreference muestra un EditText en un diálogo y guarda como String el valor ingresado por el usuario.

Para implementarla, solo abre el archivo res/xml/preferences.xml y añade una etiqueta <EditTextPreference>:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <EditTextPreference
        app:defaultValue="No establecido"
        app:key="businessName"
        app:title="Nombre del negocio"
        app:useSimpleSummaryProvider="true" />
</PreferenceScreen>

Los atributos usados cumplen con las siguientes configuraciones:


ListPreference

Este tipo de preferencia te provee un patrón de selección única entre varias entradas. Nuestra App aprovechará esta clase para permitir al usuario elegir su moneda:

ListPreference muestra una lista de RadioButtons en un diálogo, del cual el usuario puede elegir solo uno.

Para disponer la selección de la moneda del usuario añade una etiqueta <ListPreference> en la jerarquía de preferencias de esta forma:

<ListPreference
    app:defaultValue="1"
    app:entries="@array/currency_entries"
    app:entryValues="@array/currency_values"
    app:key="currency"
    app:title="Moneda"
    app:useSimpleSummaryProvider="true" />

Lo especial de este tipo de preferencia son los atributos entries y entryValues. El primero es un array con los valores que se mostrarán al usuario y el segundo un array de los índices que les corresponden:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="currency_entries">
        <item>COP</item>
        <item>USD</item>
        <item>EUR</item>
    </string-array>

    <string-array name="currency_values">
        <item>1</item>
        <item>2</item>
        <item>3</item>
</resources>

Dicha correspondencia se ve en la selección, si selecciona la etiqueta "COP" se tomará el índice "1" como valor actual de la preferencia. Obviamente, ambos arreglos deben ser del mismo tamaño para sostener esta estructura 1:1.


MultiSelectListPreference

Ahora bien, supongamos que deseamos establecer una frecuencia de envío de un resumen de cuenta al correo del usuario. Aquí entraría MultiSelectListPreference:

Esta despliega una lista de CheckBoxes en un diálogo y el usuario puede elegir múltiples entradas.

Al igual que ListPreference, añade una etiqueta <MultiSelectListPreference>:

<MultiSelectListPreference
    android:defaultValue="@array/account_summary_default"
    android:entries="@array/account_summary_entries"
    android:entryValues="@array/account_summary_values"
    android:key="accountSummary"
    android:title="Frecuencia resumen de cuenta" />

Uusaremos entries y entryValues para presentar a los días de la semana:

<string-array name="account_summary_entries">
    <item>Lunes</item>
    <item>Martes</item>
    <item>Miércoles</item>
    <item>Jueves</item>
    <item>Viernes</item>
    <item>Sábado</item>
    <item>Domingo</item>
</string-array>

<string-array name="account_summary_values">
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
</string-array>

Como ves, el texto secundario no es actualizado al confirmar las entradas seleccionadas. Por lo que debemos hacerlo desde Kotlin:

private fun setUpAccountSummary() {
    val accountSummary: MultiSelectListPreference? = findPreference("accountSummary")
    accountSummary?.run {
        setSummary(values) // Texto secundario inicial
        setOnPreferenceChangeListener { _, newValue ->
            val newValues = newValue as Set<String>
            accountSummary.setSummary(newValues) // Texto secundario al cambiar
            true
        }
    }
}

fun MultiSelectListPreference.setSummary(newValues: Set<String>) {
    summary = if (newValues.isEmpty())
        "Sin envío"
    else
        newValues.joinToString(", ") { value ->
            entries[findIndexOfValue(value)]
        }
}

Desde SettingsFragment configuramos la preferencia accountSummary a partir de una función de extensión llamada setSummary().

Esta consiste en la evaluación de los valores seleccionados. Si no hay ninguno, entonces disponemos del texto "Sin envío". De lo contrario usamos la función joinToString() para mapear los valores en un String que contenga la lista de entradas separadas por coma.

Encontrar el índice de una entrada a partir del valor lo logras con findIndexOfValue().

Finalmente desde setUpAccountSummary() usamos la función de alcance run() para crear un contexto de configuración de la preferencia. Claramente buscamos actualizar el valor de Preference.summary, por lo que realizamos la asignación inicial y luego cuando el observador OnPreferenceChangeListener detecte un nuevo cambio.


SeekBarPreference

Cuando se da la situación en la que debes proveer al usuario la selección entre un conjunto de valores continuos usa a SeekBarPreference. Por ejemplo, proveer un rango de distancia para filtrar ofertas:

Como ves, SeekBarPreference usa en su layout una SeekBar junto a un TextView que muestra el valor actual del deslizador.

Concretamente en nuestro ejemplo, añadimos la etiqueta <SeekBarPreference> para la distancia así:

<SeekBarPreference
    app:defaultValue="50"
    app:showSeekBarValue="true"
    app:title="Distancia (KM)" />

Los atributos específicos de este componente son:


SwitchPreferenceCompat

La SwitchPreferenceCompat provee dos estados con el widget Switch. Este formato te permite otorgarle al usuario la activación/desactivación de un comportamiento o presentación en la App. Por ejemplo, habilitar la visualización de una sección de últimos cambios:

Probemos su estética y comportamiento añadiendo una nueva etiqueta <SwitchPreferenceCompat> en nuestra jerarquía:

<SwitchPreferenceCompat
    android:defaultValue="true"
    android:key="latestEvents"
    android:title="Mostrar últimos cambios"
    app:icon="@drawable/ic_timeline"
    app:summaryOff="No aparecerán los últimos cambios ocurridos en la pantalla principal"
    app:summaryOn="Aparecerán los últimos cambios ocurridos en la pantalla principal" />

Ya que SwitchPreferenceCompat es heredera de TwoStatePreference, tendrás los siguientes atributos a disposición:

Dependencia De Ajustes

Si deseas que el valor de un ajuste dependa del de otro que usa SwitchPreferenceCompat, entonces usa el atributo dependency. Por ejemplo, si la aparición de los últimos cambios está activa, podemos habilitar una preferencia que defina el atributo de ordenamiento de dicha sección:

Para establecer la dependencia asigna el valor de app:key de la preferencia SwitchPreferenceCompat en el atributo app:dependency de la preferencia dependiente:

<ListPreference
    android:defaultValue="date"
    android:entries="@array/latest_events_order_entries"
    android:entryValues="@array/latest_events_order_values"
    android:key="latestEventsOrder"
    android:title="Ordenar por"
    app:dependency="latestEvents"
    app:useSimpleSummaryProvider="true" />

Como ves, asignamos latestEvents en una nueva preferencia que define el atributo de ordenamiento para los cambios registrados como eventos

Esto hará que al desactivar el valor del switch, se desactive el ajuste asociado de ordenamiento.


Organizar Preferencias

En este tutorial aprendiste sobre las clases disponibles para componer una pantalla de ajustes con múltiples patrones de selección y colección de datos del usuario.

No obstante, el estado actual muestra múltiples aspectos revueltos que podrían ser separados por categorías. Y es precisamente esta organización la que aplicaremos en el siguiente tutorial Categorías Y Subpantallas De Preferencias (todo).

Veremos cómo usar la clase PreferenceCategory para separar por grupos a nuestras preferencias. O como agregar subpantallas de preferencias para marcar aún más la separación.


Más Contenidos Android

Salir de la versión móvil