Clase auxiliar DualScreenInfo de Xamarin.Forms
La clase DualScreenInfo
permite determinar en qué panel se encuentra la vista, qué tamaño tiene, en qué posición está el dispositivo, el ángulo de la bisagra y mucho más.
Configuración de DualScreenInfo
Siga estas instrucciones para crear un diseño de doble pantalla en la aplicación:
- Siga las instrucciones de la sección Primeros pasos para agregar NuGet y configurar la clase
MainActivity
de Android. - Agregue
using Xamarin.Forms.DualScreen;
al archivo de clase. - Use la clase
DualScreenInfo.Current
en la aplicación.
Propiedades
- Cuando se distribuye en dos pantallas,
SpanningBounds
devuelve dos rectángulos que indican los límites de cada área visible. Si la ventana no está expandida, se devolverá una matriz vacía. HingeBounds
indica la posición de la bisagra en la pantalla.IsLandscape
indica si el dispositivo está en posición horizontal. Esto resulta útil porque las API de orientación nativas no notifican correctamente la orientación cuando una aplicación se distribuye en dos pantallas.SpanMode
indica si el diseño está en modo de alto, de ancho o de un solo panel.
Además, el evento PropertyChanged
se desencadena cuando cambian las propiedades, y el evento HingeAngleChanged
se desencadena cuando cambia el ángulo de la bisagra.
Sondeo del angulo de bisagra en Android y UWP
El método siguiente está disponible cuando se tiene acceso a DualScreenInfo
desde proyectos de la plataforma Android y UWP:
GetHingeAngleAsync
recupera el ángulo actual de la bisagra del dispositivo. Al usar el simulador, se puede establecer el valor de HingeAngle si se modifica el sensor de presión.
Este método se puede invocar desde los representadores personalizados en Android y UWP. En el código siguiente se muestra un ejemplo de representador personalizado de Android:
public class HingeAngleLabelRenderer : Xamarin.Forms.Platform.Android.FastRenderers.LabelRenderer
{
System.Timers.Timer _hingeTimer;
public HingeAngleLabelRenderer(Context context) : base(context)
{
}
async void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_hingeTimer == null)
return;
_hingeTimer.Stop();
var hingeAngle = await DualScreenInfo.Current.GetHingeAngleAsync();
Device.BeginInvokeOnMainThread(() =>
{
if (_hingeTimer != null)
Element.Text = hingeAngle.ToString();
});
if (_hingeTimer != null)
_hingeTimer.Start();
}
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (_hingeTimer == null)
{
_hingeTimer = new System.Timers.Timer(100);
_hingeTimer.Elapsed += OnTimerElapsed;
_hingeTimer.Start();
}
}
protected override void Dispose(bool disposing)
{
if (_hingeTimer != null)
{
_hingeTimer.Elapsed -= OnTimerElapsed;
_hingeTimer.Stop();
_hingeTimer = null;
}
base.Dispose(disposing);
}
}
Acceso a DualScreenInfo en la ventana de la aplicación
En el código siguiente se muestra cómo acceder a DualScreenInfo
en la ventana de la aplicación:
DualScreenInfo currentWindow = DualScreenInfo.Current;
// Retrieve absolute position of the hinge on the screen
var hingeBounds = currentWindow.HingeBounds;
// check if app window is spanned across two screens
if(currentWindow.SpanMode == TwoPaneViewMode.SinglePane)
{
// window is only on one screen
}
else if(currentWindow.SpanMode == TwoPaneViewMode.Tall)
{
// window is spanned across two screens and oriented top-bottom
}
else if(currentWindow.SpanMode == TwoPaneViewMode.Wide)
{
// window is spanned across two screens and oriented side-by-side
}
// Detect if any of the properties on DualScreenInfo change.
// This is useful to detect if the app window gets spanned
// across two screens or put on only one
currentWindow.PropertyChanged += OnDualScreenInfoChanged;
Aplicación de DualScreenInfo a los diseños
La clase DualScreenInfo
tiene un constructor que puede tomar un diseño y proporcionar información sobre él con respecto a las dos pantallas del dispositivo:
<Grid x:Name="grid" ColumnSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Column1Width}" />
<ColumnDefinition Width="{Binding Column2Width}" />
<ColumnDefinition Width="{Binding Column3Width}" />
</Grid.ColumnDefinitions>
<Label FontSize="Large"
VerticalOptions="Center"
HorizontalOptions="End"
Text="I should be on the left side of the hinge" />
<Label FontSize="Large"
VerticalOptions="Center"
HorizontalOptions="Start"
Grid.Column="2"
Text="I should be on the right side of the hinge" />
</Grid>
public partial class GridUsingDualScreenInfo : ContentPage
{
public DualScreenInfo DualScreenInfo { get; }
public double Column1Width { get; set; }
public double Column2Width { get; set; }
public double Column3Width { get; set; }
public GridUsingDualScreenInfo()
{
InitializeComponent();
DualScreenInfo = new DualScreenInfo(grid);
BindingContext = this;
}
protected override void OnAppearing()
{
base.OnAppearing();
DualScreenInfo.PropertyChanged += OnInfoPropertyChanged;
UpdateColumns();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
DualScreenInfo.PropertyChanged -= OnInfoPropertyChanged;
}
void UpdateColumns()
{
// Check if grid is on two screens
if (DualScreenInfo.SpanningBounds.Length > 0)
{
// set the width of the first column to the width of the layout
// that's on the left screen
Column1Width = DualScreenInfo.SpanningBounds[0].Width;
// set the middle column to the width of the hinge
Column2Width = DualScreenInfo.HingeBounds.Width;
// set the width of the third column to the width of the layout
// that's on the right screen
Column3Width = DualScreenInfo.SpanningBounds[1].Width;
}
else
{
Column1Width = 100;
Column2Width = 0;
Column3Width = 100;
}
OnPropertyChanged(nameof(Column1Width));
OnPropertyChanged(nameof(Column2Width));
OnPropertyChanged(nameof(Column3Width));
}
void OnInfoPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
UpdateColumns();
}
}
En la captura de pantalla siguiente se muestra el diseño resultante: