Skip to content

Most visited

Recently visited

navigation

Implementación de flujos de IU adaptables

El flujo de IU puede variar según el diseño que tu aplicación muestre actualmente. Por ejemplo, si tu aplicación se encuentra en modo de panel dual , al hacer clic sobre un elemento en el panel izquierdo se mostrará simplemente el contenido en el panel derecho. En modo de panel único, el contenido debería mostrarse por sí solo (en una actividad diferente).

Determinar el diseño actual

Ya que cada diseño que implementes será algo diferente, probablemente una de las primeras cosas por hacer será determinar qué diseño está viendo actualmente el usuario. Por ejemplo, tal vez quieras saber si el usuario se encuentra en modo de "panel único" o "panel dual". Puedes hacer eso consultando si una determinada vista existe y es visible:

public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &&
                        articleView.getVisibility() == View.VISIBLE;
    }
}

Ten en cuenta que este código consulta si el panel "artículo" se encuentra disponible o no, lo cual es mucho más flexible que programar de forma rígida una consulta para cada diseño específico.

Otra forma de adaptar la existencia de distintos componentes es verificar si se encuentran disponibles antes de ejecutar una operación sobre ellos. Por ejemplo, en el ejemplo de app “News Reader”, hay un botón que abre un menú, pero ese botón solo existe cuando se ejecuta en una versión anterior a Android 3.0 (ya que su función queda a cargo de ActionBar en el nivel de API 11 y en niveles superiores). Entonces para agregar el receptor de eventos para este botón, puedes hacer lo siguiente:

Button catButton = (Button) findViewById(R.id.categorybutton);
OnClickListener listener = /* create your listener here */;
if (catButton != null) {
    catButton.setOnClickListener(listener);
}

Reaccionar conforme al diseño actual

Algunas acciones pueden tener un resultado diferente en función del diseño actual. Por ejemplo, en la muestra de News Reader, hacer clic en un encabezado de la lista abrirá el artículo en el panel del lado derecho si la IU está en modo de panel dual, pero se iniciará una actividad independiente si la IU está en modo de panel único:

@Override
public void onHeadlineSelected(int index) {
    mArtIndex = index;
    if (mIsDualPane) {
        /* display article on the right pane */
        mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    } else {
        /* start a separate activity */
        Intent intent = new Intent(this, ArticleActivity.class);
        intent.putExtra("catIndex", mCatIndex);
        intent.putExtra("artIndex", index);
        startActivity(intent);
    }
}

De la misma manera, si la app está en modo de panel dual, debería configurar la barra de acciones con pestañas para la navegación; mientras que si la app está en modo de panel único, debería configurar la navegación con un widget desplegable. Por lo tanto, tu código debería comprobar también qué caso es el adecuado:

final String CATEGORIES[] = { "Top Stories", "Politics", "Economy", "Technology" };

public void onCreate(Bundle savedInstanceState) {
    ....
    if (mIsDualPane) {
        /* use tabs for navigation */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_TABS);
        int i;
        for (i = 0; i < CATEGORIES.length; i++) {
            actionBar.addTab(actionBar.newTab().setText(
                CATEGORIES[i]).setTabListener(handler));
        }
        actionBar.setSelectedNavigationItem(selTab);
    }
    else {
        /* use list navigation (spinner) */
        actionBar.setNavigationMode(android.app.ActionBar.NAVIGATION_MODE_LIST);
        SpinnerAdapter adap = new ArrayAdapter(this,
                R.layout.headline_item, CATEGORIES);
        actionBar.setListNavigationCallbacks(adap, handler);
    }
}

Reutilizar fragmentos en otras actividades

Un patrón recurrente al diseñar para diferentes pantallas es tener una parte de tu interfaz implementada como un panel en algunas configuraciones de pantalla y como actividad independiente en otras configuraciones. Por ejemplo, en el ejemplo de News Reader , el texto del artículo de noticias se presenta en el panel de la derecha en pantallas grandes, pero es una actividad independiente en pantallas más pequeñas.

En casos como este, normalmente puedes evitar duplicar el código si reutilizas la misma subclase Fragment en distintas actividades. Por ejemplo, ArticleFragment se usa en el diseño de panel dual:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>

Y se reutiliza (sin un diseño) en el diseño de actividad para pantallas más pequeñas (ArticleActivity):

ArticleFragment frag = new ArticleFragment();
getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();

Naturalmente, esto produce el mismo efecto que declarar el fragmento en un diseño XML . Aunque, en este caso, un diseño XML sería un trabajo innecesario, ya que el fragmento del artículo es el único componente de esta actividad.

Un punto muy importante a tener en cuenta cuando diseñes tus fragmentos es no crear una vinculación fuerte para una actividad específica. Para hacer esto, normalmente puedes definir una interfaz que resuma todas las formas en las que tiene que interactuar el fragmento con su actividad host. Luego, la actividad host implementa esa interfaz:

Por ejemplo, el HeadlinesFragment de la app News Reader hace exactamente eso:

public class HeadlinesFragment extends ListFragment {
    ...
    OnHeadlineSelectedListener mHeadlineSelectedListener = null;

    /* Must be implemented by host activity */
    public interface OnHeadlineSelectedListener {
        public void onHeadlineSelected(int index);
    }
    ...

    public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener listener) {
        mHeadlineSelectedListener = listener;
    }
}

Luego, cuando el usuario selecciona un encabezado, el fragmento notifica al receptor especificado por la actividad host (en lugar de notificar una actividad específica codificada de forma rígida):

public class HeadlinesFragment extends ListFragment {
    ...
    @Override
    public void onItemClick(AdapterView<?> parent,
                            View view, int position, long id) {
        if (null != mHeadlineSelectedListener) {
            mHeadlineSelectedListener.onHeadlineSelected(position);
        }
    }
    ...
}

Esta técnica se detalla más adelante en la guía Compatibilidad con tablets y teléfonos.

Manejar cambios en la configuración de pantalla

Si utilizas actividades independientes para implementar partes separadas de tu interfaz, debes tener en cuenta que es posible que tengas que reaccionar ante determinados cambios en la configuración (como un cambio de rotación) para que tu interfaz siga siendo coherente.

Por ejemplo, en una típica tablet de 7" con Android 3.0 o posterior, la muestra de News Reader utiliza una actividad independiente para mostrar el artículo de noticias en el modo de retrato, pero utiliza un diseño de panel dual en el modo de paisaje.

Esto significa que cuando el usuario está en modo de retrato y la actividad para ver un artículo está en pantalla, necesitas detectar que la orientación haya cambiado a modo horizontal y que reaccione correctamente finalizando la actividad y regresando a la actividad principal para que el contenido pueda mostrarse en el diseño de panel dual:

public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);

        // If should be in two-pane mode, finish to return to main activity
        if (getResources().getBoolean(R.bool.has_two_panes)) {
            finish();
            return;
        }
        ...
}
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Follow Google Developers on WeChat

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)