In our previous chapter, we looked at how we can incorporate platform-specific features within the TrackMyWalks
app, which is dependent on the mobile platform. You learned how to create a C# class, which acted as a location service that included a number of class methods for both iOS and Android platforms.
We also covered how to properly perform location updates whether the application's state is in the foreground or background by registering the app as a background-necessary application.
In this chapter, you'll learn how to work with the DataTemplateCustomRenderer
by creating a C# class to lay out your views beautifully within your applications, and you will also get accustomed to working with platform-specific APIs to extend the default behavior of Xamarin.Forms' controls through the use of custom renderers, by creating a custom picker.
We will also be covering how to use the Xamarin.Forms Effects
API to customize the appearance and styling of native control elements for each platform, by implementing a CustomRenderer
class. We'll look at how to manipulate the visual appearance of data that is bound, through the use of value and image converters.
This chapter will cover the following points:
DataTemplate
class which utilizes native platform capabilities, that come as part of the iOS and Android platformsEffects
API to change the appearance of control elementsWalkEntry
content page to use the CustomRenderer
DistanceTravelled
content page to use the Effects
APIOne of the features of the Xamarin.Forms
toolkit is the ability to manipulate the user interface by leveraging the various platform-specific APIs that are available, whether it be manipulating the appearance of controls and their elements using custom renderers, or changing the appearance and styling of native control elements.
In this section, we will be working with the Xamarin.Forms
data templates, which will provide the ability to define the presentation of data. Let's begin by creating a new folder called Data Templates
, within our TrackMyWalks
solution, which will be used to represent our Data Templates
, by following these steps:
TrackMyWalks
solution is loaded within the Xamarin Studio IDE.TrackMyWalks
Portable Class Library project, called Data Templates
as shown in the following screenshot:
Data Templates
folder. If you can't remember how to do this, you can refer to the section entitled Creating the Navigation Service Interface for the TrackMyWalks app, within
Chapter 3
, Navigating within the MVVM model - The Xamarin.Forms Way.WalkCellDataTemplate
as the name of the new class file, as shown in the following screenshot:
WalkCellDataTemplate
class; perform the following steps.WalkCellDataTemplate.cs
file is displayed within the code editor, and enter the following code snippet:// // WalkCellDataTemplate.cs // TrackMyWalks DataTemplate for Cells // // Created by Steven F. Daniel on 01/10/2016. // Copyright © 2016 GENIESOFT STUDIOS. All rights reserved. // using TrackMyWalks.Converters; using Xamarin.Forms; namespace TrackMyWalks.Controls { public class WalkCellDataTemplate : ViewCell { public WalkCellDataTemplate() { var walkTrailImage = new Image { WidthRequest = 140, HeightRequest = 140, HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand, Aspect = Aspect.Fill }; walkTrailImage.SetBinding(Image.SourceProperty, "ImageUrl"); var TrailNameLabel = new Label() { FontAttributes = FontAttributes.Bold, FontSize = 16, TextColor = Color.Black }; TrailNameLabel.SetBinding(Label.TextProperty, "Title"); var totalKilometersLabel = new Label() { FontAttributes = FontAttributes.Bold, FontSize = 12, TextColor = Color.FromHex("#666") }; totalKilometersLabel.SetBinding(Label.TextProperty, "Kilometers", stringFormat: "Kilometers: {0}"); var trailDifficultyLabel = new Label() { FontAttributes = FontAttributes.Bold, FontSize = 12, TextColor = Color.Black }; trailDifficultyLabel.SetBinding(Label.TextProperty, "Difficulty", stringFormat: "Difficulty: {0}"); var trailDifficultyImage = new Image { HeightRequest = 50, WidthRequest = 50, Aspect = Aspect.AspectFill, HorizontalOptions = LayoutOptions.Start }; trailDifficultyImage.SetBinding(Image.SourceProperty, "Difficulty", converter: new TrailImageConverter()); var notesLabel = new Label() { FontSize = 12, TextColor = Color.Black }; notesLabel.SetBinding(Label.TextProperty, "Notes"); var notesStack = new StackLayout() { Spacing = 3, Orientation = StackOrientation.Vertical, VerticalOptions = LayoutOptions.FillAndExpand, Children = { notesLabel } }; var statusLayout = new StackLayout { Orientation = StackOrientation.Vertical, Children = { totalKilometersLabel, trailDifficultyLabel, trailDifficultyImage } }; var DetailsLayout = new StackLayout { Padding = new Thickness(10, 0, 0, 0), Spacing = 0, HorizontalOptions = LayoutOptions.FillAndExpand, Children = { TrailNameLabel, statusLayout, notesStack } }; var cellLayout = new StackLayout { Spacing = 0, Padding = new Thickness(10, 5, 10, 5), Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.FillAndExpand, Children = { walkTrailImage, DetailsLayout } }; this.View = cellLayout; } } }
In the preceding code snippet, we began by ensuring that our class inherits from the Xamarin.FormsViewCell
class renderer, and is essentially a cell that can be added to any ListView
or TableView
control that contains a defined view. When working with Xamarin.Forms
, and the ViewCell
class, every cell has an accompanying renderer that is associated with each platform that creates an instance of a native control. Whenever a ViewCell
class is rendered under the iOS platform, the ViewCellRenderer
class will instantiate the native UITableViewCell
control. Alternatively, under the Android platform, the ViewCellRenderer
class instantiates a native View
control.
Finally, on the Windows Phone platform, the ViewCellRenderer
class instantiates a native DataTemplate
control. Next, we create the cell layout information using the StackLayout
control, and then use the SetBinding
property to create and bind each of our model values to a specific property. Finally, we define a cellLayout
variable that uses the StackLayout
control, to add each of our child elements and then assign the resulting cellLayout
to the class View
.
If you are interested in finding out more information about DataTemplates
, please refer to the Xamarin developer documentation located at
https://developer.xamarin.com/guides/xamarin-forms/templates/data-templates/.
Now that we have created our WalkCellDataTemplate
, the next step is to modify the walks main page so that it can make use of this class.
In the previous section, we created the class for our WalkCellDataTemplate
, as well as defining the layout information for each of the control elements that we would like to have displayed within our View
.
In this section, we will take a look at how to implement the necessary code changes so that the WalksPageContentPage
can take advantage of our WalkCellDataTemplate
class.
Let's take a look at how we can achieve this, by following the steps:
WalksPage.cs
file is displayed within the code editor, and enter in the following highlighted code sections as shown in the following code snippet:// // WalksPage.cs // TrackMyWalks // // Created by Steven F. Daniel on 04/08/2016. // Copyright © 2016 GENIESOFT STUDIOS. All rights reserved. // using Xamarin.Forms; using TrackMyWalks.Models; using TrackMyWalks.ViewModels; using TrackMyWalks.Services; using TrackMyWalks.DataTemplates; namespace TrackMyWalks { public class WalksPage : ContentPage { WalksPageViewModel _viewModel { get { return BindingContext as WalksPageViewModel; } } public WalksPage() { var newWalkItem = new ToolbarItem { Text = "Add Walk" }; ... ... ... // Define our Data Template Class var walksList = new ListView { HasUnevenRows = true, ItemTemplate = new DataTemplate(typeof( WalkCellDataTemplate)), SeparatorColor = (Device.OS == TargetPlatform.iOS) ? Color.Default : Color.Black }; ... ... ... } }
In the preceding code snippet, we began by including a reference to our DataTemplates
class, via the using
statement. Then we passed in the WalkCellDataTemplate
data template to the DataTemplate
class object, which will be assigned to the ItemTemplate
property of the ListView
class. Next, depending on the operating system we are running on, we'll set the separator color for our TableView
.
As you can see from the preceding screenshot, this will show you a list of our current walks trail entries, which are nicely rendered using the DataTemplate
, and displayed within the ListView
control.
In our next section, you will see how we can go about creating a custom picker for our WalkEntry
content page, so that we can display a list of difficulty choices for the user to choose from.
3.141.38.121