Chapter 5. Customizing the User Interface

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:

  • Creating a custom DataTemplate class which utilizes native platform capabilities, that come as part of the iOS and Android platforms
  • Working with custom renderers to change the appearance of control elements
  • Using the platform Effects API to change the appearance of control elements
  • Working with Boolean and string to image value converters
  • Updating the walks content page application to use the data template
  • Updating the WalkEntry content page to use the CustomRenderer
  • Updating the DistanceTravelled content page to use the Effects API

Creating the DataTemplate class for the TrackMyWalks app

One 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:

  1. Launch the Xamarin Studio application, and ensure that the TrackMyWalks solution is loaded within the Xamarin Studio IDE.
  2. Next, create a new folder, within the TrackMyWalks Portable Class Library project, called Data Templates as shown in the following screenshot:

    Creating the DataTemplate class for the TrackMyWalks app

  3. Next, create an empty class within the 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.
  4. Then, choose the Empty Class option located within the General section, and enter WalkCellDataTemplate as the name of the new class file, as shown in the following screenshot:

    Creating the DataTemplate class for the TrackMyWalks app

  5. Next, click on the New button to allow the wizard to create the new empty class file, as shown in the preceding screenshot.
  6. Our next step is to begin creating and implementing the code for our WalkCellDataTemplate class; perform the following steps.
  7. Ensure that the 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.

Note

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.

Updating the walks main page to use the data template

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:

  1. Ensure that the 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.

Updating the walks main page to use the data template

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.38.121