Control de giro
En este tema se describe cómo controlar los cambios de orientación del dispositivo en Xamarin.Android. Se explica cómo trabajar con el sistema de recursos android para cargar automáticamente recursos para una orientación de dispositivo determinada, así como cómo controlar mediante programación los cambios de orientación.
Información general
Dado que los dispositivos móviles se rotan fácilmente, la rotación integrada es una característica estándar en sistemas operativo móviles. Android proporciona un marco sofisticado para trabajar con la rotación dentro de las aplicaciones, tanto si la interfaz de usuario se crea mediante declaración en XML como mediante programación en el código. Al controlar automáticamente los cambios de diseño declarativo en un dispositivo girado, una aplicación puede beneficiarse de la estrecha integración con el sistema de recursos android. Para el diseño mediante programación, los cambios se deben controlar manualmente. Esto permite un control más preciso en tiempo de ejecución, pero a costa de más trabajo para el desarrollador. Una aplicación también puede optar por no participar en el reinicio de actividad y tomar el control manual de los cambios de orientación.
En esta guía se examinan los siguientes temas de orientación:
Rotación declarativa de diseño: cómo usar el sistema de recursos de Android para crear aplicaciones con orientación, incluido cómo cargar diseños y drawables para determinadas orientaciones.
Rotación de diseño mediante programación: cómo agregar controles mediante programación, así como cómo controlar manualmente los cambios de orientación.
Control de la rotación mediante declaración con diseños
Al incluir archivos en carpetas que siguen las convenciones de nomenclatura, Android carga automáticamente los archivos adecuados cuando cambia la orientación. Esto incluye la compatibilidad para:
Recursos de diseño: especifica qué archivos de diseño se inflan para cada orientación.
Recursos drawable: especifica qué drawables se cargan para cada orientación.
Recursos de diseño
De forma predeterminada, los archivos XML de Android (AXML) incluidos en la carpeta Resources/layout se usan para representar vistas para una actividad. Los recursos de esta carpeta se usan para la orientación vertical y horizontal si no se proporcionan recursos de diseño adicionales específicamente para horizontal. Considere la estructura del proyecto creada por la plantilla de proyecto predeterminada:
Este proyecto crea un único archivo Main.axml en la carpeta Resources/layout. Cuando se llama al método de la actividad, se infla la vista definida en OnCreateOnCreate que declara un botón como se muestra en el código XML siguiente:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
</LinearLayout>
Si el dispositivo gira a orientación horizontal, se vuelve a llamar al método de la actividad y se infla el mismo archivo OnCreateOnCreate como se muestra en la captura de pantalla siguiente:
Orientation-Specific diseños
Además de la carpeta de diseño (cuyo valor predeterminado es vertical y también se puede denominar explícitamente layout-port mediante la inclusión de una carpeta denominada ), una aplicación puede definir las vistas que necesita cuando está en horizontal sin ningún cambio de código.
Supongamos que el archivo Main.axml contenía el siguiente XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is portrait"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
Si se agrega al proyecto una carpeta denominada layout-land que contiene un archivo Main.axml adicional, al inflar el diseño en horizontal, Android cargará el archivo Main.axml recién agregado. Tenga en cuenta la versión horizontal del archivo Main.axml que contiene el código siguiente (para simplificar, este XML es similar a la versión vertical predeterminada del código, pero usa una cadena diferente en ):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:text="This is landscape"
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
</RelativeLayout>
La ejecución de este código y la rotación del dispositivo de vertical a horizontal muestra la nueva carga XML, como se muestra a continuación:
Recursos drawables
Durante la rotación, Android trata los recursos drawable de forma similar a los recursos de diseño. En este caso, el sistema obtiene los drawables de las carpetas Resources/drawable y Resources/drawable-land, respectivamente.
Por ejemplo, digamos que el proyecto incluye una imagen denominada Monkey.png en la carpeta Resources/drawable, donde se hace referencia al drawable desde un en XML como este:
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/monkey"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
Supongamos además que se incluye una versión diferente de Monkey.png en Resources/drawable-land. Al igual que con los archivos de diseño, cuando se gira el dispositivo, el que se puede dibujar cambia para la orientación determinada, como se muestra a continuación:
Control de la rotación mediante programación
A veces se definen diseños en el código. Esto puede ocurrir por diversos motivos, como limitaciones técnicas, preferencias del desarrollador, etc. Cuando se agregan controles mediante programación, una aplicación debe tener en cuenta manualmente la orientación del dispositivo, que se controla automáticamente cuando se usan recursos XML.
Agregar controles en el código
Para agregar controles mediante programación, una aplicación debe realizar los pasos siguientes:
- Cree un diseño.
- Establecer parámetros de diseño.
- Crear controles.
- Establecer parámetros de diseño de control.
- Agregue controles al diseño.
- Establezca el diseño como vista de contenido.
Por ejemplo, considere una interfaz de usuario que consta de un único control agregado TextView a , como se muestra en el código RelativeLayout siguiente.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// create TextView control
var tv = new TextView (this);
// set TextView's LayoutParameters
tv.LayoutParameters = layoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Este código crea una instancia de una RelativeLayout clase y establece su propiedad LayoutParameters . La clase es la forma de Android de encapsular cómo se posicionan los LayoutParams controles de una manera reutilizable. Una vez creada una instancia de un diseño, se pueden crear controles y agregarse a ella. Los controles también LayoutParameters tienen , como en este TextView ejemplo. Después de crear el , agregarlo a y establecer como la vista de contenido da como resultado que la aplicación muestre el como TextViewRelativeLayout se RelativeLayoutTextView muestra:
Detectar orientación en el código
Si una aplicación intenta cargar una interfaz de usuario diferente para cada orientación cuando se llama (esto sucede cada vez que se gira un dispositivo), debe detectar la orientación y, a continuación, cargar el código de interfaz de usuario OnCreate deseado. Android tiene una clase denominada , que se puede usar para determinar la rotación actual del dispositivo a través de WindowManager la propiedad , como se muestra a WindowManager.DefaultDisplay.Rotation continuación:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// create a layout
var rl = new RelativeLayout (this);
// set layout parameters
var layoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
rl.LayoutParameters = layoutParams;
// get the initial orientation
var surfaceOrientation = WindowManager.DefaultDisplay.Rotation;
// create layout based upon orientation
RelativeLayout.LayoutParams tvLayoutParams;
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
} else {
tvLayoutParams = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
tvLayoutParams.LeftMargin = 100;
tvLayoutParams.TopMargin = 100;
}
// create TextView control
var tv = new TextView (this);
tv.LayoutParameters = tvLayoutParams;
tv.Text = "Programmatic layout";
// add TextView to the layout
rl.AddView (tv);
// set the layout as the content view
SetContentView (rl);
}
Este código establece que se coloque a 100 píxeles desde la parte superior izquierda de la pantalla, animando automáticamente al nuevo diseño, cuando se gira a horizontal, como se muestra TextView aquí:
Impedir el reinicio de la actividad
Además de controlar todo en , una aplicación también puede evitar que se reinicie una actividad cuando cambia la orientación estableciendo en el OnCreateConfigurationChangesActivityAttribute siguiente:
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
Ahora, cuando se gira el dispositivo, la actividad no se reinicia. Para controlar manualmente el cambio de orientación en este caso, una actividad puede invalidar el método y determinar la orientación del objeto que se pasa, como en la nueva implementación de la OnConfigurationChangedConfiguration actividad siguiente:
[Activity (Label = "CodeLayoutActivity", ConfigurationChanges=Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
public class CodeLayoutActivity : Activity
{
TextView _tv;
RelativeLayout.LayoutParams _layoutParamsPortrait;
RelativeLayout.LayoutParams _layoutParamsLandscape;
protected override void OnCreate (Bundle bundle)
{
// create a layout
// set layout parameters
// get the initial orientation
// create portrait and landscape layout for the TextView
_layoutParamsPortrait = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape = new RelativeLayout.LayoutParams (ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
_layoutParamsLandscape.LeftMargin = 100;
_layoutParamsLandscape.TopMargin = 100;
_tv = new TextView (this);
if (surfaceOrientation == SurfaceOrientation.Rotation0 || surfaceOrientation == SurfaceOrientation.Rotation180) {
_tv.LayoutParameters = _layoutParamsPortrait;
} else {
_tv.LayoutParameters = _layoutParamsLandscape;
}
_tv.Text = "Programmatic layout";
rl.AddView (_tv);
SetContentView (rl);
}
public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged (newConfig);
if (newConfig.Orientation == Android.Content.Res.Orientation.Portrait) {
_tv.LayoutParameters = _layoutParamsPortrait;
_tv.Text = "Changed to portrait";
} else if (newConfig.Orientation == Android.Content.Res.Orientation.Landscape) {
_tv.LayoutParameters = _layoutParamsLandscape;
_tv.Text = "Changed to landscape";
}
}
}
Aquí los TextView's parámetros de diseño se inicializan para horizontal y vertical. Las variables de clase mantienen los parámetros, junto con el propio , ya que la actividad no se volverá a crear TextView cuando cambie la orientación. El código sigue empleando surfaceOrientartion en para establecer el diseño inicial de OnCreateTextView . Después, controla OnConfigurationChanged todos los cambios de diseño posteriores.
Al ejecutar la aplicación, Android carga los cambios de la interfaz de usuario a medida que se produce la rotación de dispositivos y no reinicia la actividad.
Impedir el reinicio de la actividad para diseños declarativos
Los reinicios de actividad causados por la rotación de dispositivos también se pueden evitar si se define el diseño en XML. Por ejemplo, podemos usar este enfoque si queremos evitar un reinicio de la actividad (por motivos de rendimiento, quizás) y no es necesario cargar nuevos recursos para distintas orientaciones.
Para ello, se sigue el mismo procedimiento que se usa con un diseño mediante programación. Simplemente establezca ConfigurationChanges en , como hicimos en el ActivityAttributeCodeLayoutActivity anterior. Cualquier código que tenga que ejecutarse para el cambio de orientación se puede implementar de nuevo en el OnConfigurationChanged método .
Mantener el estado durante los cambios de orientación
Tanto si se administra la rotación mediante declaración como mediante programación, todas las aplicaciones Android deben implementar las mismas técnicas para administrar el estado cuando cambia la orientación del dispositivo. La administración del estado es importante porque el sistema reinicia una actividad en ejecución cuando se gira un dispositivo Android. Android hace esto para facilitar la carga de recursos alternativos, como diseños y drawables diseñados específicamente para una orientación determinada. Cuando se reinicia, la actividad pierde cualquier estado transitorio que pueda haber almacenado en variables de clase local. Por lo tanto, si una actividad depende del estado, debe conservar su estado en el nivel de aplicación. Una aplicación debe controlar el guardado y la restauración de cualquier estado de la aplicación que quiera conservar en los cambios de orientación.
Para obtener más información sobre el estado persistente en Android, consulte la guía ciclo de vida de la actividad.
Resumen
En este artículo se ha abordado cómo usar las funcionalidades integradas de Android para trabajar con la rotación. En primer lugar, se explica cómo usar el sistema de recursos android para crear aplicaciones con orientación. A continuación, se muestra cómo agregar controles en el código, así como cómo controlar los cambios de orientación manualmente.





