CHAPTER 2
The Xamarin Community Toolkit includes several views that are of common use in mobile apps but that were not available in the Xamarin.Forms code base, filling the gap with native development. Views also include new layouts, which extend the possibilities of arranging the user interface. This chapter describes layouts and views offered by the library, using the official sample project as the starting point, but with many considerations about practical use.
Three new layouts are available in the Xamarin Community Toolkit: DockLayout, StateLayout, and UniformGrid. Actually, as you’ll discover shortly, the StateLayout is rather a collection of attached properties, but it is classified as a layout. This section describes both, and the sample pages are located under the Pages\Views folder of the official sample project.
DockLayout is a new layout that allows for docking child visual elements in all the four directions (top, bottom, left, right). If you run the sample app and look at Figure 5, you can see how several visual elements (Button views, to be precise) are docked in different positions.
Figure 5: Docking contents on four directions
The XAML code for this example is the following.
<xct:DockLayout
LastChildFill="False">
<Button xct:DockLayout.Dock="Top" Text="Top" HeightRequest="50"/>
<Button xct:DockLayout.Dock="Bottom" Text="Bottom"
HeightRequest="50"/>
<Button xct:DockLayout.Dock="Left" Text="Left" WidthRequest="60"/>
<Button xct:DockLayout.Dock="Left" Text="Left" WidthRequest="60"/>
<Button xct:DockLayout.Dock="Right" Text="Right" WidthRequest="80"/>
<Button xct:DockLayout.Dock="Right" Text="Right" WidthRequest="80"/>
</xct:DockLayout>
These are the relevant points:
DockLayout is extremely useful and adds a lot of flexibility to the user interface, so this is really a great addition.
Sometimes you might need to display specific views when the app is in a specific state, for example, displaying loaders when the app is busy doing something, or an error message when something went wrong. With the StateLayout control, you can turn any layout element, like a Grid or StackLayout, into an individual state-aware element.
Each layout that you make state-aware, using the StateLayout attached properties, contains a collection of StateView objects. These objects can be used as templates for the different states supported by StateLayout. Whenever the CurrentState property is set to a value that matches the State property of one of the StateViews, its contents will be displayed instead of the main content.
This view is demonstrated in the Pages\Views\StateLayoutPage.xaml, and if you run the sample app, you can press the Cycle All States button to get an example of how each state can be used to display a specific view for each state. Figure 6 shows an example.
Figure 6: Assigning views to a specific state
Possible states are defined in the LayoutState enumeration, and values can be: None, Loading, Saving, Success, Error, Empty, and Custom. For example, let’s consider the first piece of the XAML code that defines a StateView for a Grid, to be used when the state is loading.
<Grid xct:StateLayout.CurrentState="{Binding MainState}"
xct:StateLayout.AnimateStateChanges="true">
<xct:StateLayout.StateViews>
<xct:StateView StateKey="Loading"
BackgroundColor="White"
VerticalOptions="FillAndExpand">
<StackLayout VerticalOptions="Center"
HorizontalOptions="Center">
<ActivityIndicator Color="#1abc9c"
IsRunning="{Binding MainState,
Converter={StaticResource StateToBooleanConverter},
ConverterParameter={x:Static
xct:LayoutState.Loading}}" />
<Label Text="Loading..." HorizontalOptions="Center" />
</StackLayout>
</xct:StateView>
</xct:StateLayout.StateViews>
</Grid>
As you can see, the Grid uses attached properties of the StateLayout. In the example, the CurrentState property is bound to a property called MainState of type LayoutState, and is defined in the backing StateLayoutViewModel class. It represents the current state of the view, and when it’s None, it’s in a default state. By specifying the collection of StateViews, you can decide what happens when a state changes.
In this case, a StateView object specifies that if the state changes to Loading, the content of the Grid must be replaced by a StackLayout containing an ActivityIndicator. When the state changes back to None, the Grid will also return to display its original content. The type of state can be supplied by assigning the StateKey property of the StateView with one of the values from the LayoutState enumeration.
Notice how the ActivityIndicator.IsRunning property is bound to the current state and converted from LayoutState to bool via the StateToBooleanConverter class. The latter returns true if the value of the bound property (MainState in this case) equals the state supplied via the ConverterParameter.
The other states in the example work similarly, but with a different state. The key point is that you can supply a view for a different state directly inside the current view, without the need to implement custom logic for state changes and without the need to create a more complex UI hierarchy.
You can also implement custom states by using the Custom value from the LayoutState enumeration in combination with the CustomStateKey property of the StateView object. An example is available in the XAML code of the StateLayoutPage.xaml file.
<xct:StateView StateKey="Custom" CustomStateKey="ThisIsCustomToo">
<Label Text="Hi, I'm a custom state too!" VerticalOptions="Center"
VerticalTextAlignment="Center"
HorizontalOptions="Center" HorizontalTextAlignment="Center" />
</xct:StateView>
The binding will then work exactly as explained in the previous steps.
The third and last view offered by the Xamarin Community Toolkit is the UniformGrid. This is a simplified Grid with rows and columns of the same size. The usage, demonstrated in the Pages\Views\UniformGridPage.xaml file, is extremely simple, and the sample code is the following.
<xct:UniformGrid>
<BoxView Color="Red" />
<BoxView Color="Yellow" />
<BoxView Color="Orange" />
<BoxView Color="Purple" />
<BoxView Color="Blue" />
<BoxView Color="Green" />
<BoxView Color="LightGreen" />
<BoxView Color="Gray" />
<BoxView Color="Pink" />
</xct:UniformGrid>
The result is visible in Figure 7. Notice that, unlike in the regular Grid, it is not possible to specify the RowDefinitions and ColumnDefinitions collections, because the UniformGrid automatically arranges its content wrapping and alignment as necessary.
Figure 7: The UniformGrid in action
New design standards have risen in the recent years, and consequently, new views have entered into common mobile app designs as well. The Xamarin Community Toolkit bridges the gap between the Xamarin.Forms code base and such new designs, introducing views that are now common in mobile apps, and that will help you be more productive by avoiding spending time on creating custom views.
An avatar identifies a profile picture of a person or contact, and when the image is not available, the avatar usually displays the initials of the person’s name. There are many programs that use avatars to identify people or contacts; Microsoft Outlook is an example.
The Xamarin Community Toolkit makes it easy to use avatars in your apps by offering the AvatarView control. For an understanding of how it works, look at Figure 8, which shows the sample app in action on the Pages\Views\AvatarViewPage.xaml file.
![]()
Figure 8: The AvatarView in action
The app shows a list of people, some of whom are real people currently working at Microsoft, whereas the Xamarin Monkey and Unknown are test data. Pictures are assigned to the AvatarView via the public URL, and you will shortly see how. The user interface of the page mainly consists of a CollectionView, which is populated with the Items property of the AvatarViewViewModel class, whose code is represented in Code Listing 1.
Code Listing 1
namespace Xamarin.CommunityToolkit.Sample.ViewModels.Views { public class AvatarViewViewModel : BaseViewModel { public object[] Items { get; } = { new { Initials = "AM", Source = string.Empty, Name = "Andrei Misiukevich" }, new { Initials = "DO", Source = "https://picsum.photos/500/500?image=472", Name = "David Ortinau" }, new { Initials = "ST", Source = "https://picsum.photos/500/500?image=473", Name = "Steven Thewissen" }, new { Initials = "GV", Source = string.Empty, Name = "Glenn Versweyveld" }, new { Initials = "JSR", Source = string.Empty, Name = "Javier Suárez Ruiz" }, new { Initials = "GV", Source = "https://picsum.photos/500/500?image=474", Name = "Gerald Versluis" }, new { Initials = "XM", Source = "https://picsum.photos/500/500?image=475", Name = "Xamarin Monkey" }, new { Initials = string.Empty, Source = string.Empty, Name = "Unknown" } }; } } |
The Items property is of type object[] and contains a collection of anonymous types. This has been probably implemented in this way for the sake of speed, but in the real world, you will want to expose a strongly typed ObservableCollection.
Each object instance allows for specifying an image URL (Source property), name initials if an image is not available (Initials property), and the full name (Name property). In the XAML code of the page, the AvatarView represents the DataTemplate of the CollectionView, and is declared as follows.
<xct:AvatarView ColorTheme="{x:Static xct:ColorTheme.Jungle}"
FontSize="Medium"
Size="{Binding Value,
Source={x:Reference Slider}}"
Text="{Binding Initials}">
<xct:AvatarView.Source>
<UriImageSource Uri="{Binding Source}" />
</xct:AvatarView.Source>
</xct:AvatarView>
The most relevant points in this code are the following:
If no image and no initials are available, the AvatarView will simply display an X character, which is the initial of Xamarin.
The BadgeView allows you to display overlayed icons on a view, known as badges, and it is typically used to display new notifications such as the number of new contents in the app. The BadgeView is demonstrated in the Pages\Views\BadgeViewPage.xaml of the sample project, and Figure 9 shows several instances in action.

Figure 9: The BadgeView in action
As you can see, you can use this view to show how many new notifications the user got in the app. We can discuss how it works starting from the first instance at the top of the XAML, and then adding information incrementally. At a glance, the BadgeView can be thought of as a transparent container for another view, on which it overlays a badge with the string you want to display. In terms of XAML, this works as follows.
<xct:BadgeView
BackgroundColor="Red" TextColor="White" Text="1">
<Label
Text="BadgeView"/>
</xct:BadgeView>
As you can see, the Label that displays the notification is surrounded by the BadgeView. You can specify the background color and the text color. The Text property is of type string, so you are not limited to displaying only numbers. You do not necessarily need to pass something, so you can also use an empty string if your purpose is only attracting the attention of the user.
Let’s now walk through possible customizations you can do over the control, and that you will be able to find in the continuing XAML code.
You can customize the font of the BadgeView via the FontFamily, FontAttributes, and FontSize properties, as you would do with any other view supporting text. FontSize also supports named size values (such as Normal, Medium, and Large).
You can assign the BorderColor property with a value of type Color and set a different color for the border of the BadgeView, so you can have different border and background colors. In addition, you can set the HasShadow property with true if you want to display a shadow below the control. The default is false.
By default, the badge is placed at the top-right corner. However, it is possible to specify a different position by assigning the BadgePosition property with one of the values from the BadgePosition enumeration, all self-explanatory, which can be TopLeft, TopRight, BottomLeft, or BottomRight. Figure 9 has clear examples of repositioning the badge.
The child content of a BadgeView can be any visual element, which means you can design a layout (such as a Grid or StackLayout) and create a more complex view, and badges will work exactly as expected.
In the past, you could add camera capabilities to your Xamarin.Forms projects using the Media plugin. This allowed you to capture videos and photos from your device’s camera and did an excellent job, but it was not optimized for .NET Standard, and was in the charge of an individual developer, which means it could be maintained only when and if possible.
The Xamarin Community Toolkit brings back camera capabilities, and it integrates perfectly with the latest version of Xamarin.Forms—plus, it is fully backed by Microsoft. Camera support is offered by the CameraView control, which allows for capturing videos and images from your device. It is demonstrated in the Pages\Views\CameraView.xaml file. The result of this sample page is visible in Figure 10. Notice that it is based on the simulator, so the camera is presenting a fake image.

Figure 10: Capturing media from your device
You can control several options of the camera and record the captured content, and now you will see how. In the sample XAML code, the CameraView is defined as follows.
<xct:CameraView
x:Name="cameraView"
CaptureMode="Video"
FlashMode="On"
HorizontalOptions="FillAndExpand"
MediaCaptured="CameraView_MediaCaptured"
OnAvailable="CameraView_OnAvailable"
VerticalOptions="FillAndExpand" />
The CaptureMode property can be assigned with Video, Photo, or Default (which goes for taking a picture if the property is not specified). The FlashMode option can be assigned with On or Off. When the camera starts running on the device, the OnAvailable event is raised. In terms of camera availability, you might want to check in your apps whether the value of the read-only CameraView.IsAvailable property returns true.
In the sample code-behind for the page, the code sets the camera zoom based on the value of a Slider defined in the user interface. The CameraView exposes two properties for managing the zoom, both of type double. Zoom represents the current zoom value for the camera, and MaxZoom represents the maximum zoom value for the camera.
Another interesting property is CameraOptions, which allows for selecting the current camera, and whose value can be Default, Back, Front, or External. Default matches the default camera settings of the device.
The IsBusy property is also interesting and returns true if the camera is busy capturing media and cannot be used. When working with media content, the CameraView allows you to handle two events: MediaCaptured and MediaCaptureFailed. The first one is raised once the user stops capturing content, which means taking a picture or recording a video.
The code-behind for the sample page shows how to handle the event as follows.
void CameraView_MediaCaptured(object? sender,
MediaCapturedEventArgs e)
{
switch (cameraView.CaptureMode)
{
default:
case CameraCaptureMode.Default:
case CameraCaptureMode.Photo:
previewPicture.IsVisible = true;
previewPicture.Rotation = e.Rotation;
previewPicture.Source = e.Image;
doCameraThings.Text = "Snap Picture";
break;
case CameraCaptureMode.Video:
previewPicture.IsVisible = false;
doCameraThings.Text = "Start Recording";
break;
}
}
If the camera is capturing a picture, an image view called previewPicture is made visible, and its Source property is assigned with the captured image, which is stored in the Image property of the MediaCapturedEventArgs object instance (and saved on the device if the camera settings allow for this).
The user interface also defines a Button called doCameraThings, whose text is changed based on the selection of taking a picture. Before discussing how things work when working with videos, let’s have a look at the XAML code for both views.
<Button
x:Name="doCameraThings"
Command="{Binding ShutterCommand, Source={x:Reference cameraView}}"
IsEnabled="False" Text="Start Recording" />
<Image
x:Name="previewPicture"
Aspect="AspectFit" BackgroundColor="LightGray"
HeightRequest="250" IsVisible="False" />
The Command property of the Button is bound to the ShutterCommand property of the CameraView. This command is invoked when the shutter is triggered. Regarding videos, when the user stops capturing, the media content is just saved on the device.
Tip: Remember that a real application must ask for the user’s permission before accessing the camera. This can be quickly accomplished via the Permissions class from the Xamarin Essentials library.
The Expander is a view that can contain a hierarchy of visual elements, display them when expanded, and hide them when collapsed. In mobile app designs, this kind of view is also known as accordion. In the sample project, it is demonstrated in the Pages\Views\ExpanderPage.xaml file. If you look at the source code, you can see the following declaration.
<xct:Expander ExpandAnimationEasing="{x:Static Easing.CubicIn}"
CollapseAnimationEasing="{x:Static Easing.CubicOut}"
IsExpanded="{Binding IsExpanded}"
Command="{Binding BindingContext.Command,
Source={x:Reference page}}"
CommandParameter="{Binding .}">
With the ExpandAnimationEasing and CollapseAnimationEasing properties, you can assign the animation that runs when the Expander is expanded or collapsed. The IsExpanded property, of type bool, allows for programmatically controlling the status of the Expander.
You can also execute an action when the Expander is engaged via the Command property and its CommandParameter value. When the Expander is collapsed, the view displays the value of its Header property, defined as follows.
<xct:Expander.Header>
<StackLayout Orientation="Horizontal" Spacing="0">
<Label Text="{Binding Name}"
HorizontalOptions="FillAndExpand"
FontSize="32"
FontAttributes="Bold"/>
<Label Text="Enable nested:"
FontSize="13"
VerticalOptions="CenterAndExpand" />
<Switch IsToggled="{Binding IsEnabled}" />
</StackLayout>
</xct:Expander.Header>
The value of the Header is an individual view, which can also be a layout for a more complex visual hierarchy. When the Expander is expanded, the view displays the value of its Content property. This is an implicit property, so you can omit declaring it explicitly, and the view will display the visual element included between the enclosing tags as follows.
<xct:Expander>
<!-- Content goes here… -->
</xct:Expander>
In the sample code, the Content is another Expander to demonstrate nested expanders. Notice that the Content property should only include an individual View object. If you wish to use a layout for a more complex visual hierarchy, you can use the ControlTemplate property, in which you define a DataTemplate that contains your structure.
<xct:Expander.ContentTemplate>
<DataTemplate>
<StackLayout Spacing="0" Margin="10"
Padding="1" BackgroundColor="Black">
<BoxView HeightRequest="50" Color="White" />
<BoxView HeightRequest="50" Color="Red" />
<BoxView HeightRequest="50" Color="White" />
</StackLayout>
</DataTemplate>
</xct:Expander.ContentTemplate>
Figure 11 shows how the sample page appears.

Figure 11: Displaying contents with the Expander
One common implementation of the header is using arrow icons. For instance, an up-arrow icon indicates a collapsed state, and a down-arrow icon indicates an expanded state.
Gravatar is an online service for providing globally unique avatars, and it is widely used to create certified profile pictures. By creating a profile picture on Gravatar, you can be sure that your identity is safe. The profile picture is strictly related to your email address, and this is an important point to highlight, as you will see shortly.
The Xamarin Community Toolkit allows for displaying certified profile pictures from Gravatar via the GravatarImageSource class, which is demonstrated in the Pages\Views\GravatarImagePage.xaml file of the sample project. This object retrieves an image from Gravatar and returns an ImageSource object that can be assigned to an Image view.
A XAML markup extension is also available, and you are going to see both options in action. A good idea is first having a look at the sample page in action on the device, shown in Figure 12.
![]()
Figure 12: Displaying profile pictures from Gravatar
As you can see, an email address is specified, and it is how the GravatarImageSource can download the profile picture from Gravatar. In the example, you see the same picture twice, but in the XAML this happens with a different syntax. You also see a default picture, which you can use in several situations, such as download errors.
If you now look at the XAML code of the page, you will see that the first image is displayed via the following markup.
<Image>
<Image.Source>
<xct:GravatarImageSource Email="{Binding Email}"
Size="{Binding Size}"
CachingEnabled="{Binding EnableCache}" />
</Image.Source>
</Image>
As you can see, the GravatarImageSource object is populating the ImageSource property of the Image view, and the source for the picture is specified via the Email property. In the sample project, the email is exposed by the Email property of the GravatarImageViewModel class, and it is of type string.
You can also specify a size for the picture, with the Size property of type int whose value can be between 0 and 100. You can also cache the image via the CachingEnabled property in order to optimize memory. Both Size and EnableCache binding properties are exposed by the ViewModel. As an alternative, you can use the GravatarImage markup extension, which offers an inline syntax and works as follows.
<Image Source="{xct:GravatarImage {Binding Email},
Size=65, CachingEnabled={Binding EnableCache}}" />
The key point here is that you can use the GravatarImage markup extension directly in the binding specification for the Image.Source property. It is also possible to provide a default picture in case the GravatarImageSource is not able to retrieve the proper one, and this is possible by assigning the Default property with an object of type DefaultGravatar.
The sample XAML is the following.
<Image Source="{xct:GravatarImage '',
Default={Binding DefaultGravatar},
Size={Binding Size}, CachingEnabled={Binding EnableCache}}" />
In the example, the source for the image is intentionally empty so that the value of the Default property is used, as you can also see in Figure 12 with the third image from the top. The DefaultGravatar object is an enumeration defined as follows.
public enum DefaultGravatar
{
FileNotFound,
MysteryPerson,
Identicon,
MonsterId,
Wavatar,
Retro,
Robohash,
Blank
}
In the GravatarImageViewModel class, the DefaultGravatar property is initialized with the MysteryPerson value, but the user interface of the sample app allows you to select a different one via a Picker so that you can get a preview of how each default image looks. With this approach, you can quickly display a certified picture for a person and, if not available, you can warn your users with a default image.
The Xamarin Community Toolkit provides a new view called MediaElement, which allows for playing audio and video in your applications. Actually, during its development, the MediaElement control was included in the Xamarin.Forms code base, but now it has been moved to the Xamarin Community Toolkit library.
MediaElement can play media content from a remote URI, from the local library, from media files embedded inside the app resources, and from local folders. In the sample project, it is demonstrated in the Pages\Views\MediaElementPage.xaml file, and it is based on a free, public Microsoft video about Xamarin that can be streamed online.
Figure 13 shows the MediaElement in action. Notice how the player shows buttons that allow for controlling the media reproduction, such as Play and Pause.

Figure 13: Playing audio and video
In the XAML, it is declared as follows.
<xct:MediaElement
x:Name="mediaElement"
Source="https://sec.ch9.ms/ch9/5d93/a1eab4bf-3288-4faf-81c4-294402a85d93/XamarinShow_mid.mp4"
ShowsPlaybackControls="True" MediaOpened="OnMediaOpened"
MediaFailed="OnMediaFailed" MediaEnded="OnMediaEnded"
HorizontalOptions="Fill" SeekCompleted="OnSeekCompleted" />
The Source property contains the URI of the media file. As you can learn through the official documentation, local files are also represented by URIs that start with the ms-appx:/// or ms-appdata:/// prefixes. The ShowsPlaybackControls property allows you to avoid the need to create playback controls manually and will make the MediaElement use the playback control of each native platform.
You certainly have the option to create your custom controls and use data binding to provide a different look and feel to your player, but this is out of the scope of this chapter. You can make media start automatically by setting the AutoPlay property with true, and you can control the media volume using the Volume property, of type double. Its value must be between 0 and 1.
The MediaElement also exposes the Aspect property, which controls the stretching of the video, and supported values are Fill, AspectFill, and AspectFit. The Duration property, of type TimeSpan?, returns the duration of the currently opened media, while the Position property, of type TimeSpan, returns the current progress over the duration.
The MediaElement view also exposes self-explanatory methods such as Play, Stop, and Pause that you can invoke in your C# code to manually control the media file. Additionally, among others, this view exposes events like:
The MediaElement is at the same time a very versatile view in its simplest form, and a completely customizable view for high-quality media playing designs.
The Shield is a view that allows for displaying information about the status of a service or a call to action in a badge-like way. Shields are very popular nowadays; for example, they are used to display information on software status on websites like NuGet, GitHub, and Azure Pipelines. With the Xamarin Community Toolkit, you can create shields as demonstrated in Figure 14.

Figure 14: Creating shields
In the sample project, the Shield view is demonstrated in the Pages\Views\ShieldPage.xaml file. A shield is made of two parts: the subject and the status. The subject is the left part and represents the name of the item to which the shield refers, whereas the status provides information on the current status of the item. Both parts are represented by properties in the Shield view, called Subject and Status respectively, both of type string?.
There are many Shield declarations in the XAML code for the page, but we will consider just two of them, since they all work in the same way—just with different property values. The first Shield to consider is also the first one in the code and is declared as follows.
<xct:Shield Grid.Row="0" Grid.Column="0"
Subject="C#"
Status=">=4.5"
StatusBackgroundColor="DodgerBlue"
StatusTextColor="White"
Tapped="OnShieldTapped" />
The Subject and Status properties are assigned with the strings you want to display in the two parts. You can customize colors for both parts, as well. For the status, you can use the StatusBackgroundColor property to customize the background and the StatusTextColor to customize the foreground color of the status string. Similarly, you can assign the SubjectBackgroundColor and SubjectTextColor properties to customize the subject background color and foreground color, respectively.
The Shield supports interaction; in fact, it exposes the Tapped event. In the sample project, the event is simply handled to display an alert as follows.
async void OnShieldTapped(object? sender, EventArgs e)
=> await DisplayAlert("Shield Event", "C# Shield Tapped", "Ok");
The second Shield that is taken into consideration is the following.
<xct:Shield Grid.Row="3" Grid.Column="0"
Subject="Radio"
StatusBackgroundColor="Red"
SubjectBackgroundColor="Cyan"
SubjectTextColor="Black"
Status="LIVE"
StatusTextColor="White"
FontSize="Large" />
In this example, you see color customization for the subject as described previously, plus you see how to customize the font size. You can use both named font sizes and numbers. Also, you can use the FontFamily and FontAttributes properties to further customize the font appearance as you would do with any other control that supports text.
Shields are probably not very common in mobile apps, but if your project needs to display the status of some services, then they can be a valid choice with no effort.
The RangeSlider view is an evolved, highly customizable version of the well-known Slider. It shows two thumbs that allow for selecting numerical values in a range. It is demonstrated in the Pages\Views\RangeSliderPage.xaml file.
If you run the sample app and enter the related example, you will be able to play with the RangeSlider by customizing its appearance. All the possible options are offered in the page, as shown in Figure 15, where you can see possible customizations available by scrolling the page.

Figure 15: Customizing a RangeSlider
For example, you can customize the thumbs with any View; you can change the size and color of the sliding track, the size and color of the thumbs, and the corner radius of the thumbs.
In the XAML for the sample page, most of the RangeSlider properties are data-bound to other views in the page, such as pickers that allow for selecting different colors, as you might have seen if you have played with the example in the app. Code Listing 2 shows how it is declared.
Code Listing 2
<xct:RangeSlider x:Name="RangeSlider" MaximumValue="10" MinimumValue="-10" StepValue="0.01" LowerValue="-10" UpperValue="10" ValueLabelStringFormat="{StaticResource CustomValueLabeStringFormat}" LowerValueLabelStyle="{StaticResource CustomLowerValueLabelStyle}" UpperValueLabelStyle="{StaticResource CustomUpperValueLabelStyle}" ThumbSize="{Binding Value, Source={x:Reference ThumbSizeSlider}}" ThumbColor="{Binding SelectedItem, Source={x:Reference ThumbColorPicker}}" LowerThumbColor="{Binding SelectedItem, Source={x:Reference LowerThumbColorPicker}}" UpperThumbColor="{Binding SelectedItem, Source={x:Reference UpperThumbColorPicker}}" ThumbBorderColor="{Binding SelectedItem, Source={x:Reference ThumbBorderColorPicker}}" LowerThumbBorderColor="{Binding SelectedItem, Source={x:Reference LowerThumbBorderColorPicker}}" UpperThumbBorderColor="{Binding SelectedItem, Source={x:Reference UpperThumbBorderColorPicker}}" TrackSize="{Binding Value, Source={x:Reference TrackSizeSlider}}" TrackColor="{Binding SelectedItem, Source={x:Reference TrackColorPicker}}" TrackHighlightColor="{Binding SelectedItem, Source={x:Reference TrackHighlightColorPicker}}" TrackBorderColor="{Binding SelectedItem, Source={x:Reference TrackBorderColorPicker}}" TrackHighlightBorderColor="{Binding SelectedItem, Source={x:Reference TrackHighlightBorderColorPicker}}" IsEnabled="{Binding IsToggled, Source={x:Reference IsEnabledSwitch}}" ValueLabelSpacing="{Binding Value, Source={x:Reference ValueLabelSpacingSlider}}"> <xct:RangeSlider.LowerThumbView> <Label Text="L" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" IsVisible="{Binding IsToggled, Source={x:Reference LowerThumbViewSwitch}}" /> </xct:RangeSlider.LowerThumbView> <xct:RangeSlider.UpperThumbView> <Label Text="U" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" IsVisible="{Binding IsToggled, Source={x:Reference UpperThumbViewSwitch}}" /> </xct:RangeSlider.UpperThumbView> </xct:RangeSlider> |
Table 1 provides a description of the properties used in the XAML.
Table 1: RangeSlider properties
Property | Type | Description |
|---|---|---|
LowerThumbBorderColor | Color | Gets or sets the border color of the lower thumb. |
LowerThumbColor | Color | Gets or sets the color of the lower thumb. |
LowerThumbRadius | double | Gets or sets the corner radius of the lower thumb. |
LowerThumbSize | double | Gets or sets the size of the lower thumb. |
LowerThumbView | View | Gets or sets a custom view to be used for the lower thumb. |
LowerValue | double | Gets or sets the lower value of the range. |
LowerValueLabelStyle | Style | Gets or sets the style used for the value label on the lower thumb. |
MaximumValue | double | Gets or sets the maximum value for the range that can be selected with the RangeSlider. |
MinimumValue | double | Gets or sets the minimum value for the range that can be selected with the RangeSlider. |
StepValue | double | Gets or sets the increment by which MaximumValue and MinimumValue change. |
ThumbBorderColor | Color | Gets or sets the border color of both the lower and upper thumbs. |
ThumbColor | Color | Gets or sets the color for both the lower and upper thumbs. |
ThumbSize | double | Gets or sets size for both the lower and upper thumbs. |
TrackBorderColor | Color | Gets or sets the color of the track bar border. |
TrackColor | Color | Gets or sets the color of the track bar. |
TrackHighlightBorderColor | Color | Gets or sets the border highlight color of the track bar, which is the part between the lower and the upper thumbs. |
TrackHighlightColor | Color | Gets or sets highlight color of the track, which is the part between the lower and the upper thumbs. |
TrackRadius | double | Gets or sets the corner radius of the track. |
TrackSize | double | Gets or sets the size of the track bar. |
UpperThumbBorderColor | Color | Gets or sets the border color of the upper thumb. |
UpperThumbColor | Color | Gets or sets the color of the upper thumb. |
UpperThumbRadius | double | Gets or sets the corner radius of the upper thumb. |
UpperThumbSize | double | Gets or sets the size of the upper thumb. |
UpperThumbView | View | Gets or sets a custom view to be used for the upper thumb. |
UpperValue | double | Gets or sets the upper value of the range. |
UpperValueLabelStyle | Style | Gets or sets the style used for the value label on the upper thumb. |
ValueLabelStringFormat | double | Gets or sets the string format used for the value labels on both the lower and upper thumbs. |
ValueLabelSpacing | double | Gets or sets the spacing of the font used for the value labels on both the lower and upper thumbs. |
ValueLabelStyle | Style | Gets or sets the style used for the value labels on both the lower and upper thumbs. |
Properties described in Table 1 are bindable properties, so for example, you could bind the Value to a command in the ViewModel and handle the value change. However, the RangeSlider also exposes events. These are summarized in Table 2.
Table 2: RangeSlider events
Event | Description |
|---|---|
ValueChanged | Occurs when the value changes. |
LowerValueChanged | Occurs when the lower value of the range changes. |
UpperValueChanged | Occurs when the upper value of the range changes. |
DragStarted | Occurs when a drag action is started on the lower or upper thumb. |
LowerDragStarted | Occurs when a drag action is started with the lower thumb. |
UpperDragStarted | Occurs when a drag action is started with the upper thumb. |
DragCompleted | Occurs when a drag action is completed on the lower or upper thumb. |
LowerDragCompleted | Occurs when a drag action is completed on the lower thumb. |
UpperDragCompleted | Occurs when a drag action is completed on the upper thumb. |
In summary, the biggest benefits of using a RangeSlider are the high level of customization, and that it allows for selecting a range using two thumbs instead of selecting a single value as with the regular Slider.
The Xamarin Community Toolkit offers great shortcuts to display toast notifications and snackbars quickly. From a layout perspective, they are similar because they are both represented by a box with some information inside, which typically auto-dismisses after a certain amount of time. However, toast notifications are normally used to display system messages. Snackbars typically show a message related to the latest operation done in the app, and they should contain a single-line message and no icon.
With regard to this, the Xamarin Community Toolkit implements two extension methods that extend the VisualElement class: DisplayToastAsync and DisplaySnackBarAsync, both demonstrated in the Pages\Views\SnackBarPage.xaml file. The sample page has four buttons, each opening a snackbar or toast notification. I will start by discussing toast notifications. They are implemented via the Clicked event handler for the DisplayToastClicked button as follows.
async void DisplayToastClicked(object? sender, EventArgs args)
{
await this.DisplayToastAsync(GenerateLongText(5));
StatusText.Text = "Toast is closed by timeout";
}
You can display a toast notification by invoking the DisplayToastAsync method on the current page instance. The method takes the string to display; in this case, an intentionally long string is generated by the GenerateLongText method. The toast notification disappears after 3,000 milliseconds by default, but you can provide a different timeout by invoking the second overload of DisplayToastAsync, whose second argument is the new timeout expressed in milliseconds. The previous code produces the result shown in Figure 16.

Figure 16: Displaying a toast notification
As you can see, the toast notification does not allow for performing an additional action, which a snackbar does. You can display snackbars by invoking the DisplaySnackBarAsync method, which optionally takes an argument of type SnackBarOptions. In its simplest form, you pass the string you want to display and an action, as demonstrated in the DisplaySnackBarClicked button event handler.
var result = await this.DisplaySnackBarAsync(GenerateLongText(5),
"Run action", () =>
{
Debug.WriteLine("SnackBar action button clicked");
return Task.CompletedTask;
});
The method provides several overloads; the one considered here shows the string passed as the first argument and allows for executing the Func<Task> action object passed as the second argument. Figure 17 shows what this looks like.

Figure 17: Displaying a snackbar
Snackbars can be customized through an instance of the SnackBarOptions object. If you look at the C# code for the DisplaySnackBarAdvancedClicked button event handler, it is easier to understand how to create advanced snackbars. In the first part, the code customizes the way the text message is displayed.
const string SmileIcon = "\uf118";
var options = new SnackBarOptions
{
MessageOptions = new MessageOptions
{
Foreground = Color.DeepSkyBlue,
Font = Font.OfSize("FARegular", 40),
Padding = new Thickness(10, 20, 30, 40),
Message = SmileIcon
},
The SnackBarOptions has a MessageOptions property, of type MessageOptions, which allows for formatting the text message with the self-explanatory properties you see in the code. Other options that can be customized are set via the following properties.
Duration = TimeSpan.FromMilliseconds(5000),
BackgroundColor = Color.Coral,
IsRtl = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft,
Notice how easy it is to set the text options with a right-to-left presentation. The duration is expressed in milliseconds, after which the snackbar will be automatically dismissed. The last property is about actions that can be executed from within the snackbar. It is possible to supply multiple actions, as demonstrated in the following code, which assigns the Actions property with an object of type List<SnackBarActionOptions>.
Actions = new List<SnackBarActionOptions>
{
new SnackBarActionOptions
{
ForegroundColor = Color.Red,
BackgroundColor = Color.Green,
Font = Font.OfSize("Times New Roman", 15),
Padding = new Thickness(10, 20, 30, 40),
Text = "Action1",
Action = () =>
{
Debug.WriteLine("1");
return Task.CompletedTask;
}
},
new SnackBarActionOptions
{
ForegroundColor = Color.Green,
BackgroundColor = Color.Red,
Font = Font.OfSize("Times New Roman", 20),
Padding = new Thickness(40, 30, 20, 10),
Text = "Action2",
Action = () =>
{
Debug.WriteLine("2");
return Task.CompletedTask;
}
}
}
};
You can customize the appearance of each individual action by assigning the ForegroundColor, BackgroundColor, Font, Padding, and Text properties. The action executed is an object of type Func<Task>. The way the method is invoked is the following.
var result = await this.DisplaySnackBarAsync(options);
Tip: Snackbars and toast notifications can be anchored to a specific view because both the DisplayToastAsync and DisplaySnackBarAsync methods extend the VisualElement class, so you can invoke such methods on every view. The sample app has examples about this scenario, in particular the “Show Snackbar with Anchor” example.
The Xamarin Community Toolkit exposes the Popup view, which allows for rendering native pop-ups on each supported platform. Pop-ups can also be customized in several ways. The sample project provides many examples, located under the Pages\Views\Popups folder.
Note: The sample project provides many examples on pop-ups, but most of them are built by adding property assignments or views to the pop-up content. For this reason, I will start discussing pop-ups from the simplest examples possible, explaining only the most relevant features.
The best thing to do is to start from the simplest pop-up, and then walk through customization possibilities. The Simple Popup example looks like Figure 18.

Figure 18: Displaying a simple pop-up
The content of a pop-up is generally a layout, so that you can create a complex visual hierarchy with a title, text, and other views. Code Listing 3 shows the XAML markup for the simple pop-up shown in Figure 18.
Code Listing 3
<?xml version="1.0" encoding="utf-8" ?> <xct:Popup xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:xct="http://xamarin.com/schemas/2020/toolkit" xmlns:local="clr-namespace:Xamarin.CommunityToolkit.Sample. Pages.Views.Popups" Size="{x:Static local:PopupSize.Small}" x:Class="Xamarin.CommunityToolkit.Sample.Pages. Views.Popups.SimplePopup"> <xct:Popup.Resources> <ResourceDictionary> <Style x:Key="Title" TargetType="Label"> <Setter Property="FontSize" Value="26" /> <Setter Property="FontAttributes" Value="Bold" /> <Setter Property="TextColor" Value="#000" /> <Setter Property="VerticalTextAlignment" Value="Center" /> <Setter Property="HorizontalTextAlignment" Value="Center" /> </Style> <Style x:Key="Divider" TargetType="BoxView"> <Setter Property="HeightRequest" Value="1" /> <Setter Property="Margin" Value="50, 25" /> <Setter Property="Color" Value="#c3c3c3" /> </Style> <Style x:Key="Content" TargetType="Label"> <Setter Property="HorizontalTextAlignment" Value="Start" /> <Setter Property="VerticalTextAlignment" Value="Center" /> </Style> <Style x:Key="PopupLayout" TargetType="StackLayout"> <Setter Property="Padding" Value="{OnPlatform Android=20, UWP=20, iOS=5}" /> </Style> </ResourceDictionary> </xct:Popup.Resources> <StackLayout Style="{StaticResource PopupLayout}"> <Label Style="{StaticResource Title}" Text="Simple Popup" /> <BoxView Style="{StaticResource Divider}" /> <Label Style="{StaticResource Content}" Text="This is a native popup with a Xamarin.Forms View being rendered. The behaviors of the popup will confirm to 100% native look and feel, but still allows you to use your Xamarin.Forms controls." /> </StackLayout> </xct:Popup> |
A pop-up is declared inside an individual XAML file and is exposed via the Popup class. You can control the pop-up size with the Size property, of type Xamarin.Forms.Size. In Code Listing 3, you can see that such a property is bound to an enumeration called PopupSize, which is not part of the library, rather it is part of the sample code, so you can walk through it as an exercise.
The StackLayout actually represents the content of the pop-up, which means you can show whatever you need. The styles defined in the Popup.Resources are applied to the child views, and the result you get is shown in Figure 18. In order to display pop-ups, you need to invoke a new extension method called ShowPopupAsync, which extends the Navigation class and takes the pop-up instance as an argument. The usage of this method is demonstrated in the PopupControlViewModel.cs file, located under ViewModels\Views, and works like this:
await Navigation.ShowPopupAsync(popup);
Optionally, ShowPopupAsync can return a result if the pop-up is enabled to do so. If you look at the ReturnResultPopup.xaml file, you will see the following assignment in the pop-up declaration.
x:TypeArguments="x:String"
With this assignment, the method will be able to return an object of type string, but you can choose a different type to return. Whatever return type you decide on, the syntax for the method invocation becomes the following.
var result = await Navigation.ShowPopupAsync(popup);
By default, pop-ups can be dismissed by tapping outside of them (behavior known as light dismiss), but sometimes you want to avoid this to make sure users tap on a button and perform a mandatory action. In this case, you can set the IsLightDismissEnabled property as follows.
IsLightDismissEnabled="False"
You can implement actions inside pop-ups. This can be quickly accomplished by adding Button views to the content of the pop-up. Two examples, called Popup with 1 Button and Popup with Multiple Buttons, demonstrate this. The following XAML from the second example shows how to implement multiple buttons.
<StackLayout Style="{StaticResource PopupLayout}">
<Label Style="{StaticResource Title}"
Text="Button Popup" />
<BoxView Style="{StaticResource Divider}" />
<Label Style="{StaticResource Content}"
Text="This is a native popup with a Xamarin.Forms View being rendered. The behaviors of the popup will confirm to 100% native look and feel, but still allows you to use your Xamarin.Forms controls." />
<StackLayout Style="{StaticResource ButtonGroup}">
<Button Text="Cancel"
Style="{StaticResource CancelButton}"
Clicked="Cancel_Clicked" />
<Button Text="OKAY"
Clicked="Okay_Clicked" />
</StackLayout>
</StackLayout>
You can simply handle the Clicked event or bind buttons to commands to execute actions. Figure 19 shows how the pop-up with buttons from the sample project appears.

Figure 19: Implementing actions inside pop-ups
You can also arrange the position of pop-ups by simply assigning the HorizontalOptions and VerticalOptions properties, both of type LayoutOptions. This allows you to place pop-ups in a position that is different from the center of the screen (the default). In the PopupControlViewModel.cs file, you can find several examples. For instance, the following snippet shows how to display a pop-up at the top-right corner.
popup.VerticalOptions = new LayoutOptions(LayoutAlignment.Start, true);
popup.HorizontalOptions = new LayoutOptions(LayoutAlignment.End, true);
The resulting pop-up appears like in Figure 20.

Figure 20: Selecting the pop-up position on screen
In summary, native pop-ups can now be displayed very quickly and without the need for building custom views. In addition, customization options are very easy to implement since most of the customizations are applied via property assignments, or by adding views to the pop-up content.
The Xamarin Community Toolkit makes it easy to organize the user interface within tabs via the TabView control. This control provides deep customization options and offers shortcuts to implement layouts that satisfy the most modern mobile design very quickly.
Due to the high number of possibilities and customization options, the official sample project includes several pages to demonstrate the usage of the TabView, located under the Pages\Views\TabView folder. I will consider the examples that highlight the most relevant properties and characteristics of the view, starting from the simplest example called Getting Started that is coded in the GettingStartedPage.xaml file. In the sample app running, this example looks like the one shown in Figure 21.

Figure 21: Simple layout with tabs
As you can see, a tab strip contains two tab definitions, each with its own text and icon. Colors can be defined in code. The opening tag for the TabView is the following.
<xct:TabView
TabStripPlacement="Bottom"
TabStripBackgroundColor="Blue"
TabStripHeight="60"
TabIndicatorColor="Yellow"
TabContentBackgroundColor="Yellow">
The TabStripPlacement property allows you to set the position of the tab strip, and its value can be Bottom or Top. The TabStripBackgroundColor property, of type Color, allows you to specify a background color for the tab strip, whereas the TabStripHeight allows you to specify the tab strip height.
The TabIndicatorColor property, of type Color, is assigned with the color you want to use to highlight the currently selected tab, whereas the TabContentBackgroundColor property allows for specifying the background color of the tab content, which is something you can easily understand by selecting the second tab in the sample page.
The TabView works as a container for TabViewItem objects, each representing a tab. For example, the first tab in the sample page is defined as follows.
<xct:TabViewItem
Icon="triangle.png" Text="Tab 1" TextColor="White"
TextColorSelected="Yellow" FontSize="12">
<Grid BackgroundColor="Gray">
<Label HorizontalOptions="Center" VerticalOptions="Center"
Text="TabContent1" />
</Grid>
</xct:TabViewItem>
These are the relevant points:
The visibility of the tab strip can be managed via the IsTabStripVisible property. You can use this property to hide and show the tab strip at runtime based on your conditions. There is basically no limit to the number of TabViewItem objects you can add, because the TabView has built-in support for scrolling. If you open the Scrollable Tabs example, you can see nine tabs by scrolling the tab strip horizontally without specifying any additional property.
An interesting feature of tabs is that they support badges. This is demonstrated in the Tab Badge example (TabBadgePage.xaml file), as you can see in Figure 22.

Figure 22: Display badges on tabs
Creating badges is very easy. Consider the following code snippet, related to the second tab on the strip.
<xct:TabViewItem
Icon="circle.png"
IconSelected="square"
Text="Tab 2"
TextColor="White"
TextColorSelected="Yellow"
BadgeText="NEW"
BadgeBackgroundColor="DarkOrange"
BadgeBackgroundColorSelected="Red"
BadgeBorderColor="Green"
BadgeBorderColorSelected="LightGreen"
BadgeTextColor="White"
FontSize="10"
FontAttributesSelected="12">
Names of the properties related to badges start with the Badge literal and are self-explanatory. The BadgeText property can be used to add text to the badge. The BadgeBackgroundColor and BadgeBackgroundColorSelected properties, both of type Color, respectively allow for setting the background color for the badge when the tab is not selected and when it is selected.
Similarly, you can set colors for the badge border via the BadgeBorderColor and BadgeBorderColorSelected properties. Finally, you can specify the color for the text in the badge via the BadgeTextColor property. In this example, some changes are also applied to the default font of the text in the TabView.
The font can be controlled via the following properties:
Before going into customizing tabs, it can be useful to summarize a few more properties:
Both the TabView and TabViewItem objects can be completely customized. The sample app has an example called Customizing Tabs, whose result is shown in Figure 23.

Figure 23: Customizing tabs
As you can see, the tab strip has a completely different look with rounded corners, and the center tab item has a completely different appearance. Let’s look into this by analyzing small pieces of code. The TabView definition is using a BoxView with rounded corners as the background.
<xct:TabView
Style="{StaticResource CustomTabStyle}">
<xct:TabView.TabStripBackgroundView>
<BoxView
Color="#484848"
CornerRadius="36, 36, 0, 0"/>
</xct:TabView.TabStripBackgroundView>
This means that the background for the tab strip can not only be a color, but also a view to be set via the TabStripBackgroundView property. The style applied to the TabView is very simple.
<Style
x:Key="CustomTabStyle" TargetType="xct:TabView">
<Setter
Property="IsTabTransitionEnabled" Value="True" />
<Setter
Property="TabStripHeight" Value="48" />
<Setter
Property="TabContentBackgroundColor" Value="#484848" />
<Setter
Property="TabStripPlacement" Value="Bottom" />
</Style>
All three TabViewItem objects redefine their base layout by assigning the ControlTemplate property with objects of type ControlTemplate, defined in the same page. While for the first and third tab, the control templates are quite easy to understand, the control template for the second tab is more complex (and interesting), so I will focus on this, which is defined as follows.
<xct:TabViewItem Text="Tab 2" Icon="circle.png"
ControlTemplate="{StaticResource FabTabItemTemplate}"
Style="{StaticResource TabItemStyle}"
TabTapped="OnFabTabTapped" />
The first thing to notice is that TabViewItem objects support interaction via the TabTapped event. The sample project displays a simple alert on tap.
void OnFabTabTapped(object? sender, TabTappedEventArgs e) =>
DisplayAlert("FabTabGallery", "Tab Tapped.", "Ok");
The TabTappedEventArgs object exposes the Position property (0-based), of type int, which allows you to understand the position of the tapped tab inside the strip. The redefined control template for the current tab is shown in Code Listing 4.
Code Listing 4
<ControlTemplate x:Key="FabTabItemTemplate"> <Grid> <ImageButton InputTransparent="True" Source="{TemplateBinding CurrentIcon}" Padding="10" HorizontalOptions="Center" BackgroundColor="#FF0000" HeightRequest="60" WidthRequest="60" Margin="6"> <ImageButton.CornerRadius> <OnPlatform x:TypeArguments="x:Int32"> <On Platform="iOS" Value="30"/> <On Platform="Android" Value="60"/> <On Platform="UWP" Value="36"/> </OnPlatform> </ImageButton.CornerRadius> <ImageButton.IsVisible> <OnPlatform x:TypeArguments="x:Boolean"> <On Platform="Android, iOS, UWP">True</On> <On Platform="macOS">False</On> </OnPlatform> </ImageButton.IsVisible> </ImageButton> <BoxView InputTransparent="True" HorizontalOptions="Center" CornerRadius="30" BackgroundColor="#FF0000" HeightRequest="60" WidthRequest="60" Margin="6"> <BoxView.IsVisible> <OnPlatform x:TypeArguments="x:Boolean"> <On Platform="Android, iOS, UWP">False</On> <On Platform="macOS">True</On> </OnPlatform> </BoxView.IsVisible> </BoxView> </Grid> </ControlTemplate> |
At the core of the template there is an ImageButton view, which is the main view in the default template. Notice how the Source property assigns the default icon via the TemplateBinding extension. All the other properties are related to the position, colors, and size. For the corner radius and for its visibility, the code makes different decisions depending on the platform the app is running on. A BoxView is used to display the red circle in the template. If you now look back at Figure 23, it should be clearer how powerful customization options are, especially if you have knowledge of how control templates work in Xamarin.Forms (and more generally, in development platforms based on XAML).
Note: You have learned all the most important things about implementing and customizing tabs and the tab strip. It will now be easier to look at the remaining sample pages, which leverage the same concepts.
Accessibility is a feature offered by the operating systems, and on most devices, and makes it possible for visually impaired people to use a phone, tablet, and PC more easily because the device will literally speak, describing the content of each individual visual element in the system UI or inside an app.
Xamarin.Forms has support for accessibility, but the Xamarin Community Toolkit goes a step further by providing the SemanticOrderView control and the SemanticEffect effect. These are both discussed here because they belong to the same area. In the sample project, the SemanticOrderView is represented in the Pages\Views\SemanticOrderViewPage.xaml file.
Tip: You will need to turn on accessibility on your device; otherwise, you will not be able to hear the text-to-speech engine working in the sample app.
It is declared as follows.
<xct:SemanticOrderView x:Name="acv">
<StackLayout>
<Label x:Name="second" Text="Second" Margin="0,20" />
<Button x:Name="third" Text="Third" Margin="0,20" />
<Label x:Name="fourth" Text="Fourth" Margin="0,20" />
<Button x:Name="fifth" Text="Fifth and last" Margin="0,20" />
<Button x:Name="first" Text="First" Margin="0,20" />
</StackLayout>
</xct:SemanticOrderView>
It basically simplifies the way the user can understand the order of visual elements in a list. The SemanticEffect object makes some steps forward, helping users to identify the type of content in the user interface. If you look into the Pages\Effects\SemanticEffectPage.xaml file, you will see several code snippets of interest. First, a series of Label views declared as follows.
<Label Text="I have no heading" xct:SemanticEffect.HeadingLevel="None"/>
<Label Text="I am a heading 1" xct:SemanticEffect.HeadingLevel="Level1"/>
<Label Text="I am a heading 2" xct:SemanticEffect.HeadingLevel="Level2"/>
<Label Text="I am a heading 3" xct:SemanticEffect.HeadingLevel="Level3"/>
<Label Text="I am a heading 4" xct:SemanticEffect.HeadingLevel="Level4"/>
<Label Text="I am a heading 5" xct:SemanticEffect.HeadingLevel="Level5"/>
<Label Text="I am a heading 6" xct:SemanticEffect.HeadingLevel="Level6"/>
<Label Text="I am a heading 7" xct:SemanticEffect.HeadingLevel="Level7"/>
<Label Text="I am a heading 8" xct:SemanticEffect.HeadingLevel="Level8"/>
<Label Text="I am a heading 9" xct:SemanticEffect.HeadingLevel="Level9"/>
The HeadingLevel property of the SemanticEffect allows for specifying the heading level of a string inside a text hierarchy. This property is of type HeadingLevel, an enumeration that supports up to nine heading levels. Another property of the effect is Description and it works like in the following Label.
<Label Text="I am a label with an automation ID"
AutomationId="labelAutomationIdTest"
xct:SemanticEffect.Description="This is a semantic description" />
When this property is assigned, the device will speak, saying the value of the description. The last property of the effect is Hint.
<Button
Text="Button with hint"
xct:SemanticEffect.Hint="This is a hint that describes the button. For example, 'sends a message'"/>
The Hint property contains a suggestion or explanation on what a view does. Figure 24 shows what the sample page looks like, but it obviously cannot represent the spoken phrases.

Figure 24: Improving accessibility with the SemanticEffect
Microsoft has also published a video about using these new elements, where they are properly demonstrated with live actions and audio, so I recommend you watch it for a better understanding.
Modern mobile designs often include views that are not part of the Xamarin.Forms codebase, but that are now becoming of common use. The Xamarin Community Toolkit bridges this gap by providing several views of common use, so that developers do not need to use third-party controls or develop such views on their own, thus saving time, eliminating external code dependencies, and improving productivity.
However, new views are only a part of modern designs. In fact, these also depend on device features and screen form factors. The next chapter describes how the Xamarin Community Toolkit also simplifies the way you can manage the user interface, especially on specific (and popular) devices.