Clase Device de Xamarin.Forms

Download SampleDescargar el ejemplo

La clase Device contiene una serie de propiedades y métodos para ayudar a los desarrolladores a personalizar el diseño y la funcionalidad por plataforma.

Además de métodos y propiedades para dirigirse al código en tamaños y tipos de hardware específicos, la clase Device incluye métodos que se pueden usar para interactuar con controles de interfaz de usuario de subprocesos en segundo plano. Para obtener más información, consulte Interacción con la interfaz de usuario desde subprocesos en segundo plano.

Proporcionar valores específicos de la plataforma

Antes de Xamarin.Forms 2.3.4, la plataforma en la que se ejecutaba la aplicación podía obtenerse examinando la propiedad Device.OS y comparándola con los valores de enumeración TargetPlatform.iOS, TargetPlatform.Android, TargetPlatform.WinPhone y TargetPlatform.Windows. Del mismo modo, se podría usar una de las sobrecargas Device.OnPlatform para proporcionar valores específicos de la plataforma a un control.

Sin embargo, desde Xamarin.Forms 2.3.4, estas API han quedado en desuso y se han reemplazado. La clase Device ahora contiene constantes de cadena públicas que identifican las plataformas: Device.iOS, Device.Android, Device.WinPhone (en desuso), Device.WinRT (en desuso), Device.UWP y Device.macOS. Del mismo modo, las sobrecargas Device.OnPlatform se han reemplazado por las API OnPlatform y On.

En C#, se pueden proporcionar valores específicos de la plataforma mediante la creación de una instrucción switch en la propiedad Device.RuntimePlatform y, a continuación, proporcionar instrucciones case para las plataformas necesarias:

double top;
switch (Device.RuntimePlatform)
{
  case Device.iOS:
    top = 20;
    break;
  case Device.Android:
  case Device.UWP:
  default:
    top = 0;
    break;
}
layout.Margin = new Thickness(5, top, 5, 0);

Las clases OnPlatform y On proporcionan la misma funcionalidad en XAML:

<StackLayout>
  <StackLayout.Margin>
    <OnPlatform x:TypeArguments="Thickness">
      <On Platform="iOS" Value="0,20,0,0" />
      <On Platform="Android, UWP" Value="0,0,0,0" />
    </OnPlatform>
  </StackLayout.Margin>
  ...
</StackLayout>

La clase OnPlatform es una clase genérica para la que se debe crear una instancia con un atributo x:TypeArguments que coincida con el tipo de destino. En la clase On, el atributo Platform puede aceptar un valor string único o varios valores string delimitados por comas.

Importante

Si se proporciona un valor de atributo Platform incorrecto en la clase On, no se producirá un error. En su lugar, el código se ejecutará sin que se aplique el valor específico de la plataforma.

Como alternativa, la extensión de marcado OnPlatform se puede usar en XAML para personalizar la apariencia de la interfaz de usuario por plataforma. Para obtener más información, consulta Extensión de marcado OnPlatform.

Device.Idiom

La propiedad Device.Idiom se puede usar para modificar diseños o funcionalidades en función del dispositivo en el que se ejecuta la aplicación. La enumeración TargetIdiom contiene los valores siguientes:

  • Teléfono: dispositivos iPhone, iPod touch y Android más estrechos que 600 puntos por pulgada^
  • Tableta: iPad, dispositivos Windows y dispositivos Android más anchos que 600 puntos por pulgada^
  • Desktop: solo se devuelve en aplicaciones para UWP en equipos de escritorio con Windows 10 (devuelve Phone en dispositivos Windows móviles, incluido en escenarios de Continuum)
  • TV: dispositivos Tizen TV
  • Reloj: dispositivos de reloj Tizen
  • No admitido: sin usar

^ puntos por pulgada no es necesariamente el recuento de píxeles físicos

La propiedad Idiom es especialmente útil para crear diseños que aprovechan las pantallas más grandes, como esta:

if (Device.Idiom == TargetIdiom.Phone) {
    // layout views vertically
} else {
    // layout views horizontally for a larger display (tablet or desktop)
}

La clase OnIdiom proporciona la misma funcionalidad en XAML:

<StackLayout>
    <StackLayout.Margin>
        <OnIdiom x:TypeArguments="Thickness">
            <OnIdiom.Phone>0,20,0,0</OnIdiom.Phone>
            <OnIdiom.Tablet>0,40,0,0</OnIdiom.Tablet>
            <OnIdiom.Desktop>0,60,0,0</OnIdiom.Desktop>
        </OnIdiom>
    </StackLayout.Margin>
    ...
</StackLayout>

La clase OnIdiom es una clase genérica que se debe crear una instancia con un atributo x:TypeArguments que coincida con el tipo de destino.

Como alternativa, la extensión de marcado OnIdiom se puede usar en XAML para personalizar la apariencia de la interfaz de usuario en función de la expresión del dispositivo en el que se ejecuta la aplicación. Para obtener más información, vea Extensión de marcado OnIdiom.

Device.FlowDirection

El valor Device.FlowDirection recupera un valor de enumeración FlowDirection que representa la dirección del flujo actual que usa el dispositivo. La dirección de flujo es la dirección en la que el ojo humano lee los elementos de la interfaz de usuario en la página. Los valores de la enumeración son:

En XAML, el valor Device.FlowDirection se puede recuperar mediante la extensión de marcado x:Static:

<ContentPage ... FlowDirection="{x:Static Device.FlowDirection}"> />

El código equivalente en C# es:

this.FlowDirection = Device.FlowDirection;

Para obtener más información sobre la dirección del flujo, consulte Localización de derecha a izquierda.

Device.Styles

La propiedad Styles contiene definiciones de estilo integradas que se pueden aplicar a algunas propiedades Style de controles (como Label). Los estilos disponibles son:

  • BodyStyle
  • CaptionStyle
  • ListItemDetailTextStyle
  • ListItemTextStyle
  • SubtitleStyle
  • TitleStyle

Device.GetNamedSize

GetNamedSize se puede usar al establecer FontSize en código de C#:

myLabel.FontSize = Device.GetNamedSize (NamedSize.Small, myLabel);
someLabel.FontSize = Device.OnPlatform (
      24,         // hardcoded size
      Device.GetNamedSize (NamedSize.Medium, someLabel),
      Device.GetNamedSize (NamedSize.Large, someLabel)
);

Device.GetNamedColor

Xamarin.Forms 4.6 presenta compatibilidad con colores con nombre. Un color con nombre es un color que tiene un valor diferente en función del modo del sistema (por ejemplo, claro u oscuro) activo en el dispositivo. En Android, se accede a los colores con nombre a través de la clase R.Color. En iOS, los colores con nombre se denominan colores del sistema. En el Plataforma universal de Windows, los colores con nombre se denominan recursos de temas XAML.

El método GetNamedColor se puede usar para recuperar colores con nombre en Android, iOS y UWP. El método toma un argumento string y devuelve Color:

// Retrieve an Android named color
Color color = Device.GetNamedColor(NamedPlatformColor.HoloBlueBright);

Color.Default se devolverá cuando no se encuentre un nombre de color o cuando se invoque GetNamedColor en una plataforma no admitida.

Nota:

Dado que el método GetNamedColor devuelve un Color específico de una plataforma, normalmente se debe usar junto con la propiedad Device.RuntimePlatform.

La clase NamedPlatformColor contiene las constantes que definen los colores con nombre para Android, iOS y UWP:

Android iOS macOS UWP
BackgroundDark Label AlternateSelectedControlTextColor SystemAltHighColor
BackgroundLight Link ControlAccent SystemAltLowColor
Black OpaqueSeparator ControlBackgroundColor SystemAltMediumColor
DarkerGray PlaceholderText ControlColor SystemAltMediumHighColor
HoloBlueBright QuaternaryLabel DisabledControlTextColor SystemAltMediumLowColor
HoloBlueDark SecondaryLabel FindHighlightColor SystemBaseHighColor
HoloBlueLight Separator GridColor SystemBaseLowColor
HoloGreenDark SystemBlue HeaderTextColor SystemBaseMediumColor
HoloGreenLight SystemGray HighlightColor SystemBaseMediumHighColor
HoloOrangeDark SystemGray2 KeyboardFocusIndicatorColor SystemBaseMediumLowColor
HoloOrangeLight SystemGray3 Label SystemChromeAltLowColor
HoloPurple SystemGray4 LabelColor SystemChromeBlackHighColor
HoloRedDark SystemGray5 Link SystemChromeBlackLowColor
HoloRedLight SystemGray6 LinkColor SystemChromeBlackMediumColor
TabIndicatorText SystemGreen PlaceholderText SystemChromeBlackMediumLowColor
Transparent SystemIndigo PlaceholderTextColor SystemChromeDisabledHighColor
White SystemOrange QuaternaryLabel SystemChromeDisabledLowColor
WidgetEditTextDark SystemPink QuaternaryLabelColor SystemChromeHighColor
SystemPurple SecondaryLabel SystemChromeLowColor
SystemRed SecondaryLabelColor SystemChromeMediumColor
SystemTeal SelectedContentBackgroundColor SystemChromeMediumLowColor
SystemYellow SelectedControlColor SystemChromeWhiteColor
TertiaryLabel SelectedControlTextColor SystemListLowColor
SelectedMenuItemTextColor SystemListMediumColor
SelectedTextBackgroundColor
SelectedTextColor
Separator
SeparatorColor
ShadowColor
SystemBlue
SystemGray
SystemGreen
SystemIndigo
SystemOrange
SystemPink
SystemPurple
SystemRed
SystemTeal
SystemYellow
TertiaryLabel
TertiaryLabelColor
TextBackgroundColor
TextColor
UnderPageBackgroundColor
UnemphasizedSelectedContentBackgroundColor
UnemphasizedSelectedTextBackgroundColor
UnemphasizedSelectedTextColor
WindowBackgroundColor
WindowFrameTextColor

Device.StartTimer

La clase Device también tiene un método StartTimer que proporciona una manera sencilla de desencadenar tareas dependientes del tiempo que funcionan en código común de Xamarin.Forms, incluida una biblioteca de .NET Standard. Pase un TimeSpan para establecer el intervalo y devolver true para mantener el temporizador en ejecución o false para detenerlo después de la invocación actual.

Device.StartTimer (new TimeSpan (0, 0, 60), () =>
{
    // do something every 60 seconds
    return true; // runs again, or false to stop
});

Si el código dentro del temporizador interactúa con la interfaz de usuario (como establecer el texto de un Label o mostrar una alerta), debe realizarse dentro de una expresión de BeginInvokeOnMainThread (consulte a continuación).

Nota:

Las clases System.Timers.Timer y System.Threading.Timer son alternativas de .NET Standard al uso del método Device.StartTimer.

Interacción con la interfaz de usuario desde subprocesos en segundo plano

La mayoría de los sistemas operativos, incluidos iOS, Android y Plataforma universal de Windows, usan un modelo de un único subproceso para el código que participa en la interfaz de usuario. Con frecuencia, este subproceso se denomina el subproceso principal, el subproceso de UI. Una consecuencia de este modelo es que todo el código que accede a los elementos de la interfaz de usuario se deben ejecutar en el subproceso principal de la aplicación.

A veces, las aplicaciones usan subprocesos en segundo plano para realizar operaciones de larga duración, como recuperar datos de un servicio web. Si el código que se ejecuta en un subproceso en segundo plano necesita tener acceso a los elementos de la interfaz de usuario, debe ejecutar ese código en el subproceso principal.

La clase Device incluye los siguientes métodos static, que se pueden usar para interactuar con los elementos de la interfaz de usuario de los subprocesos de fondo:

Método Argumentos Valores devueltos Fin
BeginInvokeOnMainThread Action void Invoca un elemento Action en el subproceso principal y no espera a que se complete.
InvokeOnMainThreadAsync<T> Func<T> Task<T> Invoca un elemento Func<T> en el subproceso principal y espera a que se complete.
InvokeOnMainThreadAsync Action Task Invoca un elemento Action en el subproceso principal y espera a que se complete.
InvokeOnMainThreadAsync<T> Func<Task<T>> Task<T> Invoca un elemento Func<Task<T>> en el subproceso principal y espera a que se complete.
InvokeOnMainThreadAsync Func<Task> Task Invoca un elemento Func<Task> en el subproceso principal y espera a que se complete.
GetMainThreadSynchronizationContextAsync Task<SynchronizationContext> Devuelve el elemento SynchronizationContext para el subproceso principal.

En el código siguiente se muestra un ejemplo del uso del método BeginInvokeOnMainThread:

Device.BeginInvokeOnMainThread (() =>
{
    // interact with UI elements
});