Contact us page – Part 4a

Contact us page – Part 4a

All code can be found in my Github repository.

In this post, ill make a simple contact us page that will be rendered on both platforms iOS and Android. In this page we will have two sections, the first section will be social media icons that are tappable to get redirected and the second section is a contact us form to be filled out and sent via email.
Note: we will handle the UI part only for the contact us form, we won’t cover the backend handling for now.

Building UI using XAML

In the Pages folder, add a new Forms content page Xaml and name it ContactUsPage, then you may write down the following XAML to draw a cross-platform contact us page.

<?xml version=1.0 encoding=UTF-8?>
<ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=PuzzlersJordan.ContactUsPage Title=Contact us>
    <ContentPage.Content>
        <ScrollView>
            <StackLayout Orientation=Vertical Padding=20 Spacing=10>
                <!–Social Media section–>
                <StackLayout Orientation=Horizontal HorizontalOptions=CenterAndExpand Spacing=10>
                    <Button BorderRadius=25 HeightRequest=50 WidthRequest=50 BackgroundColor=#3b5998 Clicked=facebook_clicked Image=Facebook_icon>
                    </Button>
                    <Button BorderRadius=25 HeightRequest=50 WidthRequest=50 BackgroundColor=#1da1f2 Clicked=twitter_clicked Image=Twitter_icon>
                    </Button>
                    <Button BorderRadius=25 HeightRequest=50 WidthRequest=50 BackgroundColor=#cd201f Clicked=youtube_clicked Image=Youtube_icon>
                    </Button>
                    <Button BorderRadius=25 HeightRequest=50 WidthRequest=50 BackgroundColor=Gray Clicked=phone_clicked Image=Phone_icon>
                    </Button>
                </StackLayout>
                <StackLayout Orientation=Horizontal HorizontalOptions=CenterAndExpand >
                    <BoxView HeightRequest=0.5 VerticalOptions=CenterAndExpand HorizontalOptions=FillAndExpand BackgroundColor=Black />
                    <Label Text=Or>
                    </Label>
                    <BoxView HeightRequest=0.5 VerticalOptions=CenterAndExpand HorizontalOptions=FillAndExpand BackgroundColor=Black />
                </StackLayout>
                <!–Contact us section–>
                <Label Text=Name x:Name=NameLabel >
                </Label>
                <Entry Placeholder=John Smith>
                </Entry>
                <Label Text=Email>
                </Label>
                <Entry Placeholder=email@domain.com Keyboard=Email>
                </Entry>
                <Label Text=Phone>
                </Label>
                <Entry Placeholder=(123) 456-7890 Keyboard=Telephone>
                </Entry>
                <Label Text=Message>
                </Label>
                <Editor HeightRequest=90>
                </Editor>
                <Button HorizontalOptions=FillAndExpand Text=Send>
                </Button>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

From the above code, I’ll talk about each section separately.

Section 1: Social media icons

In order to make sure all contents fit on the page, we shall add them inside a scroll view.
So the first section will reside in a stack layout, oriented in a horizontal way so icons can look in a row starting from the centre.
To make them tappable we have added them as buttons with an image property assigned to each one.
Note: adding images is already covered in this link.

Adding more properties like BorderRadius will add a sense of user of experience to our UI that will make them look better as shown below:

Note: in case you’re wondering why icons on Android don’t have rounded corners check this StackOverflow link.
Quick tip, each button has its own handler from code behind as shown below:

        public void facebook_clicked(object sender, EventArgs e)
        {
            Device.OpenUri(new Uri(Constants.FacebookUrl));
        }
        public void youtube_clicked(object sender, EventArgs e)
        {
            Device.OpenUri(new Uri(Constants.YoutubeUrl));
        }
        public void twitter_clicked(object sender, EventArgs e)
        {
            Device.OpenUri(new Uri(Constants.TwitterUrl));
        }
        public void phone_clicked(object sender, EventArgs e)
        {
            Device.OpenUri(new Uri(tel:+962799892728));
        }

Section 2: Contact Us form

Another Stack layout but this time we leave defaulted it to a vertical orientation which will contain a list of controls of kind Label, Entry, Button and Editor.
Each of these controls has its own properties and it looks like this:

Now, notice that the editor in the iOS platform doesn’t look like a real native iOS editor (Maybe because it doesn’t have borders nor rounded corners).
In the next part ill talk about how to fix this issue using Customer Renderers.

Applying borders to the Editor control on iOS – Part 4b

Applying borders to the Editor control on iOS – Part 4b

 

All code can be found in my Github repository.

The Problem:

When using Xamarin Forms editor on iOS, people tend to not notice the control itself as it has the same background color as the content view itself with no borders. In other words, it’s invisible!
Screen Shot 2017-10-15 at 2.25.30 PMHow can we solve this problem?

The Solution:

In order to fix this issue, we need to create a new custom control by subclassing Editor control in Xamarin Forms project (PCL) Why? because we need to keep the regular Xamarin Forms editor without manipulation in case we wanted to use it later on (I doubt 😅) and then create a new custom renderer for this control on iOS platform only.

  1. In the Xamarin Forms PCL project add a new folder call it CustomControls, then add a new empty class call it MyEditor.

        public class MyEditorEditor
        {
            public MyEditor()
            {
            }
        }

  2. Add a new folder in the iOS project call it CustomRenderers then and a new class file call it MyEditorRenderer to intercept the element (Xamarin Forms control) rendering process to control (iOS control). Then override the OnElementChanged method that renders the native control and writes logic to customize the control.

        public class MyEditorRendererEditorRenderer
        {
            protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Editor> e)
            {
                base.OnElementChanged(e);
                if (Control != null)
                {
                    Control.Layer.CornerRadius = 4;
                    Control.Layer.BorderColor = Color.LightGray.ToCGColor();
                    Control.Layer.BorderWidth = 1;
                }
            }
        }

  3. Add an ExportRenderer attribute to the custom renderer class to specify that it will be used to render the Xamarin.Forms control. This attribute is used to register the custom renderer with Xamarin.Forms.

    [assembly: ExportRenderer(typeof(MyEditor), typeof(MyEditorRenderer))]
    namespace PuzzlersJordan.iOS.CustomRenderers

  4. To consume this, it can be referenced in contact us XAML in the PCL project by declaring a namespace for its location and using the namespace prefix on the control element as follows:

    <ContentPage … xmlns:local=clr-namespace:PuzzlersJordan.CustomControls;assembly=PuzzlersJordan …>

    <local:MyEditor HeightRequest=90>
    </local:MyEditor>

    Note: The local namespace prefix can be anything. However, the namespace and assembly values must match the details of the custom control. Once the namespace is declared, the prefix is used to reference the custom control

Voila, there you are!

Screen Shot 2017-10-15 at 8.15.22 PM

 

Consuming authenticated APIs with Xamarin.Forms

Consuming authenticated APIs with Xamarin.Forms

In this post, I’m going to build a fully functional cross-platform mobile application that consumes an authenticated Web APIs (OAuth authentication).
It’s a personalised To-Do application that you need to enter your phone number then enter the verification code after receiving it via SMS to enter your To-Do list.

All code can be found in my Github repository.

Step 1: Create a new Project

Using your favourite IDE (I’m using Visual Studio for Mac), Create a new solution and in the Multiplatform section choose Blank Forms App and go through the wizard to choose your preferred project directory and targeted platforms. If you need to get familiar on what to fill out in the wizard you can check my previous post
Note: It’s preferred to name the project ToDo just so we can have the same namespace in case you would like to copy paste.😋

Step 2: Consume Authentication API endpoints

  1. I’m going to start with organising the project with folders, so I’ll start with a folder named Interfaces and add a new interface called IAuthenticationService

    using System;
    using System.Net;
    using System.Threading.Tasks;

    namespace ToDo.Interfaces
    {
        public interface IAuthenticationService
        {
            Task Register(string phoneNumber);

            Task<HttpStatusCode> AuthorizeUser(string phoneNumber, string verificationCode);
        }
    }

    As shown from the code above, am listing all the required methods that we’re going to implement later on. They’re two methods Register phone number and Authorize User.
    The first one is to tackle our Web API Registration endpoint to send SMS for the registered phone number with the verification code.
    As for the second one, it will take the phone number and the received verification code to send back the Access token to the consumer so it can be saved in a secure place and later on to be passed with any requests.

  2. Now to start working on the implementation, we will create a new folder named Services and then a new class called AuthenticationService.

    using System;
    using System.Diagnostics;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Net;
    using ToDo.Interfaces;

    namespace ToDo
    {
        public class AuthenticationService : IAuthenticationService
        {
            HttpClient client;
            readonly Uri baseUri = new Uri(Constants.BaseURL);

            public AuthenticationService()
            {
                client = new HttpClient();
                client.MaxResponseContentBufferSize = 256000;
            }

            public async Task Register(string phoneNumber)
            {
                string purgedPhoneNumber = phoneNumber;

                var uri = new Uri(baseUri, api/account/register);

                try
                {
                    if (phoneNumber.Contains(+)) { purgedPhoneNumber = phoneNumber.Replace(+); }
                    var json = string.Concat({\”username\”, purgedPhoneNumber, });
                    var content = new StringContent(json, Encoding.UTF8, application/json);

                    var response = await client.PostAsync(uri, content);
                    if (response.IsSuccessStatusCode)
                    {
                        Debug.WriteLine(@”successfully sent.);
                    }

                }
                catch (Exception ex)
                {
                    Debug.WriteLine(@”ERROR {0}, ex.Message);
                }
            }

            public async Task<HttpStatusCode> AuthorizeUser(string phoneNumber, string verificationCode)
            {
                string purgedPhoneNumber = phoneNumber;
                var uri = new Uri(baseUri, token);

                if (phoneNumber.Contains(+)) { purgedPhoneNumber = phoneNumber.Replace(+); }
                var postBody = new Dictionary<stringstring>()
                    {
                        {username, purgedPhoneNumber},
                        {password, verificationCode},
                        {grant_typepassword}
                    };

                var content = new FormUrlEncodedContent(postBody);

                var response = await client.PostAsync(uri, content);
                if (response.IsSuccessStatusCode)
                {
                    //var storeService = DependencyService.Get<IUserDetailsStore>();
                    var result = await response.Content.ReadAsStringAsync();
                    var jsonData = (JObject)JsonConvert.DeserializeObject(result);

                    var token = jsonData[access_token].Value<string>();
                    //Token should be saved in key chain instead of singleton class
                    //But for demo purposes, ill put it here
                    AccountDetailsStore.Instance.Token = token;
                    //storeService.SaveCredentials(phoneNumber, token);
                }
                return response.StatusCode;
            }
        }
    }

    As shown from the code above, we started our implementation with a constructor to initialize the Http client also we defined properties (the Http client and base URI that is going to be used throughout the class).

    So to start with the first method Register, firstly we do some purging for the parameterized input to remove the + sign if it exists, and prepare the post body which we send username: (the purged number) and then do the post request by passing the full URI and content.

    As for the second method AuthorizeUser, we do the same purging but we send different post body since we received the verification code and we want to get the access token in return.
    So the post body will be:

            {username, purgedPhoneNumber},
            {password, verificationCode},
            {grant_typepassword}

    Afterwards, when we check if the response is 200 (Ok), we need to save the access token in a safe, encrypted place. Now in our case, I made a singleton class to save the access token just for demo purposes but the ideal case should be done using this approach (This going to be covered in step 4 below).

    Note: These methods are marked as async methods and you need to add Newtonsoft package in order to use any JSON related code on the above sample.

  3. As noticed from the above code, am using a static class called Constants to read any static string from it. For now, I just have BaseURL constant in it.

    using System;
    namespace ToDo
    {
        public static class Constants
        {
            public static string BaseURL = https://bookmarkerapp.azurewebsites.net/;
        }
    }

  4. As for the Singleton class we’ve talked about saving the access token in memory, we will create a new folder called Helpers and a new class called AccountDetailsStore.

    using System;
    namespace ToDo
    {
        public sealed class AccountDetailsStore
        {
            private static readonly AccountDetailsStore instance = new AccountDetailsStore();

            private AccountDetailsStore() { }

            public static AccountDetailsStore Instance
            {
                get
                {
                    return instance;
                }
            }

            public string PhoneNumber { getset; }
            public string Token { getset; }
        }
    }

  5. The last step in this phase is to create the Authentication manager, so we’re going to create a new folder called Repositories and then a new class called AuthenticationRepository to call the methods in the interface (we can call any other implementation since we’re doing Dependency Injection).

    using System;
    using System.Threading.Tasks;
    using ToDo.Interfaces;

    namespace ToDo
    {
        public class AuthenticationRepository
        {
            IAuthenticationService authenticationService;

            public AuthenticationRepository(IAuthenticationService service)
            {
                authenticationService = service;
            }

            public Task RegisterAccount(string phoneNumber)
            {
                return authenticationService.Register(phoneNumber);
            }

            public Task<System.Net.HttpStatusCode> AutherizeAccount(string phoneNumber, string verificationCode)
            {
                return authenticationService.AuthorizeUser(phoneNumber, verificationCode);
            }
        }
    }

Step 3: Create Sign-in & Verification pages

In this step, we’re going to build two pages with code sharing of 100%, Sign-in page and verification page using XAML and C#.
To get started we create a new folder called Pages

  1. Sign-in page:
    Add a new ContentPage XAML by right click on the pages folder Add – New File… and the XAML form should look like below:

    <?xml version=1.0 encoding=UTF-8?>
    <ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=ToDo.SignIn>
        <ContentPage.Content>
            <StackLayout Orientation=Vertical VerticalOptions=CenterAndExpand Padding=20,0,20,0>
                <Label HorizontalOptions=Center HorizontalTextAlignment=Center Text=Select your country and enter your phone number in order to sign in>
                </Label>
                <Picker VerticalOptions=CenterAndExpand SelectedIndexChanged=CountryPicker_SelectedIndexChanged x:Name=countryPicker ItemDisplayBinding={Binding name} Title=Select a country…>
                </Picker>
                <Entry x:Name=phoneNumberEntry Keyboard=Telephone Placeholder=Enter your phone>
                </Entry>
                <Button Text=Sign in x:Name=signInButton>
                </Button>
                <ActivityIndicator x:Name=pageActivityIndicator>
                </ActivityIndicator>
                <Label HorizontalOptions=Center HorizontalTextAlignment=Start Text=You will receive an SMS with verification code.>
                </Label>
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>

    In this XAML, we’re adding a Stack Layout inside Content Page, if you’re familiar with Content page you probably know it only takes single view so we usually insert a container such as Stack layout or scroll view.
    In this Stack layout, I’m adding controls in a vertical order and each control is centralised in the middle. As you can also see that I’ve added some properties for the stack layout like the padding to add some spaces around it.
    Now in stack layout from top to bottom, there is an informative label for the users, a picker to select a country of their phone number (Which I talk more about soon), an entry control where the user can write their phone number, the sign in button, an activity indicator to show that there is a process happening at the moment and finally anther informative label.

    No for the C# code behind:

    using System;
    using System.Collections.Generic;
    using Xamarin.Forms;
    using Newtonsoft.Json;
    using System.IO;
    using System.Reflection;
    using System.Linq;

    namespace ToDo
    {
        public partial class SignIn : ContentPage
        {
            AuthenticationRepository autheticationRepo = new AuthenticationRepository(new AuthenticationService());

            bool isLoading
            {
                set
                {
                    pageActivityIndicator.IsVisible = value;
                    pageActivityIndicator.IsRunning = value;
                    signInButton.IsVisible = !value;
                    this.IsBusy = value;
                }
            }

            public SignIn()
            {
                InitializeComponent();
                Title = Sign in;

                configureCountryPicker();
                configureSignInButton();
                pageActivityIndicator.BindingContext = this;
            }

            private void configureCountryPicker()
            {
                countryPicker.ItemsSource = getCountries();
                countryPicker.SelectedIndexChanged += CountryPicker_SelectedIndexChanged;
            }

            private void configureSignInButton()
            {
                signInButton.Clicked += SignInButton_Clicked;
            }

            private List<Models.CountryCode> getCountries()
            {
                var assembly = typeof(SignIn).GetTypeInfo().Assembly;
                Stream stream = assembly.GetManifestResourceStream(ToDo.Data.Countries.json);

                List<Models.CountryCode> countryCodes;

                using (var reader = new System.IO.StreamReader(stream))
                {
                    var json = reader.ReadToEnd();
                    countryCodes = JsonConvert.DeserializeObject<List<Models.CountryCode>>(json);
                }
                return countryCodes;
            }

            private bool validateForm()
            {
                if (countryPicker.SelectedIndex == –1return false;
                if (string.IsNullOrWhiteSpace(phoneNumberEntry.Text)) return false;
                return true;
            }

            void CountryPicker_SelectedIndexChanged(object sender, EventArgs e)
            {
                if (countryPicker.SelectedIndex == –1) { return; }
                var selectCountry = (Models.CountryCode)countryPicker.SelectedItem;
                phoneNumberEntry.Text = selectCountry.dial_code;
            }

            async void SignInButton_Clicked(object sender, EventArgs e)
            {
                if (!validateForm()) { await DisplayAlert(ValidationPlease fill missing field(s)Ok); return; };
                isLoading = true;
                var phoneNumber = phoneNumberEntry.Text.Trim();
                await autheticationRepo.RegisterAccount(phoneNumber);
                await Navigation.PushAsync(new VerificationPage(phoneNumber));
                isLoading = false;
            }
        }
    }

    This is a partial class SignIn and a child class of ContentPage.
    In the constructor, We’re doing the setup for the page: the title, configuring the country picker, configuring the sign in button and assigning the page activity indicator contexts to self.
    In the configureCountryPicker(), We’re assigning the items data source for this picker by reading a country list JSON file, also in this function, we’re assigning the event method handler when selected index changed.
    As for the configureSignInButton(), we’re also assigning the event method handler when the button is clicked.
    In getCountries() method, we’re reading the JSON file which can be found in here. To add this JSON file, create a new project folder named Data and right click then add files… and choose the JSON downloaded from the above link. Make sure to mark it as embedded resource afterwards.
    It’s important to mention the server call that we do when users click (tap) on the sign in button, we just call the method from the repository AutherizeAccount found in autheticationRepo initialized in the property at the top.
    Then add a new folder and name it Models, to add a POCO class named CountryCode, just to bind it with the results of reading the JSON file.

    using System;
    namespace ToDo.Models
    {
        public class CountryCode
        {
            public string name { getset; }
            public string dial_code { getset; }
            public string code { getset; }
        }
    }

  2. Verification Page:
    This page is where users enter the verification code received via SMS to be redirected to the To-Do list.
    Add a new ContentPage XAML by right click on the pages folder Add – New File… the XAML form should look like below:

    <?xml version=1.0 encoding=UTF-8?>
    <ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=ToDo.VerificationPage>
        <ContentPage.Content>
            <StackLayout Orientation=Vertical VerticalOptions=CenterAndExpand Padding=20,0,20,0>
                <Label Text=Enter verification code>
                </Label>
                <Entry Keyboard=Numeric x:Name=verificationEntry Placeholder=e.g. 1234>
                </Entry>
                <Button x:Name=signInButton Text=Sign in>
                </Button>
                <ActivityIndicator x:Name=pageActivityIndicator>
                </ActivityIndicator>
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>

    This page is simpler than the one we added previously, just a stack layout inside a content page with simple controls to let users add their verification code.
    Note the x:Name is like “id” property in ASP.Net web forms world, we can access this control from the server side because of this property.
    And below is the C# code for this page:

    using System;
    using System.Net;

    using Xamarin.Forms;

    namespace ToDo
    {
        public partial class VerificationPage : ContentPage
        {
            AuthenticationRepository autheticationRepo = new AuthenticationRepository(new AuthenticationService());
            string phoneNumber;

            bool isLoading
            {
                set
                {
                    pageActivityIndicator.IsVisible = value;
                    pageActivityIndicator.IsRunning = value;
                    signInButton.IsVisible = !value;
                    this.IsBusy = value;
                }
            }

            public VerificationPage(string phoneNumber)
            {
                InitializeComponent();

                this.phoneNumber = phoneNumber;
                Title = Verify yourself;
                configureSignInButton();
            }

            private void configureSignInButton()
            {
                signInButton.Clicked += SignInButton_Clicked;
            }

            async void SignInButton_Clicked(object sender, EventArgs e)
            {
                var verificationCode = verificationEntry.Text.Trim();
                isLoading = true;
                var isSuccess = await autheticationRepo.AutherizeAccount(phoneNumber, verificationCode);
                if (isSuccess == HttpStatusCode.OK)
                {
                    await Navigation.PushAsync(new MainPage());
                }
                else
                {
                    await DisplayAlert(Ops…Something went wrong, please try again laterOk);
                }
                isLoading = false;
            }
        }
    }

    The main functionality of this page is to call the AutherizeAccount and retrieve the access token to be coupled with any endpoint request later on (operation endpoints).

  3. This step is just to make sure that you change the main page of the app by changing one line in App.xaml.cs

    MainPage = new NavigationPage(new SignIn());

Step 4: Consume CRUD operations

Now to consume all the Create, Read, Update and Delete operations for the To-Do list, we’re going to do the same thing as previously, Create an interface for all the required methods and implement them in the service class and finally consume them in the Repository class.

  1. Let start with the interface, we shall name the interface with IToDoService (Surly inside Interfaces folder).

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Threading.Tasks;
    using ToDo.Models;

    namespace ToDo.Interfaces
    {
        public interface IToDoService
        {
            Task<List<ToDoItem>> GetToDoList();

            Task<HttpStatusCode> DeleteToDoItem(int itemId);

            Task<Uri> AddNewToDoItem(ToDoItem item);

            Task<ToDoItem> UpdateToDoItem(int id, ToDoItem item);
        }
    }

    As you can see from the code above, these are asynchronous methods some of them take id as integer and some take item DTO.
    So apparently we need to create this DTO which called ToDoItem, shall we?

    using System;
    namespace ToDo.Models
    {
        public class ToDoItem
        {
            public int Id { getset; }
            public string Name { getset; }
            public string Notes { getset; }
            public bool Done { getset; }
        }
    }

  2. Now we start with the implementation, create a new class named ToDoService inside the Services folder:

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    using ToDo.Interfaces;
    using ToDo.Models;
    using Xamarin.Forms;

    namespace ToDo
    {
        public class ToDoService : IToDoService
        {
            //I recommend to use 
            //https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

            HttpClient client;
            //IUserDetailsStore storeService;
            readonly string token;
            readonly Uri baseUri = new Uri(Constants.BaseURL);

            public ToDoService()
            {
                //storeService = DependencyService.Get<IUserDetailsStore>();
                token = AccountDetailsStore.Instance.Token;
                client = new HttpClient();
                client.MaxResponseContentBufferSize = 256000;
            }

            public async Task<HttpStatusCode> DeleteToDoItem(int id)
            {
                var uri = new Uri(baseUri, string.Format(api/todo/{0}, id));

                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(Authorizationstring.Format(Bearer {0}, token));

                var response = await client.DeleteAsync(uri);

                return response.StatusCode;
            }

            public async Task<Uri> AddNewToDoItem(ToDoItem item)
            {
                var uri = new Uri(baseUri, api/todo/);

                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(Authorizationstring.Format(Bearer {0}, token));

                var json = JsonConvert.SerializeObject(item);
                var content = new StringContent(json, Encoding.UTF8, application/json);
                var response = await client.PostAsync(uri, content);

                response.EnsureSuccessStatusCode();

                // Return   the URI of the created resource.
                return response.Headers.Location;
            }

            public async Task<ToDoItem> UpdateToDoItem(int id, ToDoItem item)
            {
                var uri = new Uri(baseUri, string.Format(api/todo/{0}, id));

                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(Authorizationstring.Format(Bearer {0}, token));

                var json = JsonConvert.SerializeObject(item);
                var content = new StringContent(json, Encoding.UTF8, application/json);
                var response = await client.PutAsync(uri, content);

                // Deserialize the updated product from the response body.
                var responseContent = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<ToDoItem>(responseContent);
            }

            public async Task<List<ToDoItem>> GetToDoList()
            {
                var uri = new Uri(baseUri, api/todo/);

                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Add(Authorizationstring.Format(Bearer {0}, token));

                var response = await client.GetAsync(uri);

                if (response.IsSuccessStatusCode)
                {
                    var content = await response.Content.ReadAsStringAsync();
                    return JsonConvert.DeserializeObject<List<ToDoItem>>(content);
                }
                return new List<ToDoItem>();
            }
        }
    }

    So in this implementation, we have few properties the http client, a string token and base URI. In the constructor, we’re initializing them and filling out the access token saved in the singleton class which was filled genuinely in the Authentication service.
    Now in each method, we’re doing separate API calls GET, POST, DELETE and PUT. As you can see we’re passing the Authorization header with Bearer accessToken.
    Also making sure the content of each request is UTF8 encoded.

  3. Let’s do the Repository ToDoRepository:

    using System;
    using System.Net;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using ToDo.Interfaces;
    using ToDo.Models;

    namespace ToDo
    {
        public class ToDoRepository
        {
            readonly IToDoService todoService;

            public Task<List<ToDoItem>> GetToDoList()
            {
                return todoService.GetToDoList();
            }

            public ToDoRepository(IToDoService todoService)
            {
                this.todoService = todoService;
            }

            public Task<HttpStatusCode> DeleteToDoItem(int itemId)
            {
                return todoService.DeleteToDoItem(itemId);
            }

            public Task<Uri> AddNewToDoItem(ToDoItem item)
            {
                return todoService.AddNewToDoItem(item);
            }

            public Task<ToDoItem> UpdateToDoItem(int id, ToDoItem item)
            {
                return todoService.UpdateToDoItem(id, item);
            }
        }
    }

Step5: ToDo list and Add/Edit pages

By right clicking on the Pages folder then add Forms ContentPage XAML and name it MainPage with the following XAML

<?xml version=1.0 encoding=UTF-8?>
<ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=ToDo.MainPage>
    <ContentPage.Content>
        <ListView x:Name=todoListView ItemSelected=todoListView_ItemSelected>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <ViewCell.ContextActions>
                            <MenuItem Text=Delete IsDestructive=True Clicked=OnTaskDelete CommandParameter={Binding Id} />
                        </ViewCell.ContextActions>
                        <StackLayout Padding=20,0,0,0 HorizontalOptions=StartAndExpand Orientation=Horizontal>
                            <Label Text={Binding Name} VerticalTextAlignment=Center />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.Footer>
                <Button x:Name=AddTaskButton Text=Add task></Button>
            </ListView.Footer>
        </ListView>
    </ContentPage.Content>
</ContentPage>

This page looks like a UITableView in the iOS world and ListView in Android world, we’re defining the cell template here to be a stack layout and have a label in it which will contain the to-do item title. Having stack layout as a template will give us the capability to add more controls later on.

Also, you will notice that we have defined the menu item, which is the delete button.
The delete button will behave according to the platform, press and hold on Android and swipe the cell to the left to see the delete button in iOS and by having command parameter we’re going to pass the ID to the function which is in our case OnTaskDelete.


If you notice, we have “Add task” button at the footer of this list view to redirect users to the Add/Edit page and also by having this button at the footer we’re preventing list view from having extra empty cells. Definitely, it’s going to look lame if we have extra empty cells.
now going to C# code:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ToDo.Models;
using Xamarin.Forms;

namespace ToDo
{
    public partial class MainPage : ContentPage
    {
        ToDoRepository todoRepo = new ToDoRepository(new ToDoService());

        public MainPage()
        {
            InitializeComponent();

            configurePage();
        }

        private void configurePage()
        {
            Title = To do list;
            AddTaskButton.Clicked += AddTaskButton_Clicked;
            NavigationPage.SetHasBackButton(thisfalse);
        }

        protected override void OnAppearing()
        {
            base.OnAppearing();
            var _ = configureTodoList();
        }

        private async Task configureTodoList()
        {
            todoListView.ItemsSource = await todoRepo.GetToDoList();
        }

        void AddTaskButton_Clicked(object sender, EventArgs e)
        {
            Navigation.PushAsync(new ItemDetailsPage(new ToDoItem()));
        }

        void todoListView_ItemSelected(object sender, Xamarin.Forms.SelectedItemChangedEventArgs e)
        {
            var todoItem = e.SelectedItem as ToDoItem;
            var itemDetailsPage = new ItemDetailsPage(todoItem)
            {
                BindingContext = todoItem
            };
            Navigation.PushAsync(itemDetailsPage);
        }

        public async void OnTaskDelete(object sender, EventArgs e)
        {
            var menuItem = ((MenuItem)sender);
            var taskId = (Int32)menuItem.CommandParameter;
            var isConfirmed = await DisplayAlert(Delete ConfirmationAre you sure you want to delete this task?ConfirmCancel);

            if (isConfirmed)
            {
                await todoRepo.DeleteToDoItem(taskId);
                await configureTodoList();
            }
        }
    }
}

Again, As I usually do, I start explaining the constructor. Oh, there is nothing abnormal here just removing the back button to not get back to the verification page nor sign in one. also, we’re assigning the event handler for the add task button.

Finally, Add/Edit page named ItemDetailsPage:

<?xml version=1.0 encoding=UTF-8?>
<ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=ToDo.ItemDetailsPage>
    <ContentPage.Content>
        <StackLayout Orientation=Vertical VerticalOptions=StartAndExpand Padding=20,0,20,0>
            <Label Text=Name>
            </Label>
            <Entry x:Name=nameEntry Keyboard=Default Text={Binding Path=Name} Placeholder=task name>
            </Entry>
            <Label Text=Notes>
            </Label>
            <Editor x:Name=notesEditor HeightRequest=90 Keyboard=Default Text={Binding Path=Notes}>
            </Editor>
            <Label Text=Done>
            </Label>
            <Switch x:Name=doneSwitch IsToggled={Binding Path=Done}>
            </Switch>
            <Button Text=Save x:Name=saveItemButton VerticalOptions=CenterAndExpand Clicked=SaveItemButton_Clicked>
            </Button>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Regular content page with controls in it to represent a form for adding or editing tasks.
C# code:

using System;
using System.Collections.Generic;
using ToDo.Models;
using Xamarin.Forms;

namespace ToDo
{
    public partial class ItemDetailsPage : ContentPage
    {
        ToDoItem toDoItem;
        ToDoRepository toDoRepo = new ToDoRepository(new ToDoService());

        public ItemDetailsPage(ToDoItem item)
        {
            InitializeComponent();
            this.toDoItem = item;
            Title = Details;
        }

        async void SaveItemButton_Clicked(object sender, System.EventArgs e)
        {
            toDoItem.Name = nameEntry.Text.Trim();
            toDoItem.Notes = notesEditor.Text.Trim();
            toDoItem.Done = doneSwitch.IsToggled;

            if (toDoItem.Id == 0)
            {
                await toDoRepo.AddNewToDoItem(toDoItem);
            }
            else
            {
                await toDoRepo.UpdateToDoItem(toDoItem.Id, toDoItem);
            }
            await Navigation.PopAsync(true);
        }
    }
}

Create main screen, Master-Detail Page – Part 3

All code can be found in my Github repository.

In this part, I’m going to create a main screen for the app and it’s going to be skeleton as some kind of blue·print so we can fill these pages later on with controls and contents.
First of all, you should ask yourself a question:

What is Master-Details page?

According to xamarin.com, MasterDetailPage is a page that manages two related pages of information – a master page that presents items, and a detail page that presents details about items on the master page.
it looks like as shown below:

master-detail

So, what am willing to do is to have the main screen where I can show all the promoted products and any news or trends in the detail page and on the master page i will list all the menu items, and so far am adding these:

  • Home
  • Products
  • Contact us

In summary, the list pages will be like this:

  • MainPage.xaml: MasterDetailPage, is the main container which has the menu (Hamburger menu) and contains Master and Detail properties that are both of type Page and used to get and set the master and detail pages respectively.
  • MasterPage.xaml: page where we will list all the menu items in, and once a user taps on one of these menu items, we will load this page in the detail page.
  • HomePage.xaml: page where I’ll show all the promoted products and any news or trends as mentioned above – this page will be loaded initially in MainPage.
  • ProductsPage.xaml: page where we will show products to be purchased, might contain search functionality and some filtrations.
  • ContactUsPage.xaml: Regular contact us page.

Before we get started on making pages, I would like to make a new folder name it Pages and after that, we shall create page by page (in the part, we will cover main, master and home pages).

MainPage

So on the Pages folder, we right click -> Add -> New file… and then from the forms menu choose Forms ContentPage Xaml, let’s name it MainPage.xaml
In this page, you can write the following XAML code:

<?xml version=1.0 encoding=UTF8?>
<MasterDetailPage
        xmlns=http://xamarin.com/schemas/2014/forms
        xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml
        x:Class=PuzzlersJordan.MainPage
        xmlns:local=clrnamespace:PuzzlersJordan;assembly=PuzzlersJordan
        Title=Main>
    <MasterDetailPage.Master>
        <local:MasterPage x:Name=masterPage>
        </local:MasterPage>
    </MasterDetailPage.Master>
    <MasterDetailPage.Detail>
        <NavigationPage>
            <x:Arguments>
                <local:HomePage />
            </x:Arguments>
        </NavigationPage>
    </MasterDetailPage.Detail>
</MasterDetailPage>

you can find in this XAML code that there is unusual declaration shown in below line:

xmlns:local=clrnamespace:PuzzlersJordan;assembly=PuzzlersJordan

This line is a reference declaration to the current assembly in order to reference any class found in the assembly, to reference any class you should use the local keyword as shown below:

  <local:MasterPage x:Name=masterPage>
  </local:MasterPage>

Or in:

<local:HomePage />

So to set MasterDetailPage.Master property we assign MasterPage to it and we gave it a name which is masterPage (so we can call it from the code behind).
On the other hand, for the detail property, we set a navigation page with a root page Home page.

So for the code behind, open MainPage.xaml.cs and the code should look like below:

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace PuzzlersJordan
{
    public partial class MainPage : MasterDetailPage
    {
        public MainPage()
        {
            InitializeComponent();
            masterPage.masterMenuList.ItemSelected += OnItemSelected;
        }

        void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            var item = e.SelectedItem as MasterPageItem;
            if (item != null)
            {
                Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
                masterPage.masterMenuList.SelectedItem = null;
                IsPresented = false;
            }
        }
    }
}

In the constructor, we accessed masterPage and then an instance of the masterMenuList (which is a listView that we will talk about later) to assign an event handler whenever a user taps on any of the menu items (item get selected).
So what we’re going to do is when the user taps on the menu item we will take the corresponding page and load it on the detail property and set selectedItem to null so it won’t be highlighted.

MasterPage

It’s the left menu that has all the menu items, UI wise it’s just a contentPage that has a simple StackLayout with some decoration properties shown below:

<?xml version=1.0 encoding=UTF8?>
<ContentPage xmlns=http://xamarin.com/schemas/2014/forms xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml x:Class=PuzzlersJordan.MasterPage Padding=0,40,0,0 Icon=Hamburger Title=Menu>
    <ContentPage.Content>
        <StackLayout VerticalOptions=FillAndExpand>
            <ListView x:Name=MenuListView VerticalOptions=FillAndExpand SeparatorVisibility=None>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text={Binding Title} TextColor=#a9d300 />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Let’s talk a little bit about the code above:

  • Content page with padding of 40 points from the top and a must have title.
  • Set the icon of Hamburger which comes for free with android but we have to set it manually on iOS (follow this tutorial in order to do that).
  • We have ListView control with a data template to bind data from item class.

As for the code behind:

using System;
using System.Collections.Generic;

using Xamarin.Forms;

namespace PuzzlersJordan
{
    public class MasterPageItem
    {
        public string Title { get; set;}
        public Type TargetType { get; set; }

    }

    public partial class MasterPage : ContentPage
    {

        public ListView masterMenuList
        {
            get
            {
                return MenuListView;
            }
        }

        public MasterPage()
        {
            InitializeComponent();
            var masterPageItems = new List<MasterPageItem>();

            masterPageItems.Add(new MasterPageItem
            {
                Title = Home,
                TargetType = typeof(HomePage)
            });

            masterPageItems.Add(new MasterPageItem
            {
                Title = Products,
                TargetType = typeof(ProductsPage)
            });

            masterPageItems.Add(new MasterPageItem
            {
                Title = Contact us,
                TargetType = typeof(ContactUsPage)
            });

            MenuListView.ItemsSource = masterPageItems;
        }
    }
}

I declared a simple class (MasterPageItem) with two properties Title and TargetType. On the constructor, filled out a list of menu items in the new instance of a list of MasterPageItem and assigned it to the ItemSource.

HomePage

Just an empty content page that we will work on it later, but we need it here just to not break the detail page on MainPage.

Adding Splash screen (Part 2)

Adding Splash screen (Part 2)

All code can be found in my Github repository.

The splash screen is very important to any mobile application it gets users attention from first sight.

What is Splash screen?

A splash screen is a graphical control element consisting of a window containing an image, a logo and the current version of the software. A splash screen usually appears while a game or program is launching.

Since Xamarin.Forms doesn’t support adding splash screen from one place like it does for pages, you need to go to each platform project – in our case iOS and Android – and add splash screen for each one.

iOS:

In our solution, you go to PuzzlersJordan.iOS project and follow this simple steps:

  1. In the Solution Explorer, double-click LaunchScreen.storyboard to open it for editing.
  2. Ensure that the Size Class is set to any:any and the View As is Generic.
    storyboard05.png
  3. Set the background colour of the main View by opening the properties panel – widget tab then background property.
    screen-shot-2017-02-20-at-11-36-24-pm
  4. Drag an Image View from the Toolbox into the design surface and set it at the centre of the screen.
    screen-shot-2017-02-20-at-11-48-12-pm
  5. Set the source of the Image (as an Image added to the project as an Asset Catalog) in the Property Explorer and reposition and size the image as required.
  6. Add the required constraints in order to keep image placed at the centre of the screen, constraints are:
    Vertical Alignment
    Horizontal Alignment
    screen-shot-2017-02-20-at-11-54-00-pm.png
  7. Save the changes to the Storyboard.

Am using this method because I have only the logo (not the whole images), In case you have a whole image you can follow these instructions provided by xamarinhelp.com:

  1. Create a splash screen image in the following sizes:
    320×480
    640×960
    640×1136
  2. Go to Properties > iOS Application > iPhone Launch Images and import the images. It will automatically add them to the Resources folder in your iOS Project.
    ios_splashscreen_settings
  3. Move down the properties page to add an image for iPad apps.
  4. If you are having issues with your images still displaying there are a few possible causes. The LaunchScreen.storyboard could be the issue. You can open it and correct it, or even try deleting it. Once you have done this, rebuild your application and reset your iOS Simulator or delete from your iPhone as iOS has a tendency to cache extensively in this area.

Android:

For Android, things are different. there are different ways to implement a splash screen. I have come across one of the easiest and quickest ways to do so.

All we need to do is we create a custom theme and apply it to an Activity that exhibits the splash screen. When the Activity is rendered, it loads the theme and applies the drawable resource (referenced by the theme) to the background of the activity. This approach avoids the need for creating a layout file.

Once the app has bootstrapped, the splash screen Activity starts the main Activity and removes itself from the application back-stack.

Follow along to make a fabulous splash screen for Android:

  1. Create a drawable resource for the splash screen to cater for the below resolutions (personally, I ask the designer to do so), this drawable is just the logo that we want to show in the center of the screen, name it ‘splash_logo’ since we’re going to refer to it later on:
    drawable-hdpi
    drawable-ldpi
    drawable-mdpi
    drawable-xhdpi
    drawable-xxhdpi
    drawable-xxxhdpi
    Note: It is necessary to use a bitmapped image (such as a PNG or JPG) for the image to display.
  2. In this step, we create two files:
    a. In order to reference colours in the following step, we need to create a new resource XML file inside values folder called colors.xml

    <?xml version=1.0 encoding=utf8?>
    <resources>
      <color name=splash_background>#A7CD38</color>
    </resources>

    b. To centre the splash screen image in the application, I’ll use a Layer List. The following snippet is an example of a drawable resource using a layer-list:

    <?xml version=1.0 encoding=utf8?>
    <layer-list xmlns:android=http://schemas.android.com/apk/res/android>
      <item>
        <color android:color=@color/splash_background/>
      </item>
      <item>
        <bitmap
            android:src=@drawable/splash_logo
            android:tileMode=disabled
            android:gravity=center/>
      </item>
    </layerlist>

    This layer-list will centre the splash screen image splash_logo.png on a background specified by the @color/splash_background resource as we created in step a.

  3. Create a custom theme for the splash screen Activity, edit (or add) the file values/styles.xml and create a new style element for the splash screen. A sample values/style.xml file is shown below with a style named splashscreen:

    <?xml version=1.0 encoding=UTF8?>
    <resources>
        <style name=splashscreen parent=MyTheme.Base>
            <item name=android:windowBackground>@drawable/splash_screen</item>
            <item name=android:windowNoTitle>true</item>
            <item name=android:windowIsTranslucent>false</item>
            <item name=android:windowIsFloating>false</item>
            <item name=android:backgroundDimEnabled>true</item>
            <item name=android:colorPrimaryDark>#85A42C</item>
        </style>


    </resources>

  4. We need a new Activity called SplashActivity to launch that has our splash image and performs any startup tasks. The following code is an example of a complete splash screen implementation:

    using Android.App;
    using Android.OS;
    using Android.Support.V7.App;

    namespace PuzzlersJordan.Droid
    {
        [Activity(Label = Puzzlers Jordan, Icon = @drawable/icon, Theme = @style/splashscreen, MainLauncher = true, NoHistory = true)]
        public class SplashActivity : AppCompatActivity
        {
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
                this.StartActivity(typeof(MainActivity));
            }
        }
    }

    As noticed from the above implementation, we’re assigning splashscreen theme created previously to this activity and made sure to set this activity as the Main Launcher so when the app get launched it should trigger this activity at first.

    Also, note that we attributed this activity to have NoHistory set to true so it means that the activity will not leave a historical trace. It will not remain in the activity stack for the task so the user will not be able to return to it.

    Note: You most remove the MainLauncher attribute from MainActivity.

Let’s create a project, shall we? (Part 1)

Let’s create a project, shall we? (Part 1)

All code can be found in my Github repository.

In order to get started, we need do the setup for our solution (the base block) and start from there.

Project Setup:

This is a trivial part, you need to launch your preferred IDE (as mentioned before am using Xamarin Studio) and follow these instructions:

  1. From the menu go to File, click New Solution. from the left panel under Multiplatform section choose App and from the middle panel choose Forms App with C# then press Next button.
    screen-shot-2017-02-22-at-7-56-05-pm
  2. On the second screen, Write the name of the app you’re intending to create in the App Name field (In my case the name will be PuzzlersJordan), and then write the Organization identifier.

    What is Organization identifier?

    It’s that identifier that is being used in your app to be distinguished among other apps, it comes with the form ‘com.yourcompanyname.productname’.
    For Android, it will be the package name and for iOS, it’s the bundle identifier.

    Next, make sure to check Android and iOS as Target Platforms and for the Shared Code choose ‘Use portable Class library’ and check XAML for user interface files.

    What is the difference between Shared Library and portable class library?

    To answer this question it will take me a whole blog post just to explain it. so instead I recommend reading this Xamarin Help blog post by Adam Pedley.

    screen-shot-2017-02-22-at-9-25-29-pm.png

  3. The last step, you need to specify the name of the project and solution, where should it be located on your machine and if you want to create a git repository for it.
  4. Press Create and you will be ready to develop the solution.

What are we going to build? (Part 0)

What are we going to build? (Part 0)

Previously, we talked about what is Xamarin, it’s pros/cons and Xamarin family members, It’s highly recommended to be familiar with Xamarin before kicking off with this series. if you haven’t checked it before you can click on this link.
In this series, we will be building up an application for a friend of mine, owner of Puzzlers Jordan in order to grow his business up and reach a better amount of customers/puzzle lovers.
At the moment of writing this post, the app hasn’t been created. so I’ll be building a simple functional mobile app with little to no complications for the two dominant platforms in the market (Android and iOS), I’ll be using Xamarin.Forms.
I made this decision after checking Xamarin’s site Is Xamarin.Forms right for your project? plus considering it as a challenge 😊

screen-shot-2017-02-20-at-9-17-51-pm

Finally, before we start we need to know what are the environments prior starting building the application:
This screenshot demonstrates windows and mac operating systems

screen-shot-2017-02-20-at-9-52-04-pm

So choose your preferred IDE and OS. As for me am going to use Xamarin Studio for MacOS as my IDE, feel free to follow along with any other IDE.

Before we start, note the below:

  • You have to be familiar with C# and little XAML.
  • Have a mac machine or at least connected to one since iOS platform is part of our solution.

Enjoy 🙂