Scroll to top

Spanish (Español) translation by Steven (you can also view the original English article)

La noción de fragmentos se introdujo en Android 3.0, nivel de API 11. Desde entonces, la comunidad de Android ha visto seis versiones de plataformas principales. Aún así, más de la mitad de los dispositivos Android activos no tienen esta función disponible de forma nativa. En su lugar, los desarrolladores deben usar la biblioteca de soporte de Android si van a usar fragmentos con estos dispositivos. Aprende a crear una aplicación básica basada en fragmentos usando la biblioteca de soporte de Android en este tutorial.

Paso 0: Comenzando

Este tutorial está dirigido al desarrollador de Android que necesita orientarse a la gran mayoría de los dispositivos Android que actualmente están en manos de los usuarios y quiere aprovechar la API Fragment, que simplifica la compatibilidad con una variedad de tamaños de pantalla. Debes sentirte cómodo con Java, Eclipse y familiarizado con los conceptos básicos de Android.

Este tutorial también es para aquellos que necesitan instrucciones más detalladas que las que dio nuestro otro tutorial de fragmentos o para aquellos que necesitan una nueva versión de los fragmentos.

Para ver completamente los efectos y las diferencias de un diseño de pantalla de fragmentos bien diseñado y receptivo, necesitarás dos dispositivos (o emuladores configurados): uno con una pantalla del tamaño de un teléfono normal y otro con una pantalla del tamaño de una tableta.

Ten en cuenta que este código se basa en el código de mejores prácticas creado por el asistente de Nueva aplicación de Android dentro de Eclipse. El proyecto se puede descargar y navegar en el alojamiento de código de Google, al igual que el binario instalable.

Paso 1: Vista clásica de dos paneles

El ejemplo aquí será el ejemplo de fragmento clásico, también conocido como flujo "maestro-detalle". Comenzamos con una lista de "cosas" (elementos, podrían ser canciones, películas, mascotas, lo que sea) y, cuando se hace clic en una "cosa", mostramos los detalles de esa "cosa" específica. Si el tamaño de la pantalla del dispositivo permite mostrar tanto la lista como los detalles, se utilizarán dos fragmentos. De lo contrario, solo se utiliza uno y el usuario debe hacer clic para profundizar en los detalles.

Aquí hay una figura que muestra la organización típica de la pantalla antes de los fragmentos, o cuando la pantalla no es lo suficientemente grande para manejar tanta información una al lado de la otra:

Single Pane FragmentsSingle Pane FragmentsSingle Pane Fragments

Y aquí está el diseño de la pantalla cuando se hace con fragmentos como se mostraría en un dispositivo de pantalla grande o ancha como una tableta:

Dual Pane FragmentsDual Pane FragmentsDual Pane Fragments

Los fragmentos no eliminan la necesidad de actividades. Y, de hecho, todavía necesitarás dos actividades: una actividad manejará el caso donde se muestran ambos fragmentos (modo de dos paneles) y otra para manejar la vista de detalles cuando solo se mostró la lista en la primera pantalla porque la pantalla del dispositivo el tamaño era pequeño. Mediante el uso de recursos adecuadamente organizados, la primera actividad se ajustará dinámicamente en respuesta al ancho de la pantalla. Internamente, esta actividad debe saber si está en modo de dos paneles o no para que pueda colocar correctamente el fragmento de detalle o generar la actividad de detalle según sea necesario, que contendrá solo el fragmento de detalle.

Para simplificar: deberás implementar dos clases de actividad y dos clases de fragmentos para manejar estos casos. Las clases de actividad son bastante simples, ya que solo muestran el fragmento o fragmentos correctos y controlan el flujo de la aplicación. Para nuestro ejemplo aquí usamos las siguientes clases de actividad: la clase principal, CircleListActivity, la clase de detalle que se usa a veces, CircleDetailActivity. También tenemos las dos clases Fragment que realmente realizan el diseño y el dibujo: CircleListFragment y CircleDetailFragment. Sí, estamos hablando de círculos. Los círculos son solo cosas. No hay necesidad de preocuparse por la "cosa" que hemos elegido.

Paso 2: Creación de la actividad principal

La actividad principal, CircleListActivity, es el punto de partida para cargar uno o ambos fragmentos para la pantalla.

1
 
2
import android.content.Intent;
3
import android.os.Bundle;
4
import android.support.v4.app.FragmentActivity;
5
6
public class CircleListActivity extends FragmentActivity {
7
	private boolean mTwoPane;
8
9
	@Override
10
	protected void onCreate(Bundle savedInstanceState) {
11
		super.onCreate(savedInstanceState);
12
		setContentView(R.layout.activity_circle_list);
13
14
		if (findViewById(R.id.circle_detail_container) != null) {
15
16
			mTwoPane = true;
17
18
			((CircleListFragment) getSupportFragmentManager().findFragmentById(
19
					R.id.circle_list)).setActivateOnItemClick(true);
20
		}
21
22
	}
23
24
}

Ten en cuenta que usamos el FragmentManager de soporte de Android, no el introducido en Android 3.0.

Sin embargo, la clase de actividad hace muy poco. Toda la lógica principal ocurre automáticamente porque el sistema operativo Android cargará la versión de recurso de diseño correcta para el dispositivo cuando se realiza la llamada al método setContentView(). Esto significa que solo necesitas centrar tu atención en los recursos en cuestión. ¿Cómo eliges correctamente el recurso para utilizar uno o dos fragmentos?

Paso 3: Definiendo los diseños de las pantallas

Prueba emergente: ¿Cuántos diseños necesitamos para mostrar ambos fragmentos?

Respuesta: 3, pero eso no incluye el diseño de cada fragmento.

Necesitamos un diseño que muestre tanto el fragmento de lista como el fragmento de detalle. Necesitamos otro diseño que solo muestre el fragmento de la lista. Finalmente, necesitamos un tercer diseño que muestre solo el fragmento de detalle.

Los diseños pueden usar una etiqueta de fragmento para indicar un fragmento específico para cargar. Sin embargo, esto solo funciona para fragmentos fijos. Para los fragmentos dinámicos, como el fragmento de detalle que mostrará información diferente en función de lo que se eligió, usamos una vista de contenedor para indicar dónde debe ir el fragmento en el diseño. El contenedor más común para usar es un FrameLayout, ya que solo contiene un elemento secundario y luego se puede colocar como un bloque en cualquier lugar del diseño contenedor.

Para empezar, crearemos los dos diseños de fragmentos individuales.

Primero, el diseño que mostrará solo el fragmento de lista:

1
2
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:id="@+id/circle_list"
4
    android:name="com.mamlambo.circlesfragmentexample.CircleListFragment"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:layout_marginLeft="16dp"
8
    android:layout_marginRight="16dp"
9
/>

Ahora el diseño que muestra solo el fragmento de los detalles:

1
2
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    android:id="@+id/circle_detail_container"
4
    android:layout_width="match_parent"
5
    android:layout_height="match_parent"
6
 />

Si estos parecen bastante simples, es porque lo son. Para reiterar, estos son los diseños que dictan dónde estarán los fragmentos, no cómo se ven los fragmentos.

Finalmente, combinémoslos en un diseño que mostrará ambos fragmentos:

1
2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
4
    android:layout_width="match_parent"
5
    android:layout_height="match_parent"
6
    android:layout_marginLeft="16dp"
7
    android:layout_marginRight="16dp"
8
    android:orientation="horizontal"
9
    android:showDividers="middle"
10
    >
11
12
    <fragment
13
        android:id="@+id/circle_list"
14
        android:name="com.mamlambo.circlesfragmentexample.CircleListFragment"
15
        android:layout_width="0dp"
16
        android:layout_height="match_parent"
17
        android:layout_weight="1"/>
18
19
    <FrameLayout
20
        android:id="@+id/circle_detail_container"
21
        android:layout_width="0dp"
22
        android:layout_height="match_parent"
23
        android:layout_weight="3" />
24
25
</LinearLayout>

Ahora que sabes cómo se ven los diseños, es posible que todavía te preguntes cómo se elige el correcto mediante programación.

Paso 4: Organizando los diseños para diferentes escenarios

Sabes que el sistema operativo Android elegirá los recursos adecuados en función de las características actuales del dispositivo. Por tanto, a primera vista, puedes empezar a colocar diseños en carpetas como layout-land, layout-large, layout-small, etc. Deberías nombrar el diseño de fragmento de lista única de la misma manera que el diseño de fragmento dual y colocarlos en una variedad de carpetas diferentes. Esto incluso podría funcionar, pero este método será difícil de mantener, con varios archivos diferentes para varios diseños idénticos.

En su lugar, puedes usar referencias para hacer referencia a un elemento en particular en Android desde una carpeta de recursos en particular. Lo mejor es ver un ejemplo de esto. Nombraremos nuestros tres diseños basados en actividades (a diferencia de los fragmentos individuales contenidos dentro): activity_circle_detail, activity_circle_list y activity_circle_twopane. Luego, colocaremos los tres en la carpeta de diseño estándar. Ya has visto en el código, desde el Paso 2, que solo cargamos el diseño activity_circle_list. ¿O nosotros?

Ahora agreguemos algunas referencias. Una buena forma de determinar si la pantalla es adecuada para dos paneles uno al lado del otro es por el ancho, en unidades de dp. Digamos que nuestro diseño de doble panel requiere al menos 850dp de ancho de pantalla. Creemos una carpeta llamada values-w850dp. Eso debería cubrir las tabletas de alta densidad de 7" y las tabletas de densidad media de 10" en modo horizontal, pero no incluirá teléfonos xhdpi y generalmente excluirá el modo vertical en la mayoría de los dispositivos, excepto en algunos con pantallas de muy alta resolución. En esta carpeta, crea un archivo llamado refs.xml y coloca lo siguiente en su interior:

1
2
<resources>
3
    <item name="activity_circle_list" type="layout">@layout/activity_circle_twopane</item>
4
</resources>

¿Como funciona esto? Cuando el ancho sea de 850dp o mayor, esta referencia se utilizará para cargar el diseño. Eso significa que se utilizará el diseño de doble panel en lugar de que los paneles individuales se muestren por separado. Como este calificador de recursos (convención de nomenclatura de carpetas) no se introdujo hasta el nivel de API 13, también nos gustaría incluir esta misma referencia en otro calificador de carpeta adecuado que haya existido mucho más tiempo, como values-xlarge-land. Extra grande se define como al menos 960dp por 720dp, por lo que también debemos asegurarnos de que solo se muestre en modo horizontal al incluir el calificador de tierra.

Con los diseños organizados, es hora de volver nuestro enfoque al código Java. Si bien el diseño correcto se dibujará en la pantalla cuando se inicie por primera vez la actividad de la lista, ¿qué sucede cuando se toca uno de los elementos de la lista?

Paso 5: Definición del fragmento de lista

El fragmento de lista nos permite mostrar nuestra matriz de cosas (círculos, en este caso). No es diferente a ListActivity en que proporciona cierto manejo de tareas de lista de rutina para simplificar tu propia codificación. La lista debe contener todos los círculos de la fuente de datos (una fuente de datos simulada, en este caso) y también debe manejar toques en elementos específicos para mostrar los detalles. Sin embargo, dado que un fragmento no es una actividad, debería dejar pasar eventos que podrían cambiar la pantalla a la clase de actividad de control. Un toque que ocurre en el modo de panel doble cargará un fragmento en el otro panel en la misma pantalla, mientras que un toque en el modo de panel único debería cargar una nueva actividad con el fragmento de detalle. Sin embargo, el fragmento no conoce ni debería conocer estos detalles de configuración.

Sin embargo, debes crear una forma coherente de transmitir esta información a la actividad que la contiene o la controla, que conoce y debe conocer estos detalles. Por lo general, esta comunicación se administra a través de una clase de interfaz definida en el fragmento que debe ser implementada por cualquier actividad que la utilice, un método típico para realizar devoluciones de llamada.

Aquí está el código completo para la clase CircleListFragment, incluido un mecanismo de devolución de llamada seguro y el manejo de toque que llama al método de devolución de llamada para pasar el manejo del flujo de trabajo a la actividad de control.

1
2
import android.app.Activity;
3
import android.os.Bundle;
4
import android.support.v4.app.ListFragment;
5
import android.view.View;
6
import android.widget.ArrayAdapter;
7
import android.widget.ListView;
8
9
import com.mamlambo.circlesfragmentexample.dummy.DummyContent;
10
11
public class CircleListFragment extends ListFragment {
12
13
	private static final String STATE_ACTIVATED_POSITION = "activated_position";
14
	private Callbacks mCallbacks = sDummyCallbacks;
15
	private int mActivatedPosition = ListView.INVALID_POSITION;
16
	public interface Callbacks {
17
		public void onItemSelected(String id);
18
	}
19
20
	private static Callbacks sDummyCallbacks = new Callbacks() {
21
		@Override
22
		public void onItemSelected(String id) {
23
		}
24
	};
25
26
	public CircleListFragment() {
27
	}
28
29
	@Override
30
	public void onCreate(Bundle savedInstanceState) {
31
		super.onCreate(savedInstanceState);
32
33
		setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
34
				android.R.layout.simple_list_item_activated_1,
35
				android.R.id.text1, DummyContent.ITEMS));
36
	}
37
38
	@Override
39
	public void onViewCreated(View view, Bundle savedInstanceState) {
40
		super.onViewCreated(view, savedInstanceState);
41
42
		if (savedInstanceState != null
43
				&amp;&amp; savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
44
			setActivatedPosition(savedInstanceState
45
					.getInt(STATE_ACTIVATED_POSITION));
46
		}
47
	}
48
49
	@Override
50
	public void onAttach(Activity activity) {
51
		super.onAttach(activity);
52
53
		if (!(activity instanceof Callbacks)) {
54
			throw new IllegalStateException(
55
					"Activity must implement fragment's callbacks.");
56
		}
57
58
		mCallbacks = (Callbacks) activity;
59
	}
60
61
	@Override
62
	public void onDetach() {
63
		super.onDetach();
64
65
		mCallbacks = sDummyCallbacks;
66
	}
67
68
	@Override
69
	public void onListItemClick(ListView listView, View view, int position,
70
			long id) {
71
		super.onListItemClick(listView, view, position, id);
72
73
		mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
74
	}
75
76
	@Override
77
	public void onSaveInstanceState(Bundle outState) {
78
		super.onSaveInstanceState(outState);
79
		if (mActivatedPosition != ListView.INVALID_POSITION) {
80
			outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
81
		}
82
	}
83
84
	public void setActivateOnItemClick(boolean activateOnItemClick) {
85
		getListView().setChoiceMode(
86
				activateOnItemClick ? ListView.CHOICE_MODE_SINGLE
87
						: ListView.CHOICE_MODE_NONE);
88
	}
89
90
	private void setActivatedPosition(int position) {
91
		if (position == ListView.INVALID_POSITION) {
92
			getListView().setItemChecked(mActivatedPosition, false);
93
		} else {
94
			getListView().setItemChecked(position, true);
95
		}
96
97
		mActivatedPosition = position;
98
	}
99
}

Además de la funcionalidad descrita anteriormente, existe cierta administración de ListView de modo que el elemento de la lista que se toca se muestra como seleccionado cuando está en modo de panel dual y alguna administración básica del ciclo de vida de los fragmentos. Como antes, estamos usando la versión Support Fragment para que seamos compatibles con versiones anteriores de dispositivos más antiguos. Asegúrate de importar el paquete correcto en la biblioteca de soporte mediante (import android.support.v4.app.ListFragment).

Ahora tenemos que volver a la clase Activity controladora para que maneje la devolución de llamada.

Paso 6: Actualización de la actividad principal

Agrega el soporte de devolución de llamada a la clase de actividad principal, CircleListActivity, haciendo que implemente la interfaz CircleListFragment.Callbacks creada anteriormente. Luego, implementa el método onItemSelected() para bifurcar el comportamiento de la aplicación en función de si el dispositivo puede manejar el modo de dos paneles o no. Aquí está la clase completamente actualizada:

1
2
import android.content.Intent;
3
import android.os.Bundle;
4
import android.support.v4.app.FragmentActivity;
5
6
public class CircleListActivity extends FragmentActivity implements
7
		CircleListFragment.Callbacks {
8
9
	private boolean mTwoPane;
10
11
	@Override
12
	protected void onCreate(Bundle savedInstanceState) {
13
		super.onCreate(savedInstanceState);
14
		setContentView(R.layout.activity_circle_list);
15
16
		if (findViewById(R.id.circle_detail_container) != null) {
17
			mTwoPane = true;
18
19
			((CircleListFragment) getSupportFragmentManager().findFragmentById(
20
					R.id.circle_list)).setActivateOnItemClick(true);
21
		}
22
23
		// TODO: If exposing deep links into your app, handle intents here.

24
	}
25
26
	@Override
27
	public void onItemSelected(String id) {
28
		if (mTwoPane) {
29
			Bundle arguments = new Bundle();
30
			arguments.putString(CircleDetailFragment.ARG_ITEM_ID, id);
31
			CircleDetailFragment fragment = new CircleDetailFragment();
32
			fragment.setArguments(arguments);
33
			getSupportFragmentManager().beginTransaction()
34
					.replace(R.id.circle_detail_container, fragment).commit();
35
36
		} else {
37
			Intent detailIntent = new Intent(this, CircleDetailActivity.class);
38
			detailIntent.putExtra(CircleDetailFragment.ARG_ITEM_ID, id);
39
			startActivity(detailIntent);
40
		}
41
	}
42
}

Usando la bandera para determinar si se muestra la vista de doble panel, el método onItemSelected() inicia una nueva actividad o reemplaza cualquier fragmento actual encontrado en R.id.circle_detail_container con una nueva instancia de la clase CircleDetailFragment. Para este tipo de diseño, se necesita poco más. El identificador del círculo en el que ha tocado el usuario se pasa a la nueva instancia del fragmento a través de argumentos o a la nueva Actividad, donde también convertirá el identificador en argumentos.

En este punto, necesitamos implementar tanto la clase CircleDetailActivity para el caso de un solo panel como la clase CircleDetailFragment.

Paso 7: Definición de la actividad de detalles de un solo panel

Recuerda la simplicidad del diseño de esta clase de actividad. El diseño es simplemente un marcador de posición para la clase Fragmento del detalle. Todo lo que necesita hacer esta actividad es que se le pase el identificador, convertirlo en un argumento de tipo fragmento y luego agregar el fragmento al contenedor.

1
2
package com.mamlambo.circlesfragmentexample;
3
4
import android.os.Bundle;
5
import android.support.v4.app.FragmentActivity;
6
public class CircleDetailActivity extends FragmentActivity {
7
8
	@Override
9
	protected void onCreate(Bundle savedInstanceState) {
10
		super.onCreate(savedInstanceState);
11
		setContentView(R.layout.activity_circle_detail);
12
13
				if (savedInstanceState == null) {
14
			Bundle arguments = new Bundle();
15
			arguments.putString(CircleDetailFragment.ARG_ITEM_ID, getIntent()
16
					.getStringExtra(CircleDetailFragment.ARG_ITEM_ID));
17
			CircleDetailFragment fragment = new CircleDetailFragment();
18
			fragment.setArguments(arguments);
19
			getSupportFragmentManager().beginTransaction()
20
					.add(R.id.circle_detail_container, fragment).commit();
21
		}
22
	}
23
}

Si sonaba sencillo, ahora puedes ver que lo es. La última pieza a la que debemos llegar es el fragmento de detalle en sí.

Paso 8: Mostrar el fragmento de detalle

La clase de detalle del Fragmento necesita ver qué datos de círculo deben cargarse y mostrarse. Luego, necesita cargar y, bueno, mostrar esos datos. La clase cargará un diseño. El diseño de la maquetación puede ser genérico, pero debes considerar el hecho de que, como fragmento, puede o no ser de pantalla completa. En otras palabras, como de costumbre, no hagas suposiciones sobre el tamaño de la pantalla del dispositivo. Por supuesto, también como de costumbre, puedes crear varios diseños basados en calificadores de recursos. Ten en cuenta que estos se cargarán según las características generales de la pantalla del dispositivo y no según las características del área de visualización (modos de panel).

En este ejemplo, no hay más navegación, por lo que no se necesita devolución de llamada, como sucedió con el fragmento de lista.

Sin más preámbulos, aquí está el código completo para la clase CircleDetailFragment:

1
2
import android.os.Bundle;
3
import android.support.v4.app.Fragment;
4
import android.view.LayoutInflater;
5
import android.view.View;
6
import android.view.ViewGroup;
7
import android.widget.ImageView;
8
import android.widget.TextView;
9
10
import com.mamlambo.circlesfragmentexample.dummy.DummyContent;
11
12
public class CircleDetailFragment extends Fragment {
13
	public static final String ARG_ITEM_ID = "item_id";
14
15
	private DummyContent.DummyItem mItem;
16
	public CircleDetailFragment() {
17
	}
18
19
	@Override
20
	public void onCreate(Bundle savedInstanceState) {
21
		super.onCreate(savedInstanceState);
22
23
		if (getArguments().containsKey(ARG_ITEM_ID)) {
24
			mItem = DummyContent.ITEM_MAP.get(getArguments().getString(
25
					ARG_ITEM_ID));
26
		}
27
	}
28
29
	@Override
30
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
31
			Bundle savedInstanceState) {
32
		View rootView = inflater.inflate(R.layout.fragment_circle_detail,
33
				container, false);
34
35
		if (mItem != null) {
36
			((TextView) rootView.findViewById(R.id.circle_detail))
37
					.setText(mItem.content);
38
			((ImageView) rootView.findViewById(R.id.circle_view))
39
					.setImageResource(mItem.resourceId);
40
		}
41
42
		return rootView;
43
	}
44
}

Aunque todo el código es básicamente el mismo que un fragmento que no es de soporte, ten en cuenta la importación adecuada para android.support.v4.app.Fragment para asegurarte de utilizar la clase de soporte de Android correcta.

Paso 9: Actualizando el archivo manifiesto de Android para fragmentos

Ahora necesitamos agregar los fragmentos al archivo manifiesto, ¿verdad? En realidad no. A diferencia de las clases de actividad, los fragmentos no se registran en el archivo manifiesto. Entonces, simplemente agrega las clases de actividad al archivo manifiesto y listo.

Aquí está el archivo manifiesto de muestra para tu placer visual:

1
2
<?xml version="1.0" encoding="utf-8"?>
3
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
4
    package="com.mamlambo.circlesfragmentexample"
5
    android:versionCode="1"
6
    android:versionName="1.0" >
7
8
    <uses-sdk
9
        android:minSdkVersion="8"
10
        android:targetSdkVersion="16" />
11
12
    <application
13
        android:allowBackup="true"
14
        android:icon="@drawable/ic_launcher"
15
        android:label="@string/app_name"
16
        android:theme="@style/AppTheme" >
17
        <activity
18
            android:name="com.mamlambo.circlesfragmentexample.CircleListActivity"
19
            android:label="@string/app_name" >
20
            <intent-filter>
21
                <action android:name="android.intent.action.MAIN" />
22
23
                <category android:name="android.intent.category.LAUNCHER" />
24
            </intent-filter>
25
        </activity>
26
        <activity
27
            android:name="com.mamlambo.circlesfragmentexample.CircleDetailActivity"
28
            android:label="@string/title_circle_detail"
29
            android:parentActivityName=".CircleListActivity" >
30
            <meta-data
31
                android:name="android.support.PARENT_ACTIVITY"
32
                android:value=".CircleListActivity" />
33
        </activity>
34
    </application>
35
36
</manifest>

Ten en cuenta la amplia gama de versiones del SDK de Android que se pueden admitir con este enfoque mediante la funcionalidad Fragmento de la biblioteca de compatibilidad.

Paso 10: Ejecutar la aplicación

Si bien no hemos presentado el código fuente completo pegado en este tutorial y los recursos de la aplicación, puedes completar esos detalles tú mismo. O puedes descargar el código (ver Paso 0), compilarlo y ejecutarlo. O puedes descargar el binario precompilado e instalarlo.

Independientemente de cómo lo hagas, cuando se ejecute en una configuración de dispositivo con 850dp de ancho o la pantalla sea extra grande (al menos 960x640dp), verás este diseño de pantalla (una pantalla de 1920x1200 píxeles a 10"):

Y cuando el ancho de la pantalla sea inferior a 850dp, el diseño vuelve al modo de panel único, como esta pantalla de teléfono de 1280px de ancho en modo horizontal:

O este teléfono de 768 píxeles de ancho en modo vertical:

O esta pantalla de 1200px de ancho en una tableta en modo vertical:

Debido al uso de medidas abstractas, como el uso de unidades dp, puedes ver los dos diseños diferentes en una pantalla con resoluciones de píxeles idénticas, pero densidades de píxeles diferentes. Esto ayuda a evitar que la densidad de la información (más píxeles no siempre significa que los usuarios quieran más datos) sea demasiado alta en pantallas físicamente pequeñas y es una de las mejores cosas del sistema de recursos de Android.

Conclusión

Has aprendido los conceptos básicos del uso de la API de fragmentos de Android disponible en la biblioteca de soporte de Android. Si bien hay mucho, mucho más en los fragmentos, este tutorial te brinda un punto de partida para un caso de uso muy común que puede mejorar drásticamente la apariencia de muchas aplicaciones o partes de aplicaciones, independientemente de la versión de Android con la que se estén ejecutando o las pantallas en las que se muestran.

Acerca de los autores

Los desarrolladores de dispositivos móviles Lauren Darcey y Shane Conder son coautores de varios libros sobre el desarrollo de Android: un libro de programación en profundidad titulado Desarrollo de aplicaciones inalámbricas de Android (ahora en su tercera edición como un conjunto de dos volúmenes), Sams Aprende tú mismo el desarrollo de aplicaciones Android en 24 horas, y Aprendiendo la programación de aplicaciones de Android para Kindle Fire: una guía práctica para crear tu primera aplicación Android. Cuando no están escribiendo, dedican su tiempo a desarrollar software móvil en su empresa y a brindar servicios de consultoría. Puedes comunicarse con ellos por correo electrónico a través de androidwirelessdev+mt@gmail.com, o mediante su blog en androidbook.blogspot.com y en Twitter @androidwireless.

¿Necesitas más ayuda para escribir aplicaciones de Android? ¡Mira nuestros últimos libros y recursos!

Buy Android Wireless Application Development, 3rd Edition, Volume 1 Buy Sam's Teach Yourself Android Application Development in 24 Hours, 2nd Edition Mamlambo code at Code Canyon