Cómo crear una implementación con API antiguas

En esta lección, se explica cómo crear una implementación que duplique las API más nuevas y sea compatible con los dispositivos más antiguos.

Cómo decidir una solución alternativa

La tarea más desafiante en relación con el uso de nuevas funciones de IU de una manera retrocompatible es decidir e implementar una solución más antigua (resguardo) para versiones más antiguas de la plataforma. En muchos casos, es posible cumplir el propósito de estos componentes de IU más recientes con funciones de marcos de trabajo de IU antiguas. Por ejemplo:

  • Se pueden implementar las barras de acciones con un LinearLayout horizontal que contenga botones de imagen, ya sea como barras de título personalizadas o como vistas en el diseño de la actividad. Se pueden presentar acciones de ampliación debajo del botón Menú del dispositivo.

  • Se pueden implementar pestañas de barra de acciones con un LinearLayout horizontal que contenga botones o con el elemento de IU TabWidget.

  • Se pueden implementar los widgets NumberPicker y Switch con los widgets Spinner y ToggleButton, respectivamente.

  • Se pueden implementar los widgets ListPopupWindow y PopupMenu con los widgets PopupWindow.

Por lo general, no existe una sola solución para todos los componentes de IU más recientes en dispositivos más antiguos. Ten en cuenta la experiencia del usuario: en dispositivos más antiguos, es posible que los usuarios no estén familiarizados con los patrones de diseño y los componentes de IU más recientes. Piensa en cómo se puede ofrecer la misma funcionalidad con elementos conocidos. En muchos casos, esto no es una preocupación, si se destacan los componentes de la IU más recientes en el ecosistema de la aplicación (como la barra de acciones) o si el modelo de interacción es tan extremadamente simple como intuitivo (como deslizar vistas con un ViewPager).

Cómo implementar pestañas con API antiguas

Para crear una implementación más antigua de las pestañas de la barra de acciones, puedes usar un TabWidget y TabHost (aunque alternativamente puedes usar widgets Button con diseño horizontal). Implementa esto en las clases TabHelperEclair y CompatTabEclair, ya que esa implementación usa API ingresadas antes de Android 2.0 (Eclair).

Diagrama de clases para la implementación de pestañas en Eclair

Figura 1: Diagrama de clases para la implementación de pestañas en Eclair

La implementación de CompatTabEclair almacena las propiedades de la pestaña, como el texto y el ícono de la pestaña, en las variables de instancia, ya que no hay un objeto ActionBar.Tab disponible para manejar este almacenamiento:

Kotlin

class CompatTabEclair internal constructor(val activity: FragmentActivity, tag: String) :
        CompatTab(tag) {

    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private var text: CharSequence? = null
    ...

    override fun setText(resId: Int): CompatTab {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.resources.getText(resId)
        return this
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

Java

public class CompatTabEclair extends CompatTab {
    // Store these properties in the instance,
    // as there is no ActionBar.Tab object.
    private CharSequence text;
    ...

    public CompatTab setText(int resId) {
        // Our older implementation simply stores this
        // information in the object instance.
        text = activity.getResources().getText(resId);
        return this;
    }

    ...
    // Do the same for other properties (icon, callback, etc.)
}

La implementación de TabHelperEclair usa métodos en el widget TabHost para crear objetos TabHost.TabSpec e indicadores de pestañas:

Kotlin

class TabHelperEclair internal constructor(activity: FragmentActivity) : TabHelper(activity) {

    private var tabHost: TabHost? = null
    ...

    override fun setUp() {
        // Our activity layout for pre-Honeycomb devices
        // must contain a TabHost.
        tabHost = tabHost ?: mActivity.findViewById<TabHost>(android.R.id.tabhost).apply {
            setup()
        }
    }

    override fun addTab(tab: CompatTab) {
        ...
        tabHost?.newTabSpec(tab.tag)?.run {
            setIndicator(tab.getText()) // And optional icon
            ...
            tabHost?.addTab(this)
        }
    }
    // The other important method, newTab() is part of
    // the base implementation.
}

Java

public class TabHelperEclair extends TabHelper {
    private TabHost tabHost;
    ...

    protected void setUp() {
        if (tabHost == null) {
            // Our activity layout for pre-Honeycomb devices
            // must contain a TabHost.
            tabHost = (TabHost) mActivity.findViewById(
                    android.R.id.tabhost);
            tabHost.setup();
        }
    }

    public void addTab(CompatTab tab) {
        ...
        TabSpec spec = tabHost
                .newTabSpec(tag)
                .setIndicator(tab.getText()); // And optional icon
        ...
        tabHost.addTab(spec);
    }

    // The other important method, newTab() is part of
    // the base implementation.
}

Ahora tienes dos implementaciones de CompatTab y TabHelper: una que funciona en dispositivos con Android 3.0 o versiones posteriores y usa APIs nuevas, y otra que funciona en dispositivos con Android 2.0 o versiones posteriores y usa APIs anteriores. En la siguiente lección, se analiza el uso de estas implementaciones en tu aplicación.