Xamarin.Forms Device 类

Device 类包含许多属性和方法,可帮助开发人员在每个平台的基础上自定义布局和功能。

除了面向特定硬件类型和大小的代码的方法和属性之外,Device 类还包括可用于与后台线程中的 UI 控件交互的方法。 有关详细信息,请参阅从后台线程与 UI 交互

提供特定于平台的值

在 Xamarin.Forms 2.3.4 之前,可以通过检查 Device.OS 属性并将其与 TargetPlatform.iOSTargetPlatform.AndroidTargetPlatform.WinPhoneTargetPlatform.Windows 枚举值进行比较来获取应用程序运行的平台。 同样,其中一个 Device.OnPlatform 重载可用于向控件提供特定于平台的值。

但是,自 Xamarin.Forms 2.3.4 以来,这些 API 已被弃用并替换。 Device 类现包含公共字符串常量,这些常量用于标识平台 – Device.iOSDevice.AndroidDevice.WinPhone(已弃用)、Device.WinRT(已弃用)、Device.UWP 以及 Device.macOS。 同样,Device.OnPlatform 重载已替换为 OnPlatformOn API。

在 C# 中,可以通过在 Device.RuntimePlatform 属性上创建 switch 语句,然后为所需的平台提供 case 语句来提供特定于平台的值:

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);

OnPlatformOn 类在 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>

OnPlatform 类是泛型类,必须使用与目标类型匹配的 x:TypeArguments 特性进行实例化。 在 On 类中,Platform 属性可以接受单个 string 值或多个逗号分隔的 string 值。

重要

Platform 类中提供不正确的 On 特性值不会导致错误。 相反,代码将执行,而不会应用特定于平台的值。

或者,可以在 XAML 中使用 OnPlatform 标记扩展来自定义每个平台的 UI 外观。 有关详细信息,请参阅 OnPlatform 标记扩展

Device.Idiom

Device.Idiom 属性可用于根据应用程序正在运行的设备更改布局或功能。 TargetIdiom 枚举包含以下值:

  • 手机 – iPhone、iPod touch 和 Android 设备(像素小于 600 dip^)
  • 平板电脑 – iPad、Windows 设备和 Android 设备(像素大于 600 dip^)
  • 桌面设备 - 仅在 Windows 10 台式计算机上的 UWP 应用中返回(在移动 Windows 设备上返回 Phone,包括在 Continuum 方案中)
  • 电视 - Tizen 电视设备
  • 手表 - Tizen 手表设备
  • 不支持 – 未使用

^ dip 不一定是物理像素计数

Idiom 属性特别适用于构建利用较大屏幕的布局,如下所示:

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

OnIdiom 类在 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>

OnIdiom 类是泛型类,必须使用与目标类型匹配的 x:TypeArguments 特性进行实例化。

或者,可以在 XAML 中使用 OnIdiom 标记扩展,以根据运行应用程序的设备的惯用法来自定义 UI 外观。 有关详细信息,请参见 OnIdiom 标记扩展

Device.FlowDirection

Device.FlowDirection 值检索 FlowDirection 枚举值,该值表示设备正在使用的当前流方向。 流方向是指页面 UI 元素的浏览方向。 枚举值为:

在 XAML 中,可以使用 x:Static 标记扩展检索 Device.FlowDirection 值:

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

等效 C# 代码如下:

this.FlowDirection = Device.FlowDirection;

有关流方向的详细信息,请参阅从右到左本地化

Device.Styles

Styles 属性包含可应用于某些控件(例如 Label)的 Style 属性的内置样式定义。 可用样式包括:

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

Device.GetNamedSize

GetNamedSize 可在 C# 代码中设置 FontSize 时使用:

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 引入了对命名颜色的支持。 命名颜色是具有不同值的颜色,具体取决于设备上处于活动状态的系统模式(例如浅色或深色)。 在 Android 上,可通过 R.Color 类访问命名颜色。 在 iOS 上,命名颜色称为系统颜色。 在通用 Windows 平台上,命名颜色称为 XAML 主题资源

GetNamedColor 方法可用于检索 Android、iOS 和 UWP 上的命名颜色。 该方法采用 string 参数并返回 Color

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

当找不到颜色名称或在不支持的平台上调用 GetNamedColor 时,将返回 Color.Default

注意

由于 GetNamedColor 方法返回特定于平台的 Color,因此它通常与 Device.RuntimePlatform 属性结合使用。

NamedPlatformColor 类包含用于定义 Android、iOS 和 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

Device 类还有一种 StartTimer 方法,会提供一种简单的方法来触发在 Xamarin.Forms 通用代码中工作的时间相关任务,包括 .NET Standard 库。 传递 TimeSpan 以设置间隔并返回 true 以保持计时器运行,或返回 false 以在当前调用后停止计时器。

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

如果计时器内的代码与用户界面交互(如设置 Label 的文本或显示警报),则应在 BeginInvokeOnMainThread 表达式中完成(请参阅下文)。

注意

System.Timers.TimerSystem.Threading.Timer 类是使用 Device.StartTimer 方法的 .NET Standard 替代方法。

从后台线程与 UI 交互

大多数操作系统(包括 iOS、Android 和通用 Windows 平台)对涉及用户界面的代码使用单线程模型。 此线程通常称为“主线程”或“UI 线程”。 此模型的结果是,用于访问用户界面元素的所有代码必须在应用程序的主线程上运行。

应用程序有时使用后台线程执行可能长时间运行的操作,例如从 Web 服务检索数据。 如果在后台线程上运行的代码需要访问用户界面元素,则必须在主线程上运行该代码。

Device 类包括以下 static 方法,可用于与后台线程中的用户界面元素进行交互:

方法 自变量 返回 目的
BeginInvokeOnMainThread Action void 在主线程上调用 Action,无需等待其完成。
InvokeOnMainThreadAsync<T> Func<T> Task<T> 在主线程上调用 Func<T>,并等待其完成。
InvokeOnMainThreadAsync Action Task 在主线程上调用 Action,并等待其完成。
InvokeOnMainThreadAsync<T> Func<Task<T>> Task<T> 在主线程上调用 Func<Task<T>>,并等待其完成。
InvokeOnMainThreadAsync Func<Task> Task 在主线程上调用 Func<Task>,并等待其完成。
GetMainThreadSynchronizationContextAsync Task<SynchronizationContext> 返回主线程的 SynchronizationContext

以下代码演示了使用 BeginInvokeOnMainThread 方法的示例:

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