Xamarin.Forms Device Class
The Device
class contains a number of properties and methods to help developers customize layout and functionality on a per-platform basis.
In addition to methods and properties to target code at specific hardware types and sizes, the Device
class includes methods that can be used to interact with UI controls from background threads. For more information, see Interact with the UI from background threads.
Provide platform-specific values
Prior to Xamarin.Forms 2.3.4, the platform the application was running on could be obtained by examining the Device.OS
property and comparing it to the TargetPlatform.iOS
, TargetPlatform.Android
, TargetPlatform.WinPhone
, and TargetPlatform.Windows
enumeration values. Similarly, one of the Device.OnPlatform
overloads could be used to provide platform-specific values to a control.
However, since Xamarin.Forms 2.3.4 these APIs have been deprecated and replaced. The Device
class now contains public string constants that identify platforms – Device.iOS
, Device.Android
, Device.WinPhone
(deprecated), Device.WinRT
(deprecated), Device.UWP
, and Device.macOS
. Similarly, the Device.OnPlatform
overloads have been replaced with the OnPlatform
and On
APIs.
In C#, platform-specific values can be provided by creating a switch
statement on the Device.RuntimePlatform
property, and then providing case
statements for the required platforms:
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);
The OnPlatform
and On
classes provide the same functionality in 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>
The OnPlatform
class is a generic class that must be instantiated with an x:TypeArguments
attribute that matches the target type. In the On
class, the Platform
attribute can accept a single string
value, or multiple comma-delimited string
values.
Important
Providing an incorrect Platform
attribute value in the On
class will not result in an error. Instead, the code will execute without the platform-specific value being applied.
Alternatively, the OnPlatform
markup extension can be used in XAML to customize UI appearance on a per-platform basis. For more information, see OnPlatform Markup Extension.
Device.Idiom
The Device.Idiom
property can be used to alter layouts or functionality depending on the device the application is running on. The TargetIdiom
enumeration contains the following values:
- Phone – iPhone, iPod touch, and Android devices narrower than 600 dips^
- Tablet – iPad, Windows devices, and Android devices wider than 600 dips^
- Desktop – only returned in UWP apps on Windows 10 desktop computers (returns
Phone
on mobile Windows devices, including in Continuum scenarios) - TV – Tizen TV devices
- Watch – Tizen watch devices
- Unsupported – unused
^ dips is not necessarily the physical pixel count
The Idiom
property is especially useful for building layouts that take advantage of larger screens, like this:
if (Device.Idiom == TargetIdiom.Phone) {
// layout views vertically
} else {
// layout views horizontally for a larger display (tablet or desktop)
}
The OnIdiom
class provides the same functionality in 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>
The OnIdiom
class is a generic class that must be instantiated with an x:TypeArguments
attribute that matches the target type.
Alternatively, the OnIdiom
markup extension can be used in XAML to customize UI appearance based on the idiom of the device the application is running on. For more information, see OnIdiom Markup Extension.
Device.FlowDirection
The Device.FlowDirection
value retrieves a FlowDirection
enumeration value that represents the current flow direction being used by the device. Flow direction is the direction in which the UI elements on the page are scanned by the eye. The enumeration values are:
In XAML, the Device.FlowDirection
value can be retrieved by using the x:Static
markup extension:
<ContentPage ... FlowDirection="{x:Static Device.FlowDirection}"> />
The equivalent code in C# is:
this.FlowDirection = Device.FlowDirection;
For more information about flow direction, see Right-to-left Localization.
Device.Styles
The Styles
property contains built-in style definitions that can be applied to some controls' (such as Label
) Style
property. The available styles are:
- BodyStyle
- CaptionStyle
- ListItemDetailTextStyle
- ListItemTextStyle
- SubtitleStyle
- TitleStyle
Device.GetNamedSize
GetNamedSize
can be used when setting FontSize
in C# code:
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 introduces support for named colors. A named color is a color that has a different value depending on which system mode (for example, light or dark) is active on the device. On Android, named colors are accessed via the R.Color class. On iOS, named colors are called system colors. On the Universal Windows Platform, named colors are called XAML theme resources.
The GetNamedColor
method can be used to retrieve named colors on Android, iOS, and UWP. The method takes a string
argument and returns a Color
:
// Retrieve an Android named color
Color color = Device.GetNamedColor(NamedPlatformColor.HoloBlueBright);
Color.Default
will be returned when a color name cannot be found, or when GetNamedColor
is invoked on an unsupported platform.
Note
Because the GetNamedColor
method returns a Color
that's specific to a platform, it should typically be used in conjunction with the Device.RuntimePlatform
property.
The NamedPlatformColor
class contains the constants that define the named colors for Android, iOS, and 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
The Device
class also has a StartTimer
method which provides a simple way to trigger time-dependent tasks that works in Xamarin.Forms common code, including a .NET Standard library. Pass a TimeSpan
to set the interval and return true
to keep the timer running or false
to stop it after the current invocation.
Device.StartTimer (new TimeSpan (0, 0, 60), () =>
{
// do something every 60 seconds
return true; // runs again, or false to stop
});
If the code inside the timer interacts with the user-interface (such as setting the text of a Label
or displaying an alert) it should be done inside a BeginInvokeOnMainThread
expression (see below).
Note
The System.Timers.Timer
and System.Threading.Timer
classes are .NET Standard alternatives to using the Device.StartTimer
method.
Interact with the UI from background threads
Most operating systems, including iOS, Android, and the Universal Windows Platform, use a single-threading model for code involving the user interface. This thread is often called the main thread or the UI thread. A consequence of this model is that all code that accesses user interface elements must run on the application's main thread.
Applications sometimes use background threads to perform potentially long running operations, such as retrieving data from a web service. If code running on a background thread needs to access user interface elements, it must run that code on the main thread.
The Device
class includes the following static
methods that can be used to interact with user interface elements from backgrounds threads:
Method | Arguments | Returns | Purpose |
---|---|---|---|
BeginInvokeOnMainThread |
Action |
void |
Invokes an Action on the main thread, and doesn't wait for it to complete. |
InvokeOnMainThreadAsync<T> |
Func<T> |
Task<T> |
Invokes a Func<T> on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync |
Action |
Task |
Invokes an Action on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync<T> |
Func<Task<T>> |
Task<T> |
Invokes a Func<Task<T>> on the main thread, and waits for it to complete. |
InvokeOnMainThreadAsync |
Func<Task> |
Task |
Invokes a Func<Task> on the main thread, and waits for it to complete. |
GetMainThreadSynchronizationContextAsync |
Task<SynchronizationContext> |
Returns the SynchronizationContext for the main thread. |
The following code shows an example of using the BeginInvokeOnMainThread
method:
Device.BeginInvokeOnMainThread (() =>
{
// interact with UI elements
});