Xamarin.Forms DualScreenInfo 帮助程序类
DualScreenInfo
类可用于确定你的视图位于哪个窗格中、视图的大小如何、设备的放置方向如何,以及铰链的角度等等。
配置 DualScreenInfo
按照下列说明在应用中创建一个双屏布局:
- 按照入门说明添加 NuGet 并配置 Android
MainActivity
类。 - 将
using Xamarin.Forms.DualScreen;
添加到类文件中。 - 在应用中使用
DualScreenInfo.Current
类。
属性
- 在横跨两个屏幕时,
SpanningBounds
将返回两个矩形,表示每个可见区域的边界。 如果该窗口未跨屏,它将返回一个空数组。 HingeBounds
指示铰链在屏幕上的位置。IsLandscape
:指示设备是否横向显示。 这很有用,因为应用程序跨屏显示时,本机方向 API 不会正确报告方向。SpanMode
:指示布局处于 Tall、Wide 还是 SinglePane 模式下。
此外,在任何属性发生更改时,将触发 PropertyChanged
事件,当铰链角度改变时,将触发 HingeAngleChanged
事件。
Android 和 UWP 上的轮询铰链角度
从 Android 和 UWP 平台项目访问 DualScreenInfo
时,可以使用以下方法:
GetHingeAngleAsync
会检索设备铰链的当前角度。 使用模拟器时,可通过修改压力传感器来设置 HingeAngle。
可从 Android 和 UWP 上的自定义呈现器调用此方法。 以下代码显示了 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);
}
}
访问应用程序窗口中的 DualScreenInfo
下面的代码演示了如何访问应用程序窗口的 DualScreenInfo
:
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;
将 DualScreenInfo 应用到自己的布局
DualScreenInfo
类有一个构造函数,它可采用布局并向你显示与设备双屏相关的布局信息:
<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();
}
}
以下屏幕截图显示了生成的布局: