Custom programming applications, web sites and training since 2002-we can also take care of your hosting, self-publishing and more

Xamarin Cross-Platform Solution Creating the Views Directory (AboutPage)

Now we get to create the individual Views used in our Xamarin cross-platform mobile app. Because many of these are quite similar, we will be excluding much of the code in XAML page documents below the first. As I am sure you already know, proper app design means separation of the Model-View-Controller into their own sections of code. Today we will be covering the View designs of our Wet Your Whistle mobile app. We will start below with the xaml contained in the About 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"
             xmlns:local="clr-namespace:NYWineryHopper.Views"
             xmlns:controls="clr-namespace:MarcTron.Plugin.Controls;assembly=Plugin.MtAdmob"
             x:Class="NYWineryHopper.Views.AboutPage"
             Title="About">
    <ContentPage.ToolbarItems >
        <ToolbarItem Text="Vid Walkthru" Clicked="Loadvid"  />
        <ToolbarItem Text="Settings" Clicked="LoadSettings"  />
    </ContentPage.ToolbarItems>
    <ContentPage.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="50" />
            </Grid.RowDefinitions>
            <StackLayout Grid.Row="0">
                <Label Text="About NY Wine Hopper" FontSize="Large"
                    VerticalOptions="CenterAndExpand" 
                    HorizontalOptions="CenterAndExpand" />
                <Image Source="mainpic.png" HeightRequest="200" WidthRequest="200" />
                <Label Text="by Link Em Up LLC" FontSize="Large" FontAttributes="Italic" TextDecorations="Underline"
                    VerticalOptions="CenterAndExpand" 
                    HorizontalOptions="CenterAndExpand" >
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Tapped="tapClick_Tapped" />
                    </Label.GestureRecognizers>
                </Label>
                <Grid Padding="10,0,10,0">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="50"></RowDefinition>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"></ColumnDefinition>
                        <ColumnDefinition Width="40"></ColumnDefinition>
                        <ColumnDefinition Width="40"></ColumnDefinition>
                        <ColumnDefinition Width="40"></ColumnDefinition>
                        <ColumnDefinition Width="40"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Grid.Row="0" Grid.Column="0" Text="Missing a winery/store/restaurant? Contact us" FontSize="Medium" 
                           VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
                           MaxLines="2" FontAttributes="Italic"/>
                    <Image x:Name="emClick"  Grid.Row="0" Grid.Column="1" Source="email_icon.png" >
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="tapClick_Email" />
                        </Image.GestureRecognizers>
                    </Image>
                    <Image x:Name="weClick"  Grid.Row="0" Grid.Column="2" Source="icon_web.png" >
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="tapClick_Web" />
                        </Image.GestureRecognizers>
                    </Image>
                    <Image x:Name="faClick"  Grid.Row="0" Grid.Column="3" Source="facebook_512.png" >
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="tapClick_Facebook" />
                        </Image.GestureRecognizers>
                    </Image>
                    <Image x:Name="twClick"  Grid.Row="0" Grid.Column="4" Source="twitter_512.png" >
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="tapClick_Twitter" />
                        </Image.GestureRecognizers>
                    </Image>
                </Grid>
                <ScrollView Orientation="Vertical" VerticalScrollBarVisibility="Always">
                    <StackLayout>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="Please Note: Distance calculation is an estimate which will not correlate to actual driving distance. For true driving distance and directions, use your favorite mapping program"
                            FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="Welcome to your ultimate source for North Carolina wine travels. Our app goes with you everywhere to enhance your wine bibbing experience. Whether you want to search by name, county or region we have you covered"
                            FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="When searching, you don't have to make a choice from the final three options. Clicking 'Show me' without choosing from these three options will include all of them. Our database is continually growing with more restaurants and shops. As wineries open and close, your trip can be updated as fast as our database can be maintained. If you want to include only those who have tours or tastings, that option is in the app also." FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="Since hours and availability change for seasonal and other purposes, it is a good idea to call all wineries, shops and restaurants before making a trip to their establishment. To call, click on the icon to the left and press the Phone button after that." FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="The app provides single-click access to all available web site, social media and reviews. These will open in a browser window on your device. You will notice two rows of icons below the type - Google Maps, TripAdvisor and Yelp include reviews. You are encouraged to leave reviews yourself to direct others to the wineries that you have so greatly enjoyed!" FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                        <ContentView Padding="10,0,10,0">
                            <Label Text="DISCLAIMER: Neither Link Em Up LLC or Wine Hopper Mobile Apps are responsible for the use, misuse or content of the social media accounts included in the app. There has been no monetary remuneration from the wineries, shops or restaurants to be included in the app. Likewise beyond tastings, tours or other normal participation in their business, our company has no investment in the businesses represented in the app." FontSize="Medium"
                            VerticalOptions="CenterAndExpand" 
                            HorizontalOptions="CenterAndExpand" />
                        </ContentView>
                    </StackLayout>
                </ScrollView>
            </StackLayout>
            <!--iOS = "* admob ios can go here *"; Android = "* admob android can go here *";-->
            <controls:MTAdView x:Name="mtAd" Grid.Row="1" />
        </Grid>
    </ContentPage.Content>
</ContentPage>

Above you see the complete XAML code to be placed in AboutPage.xaml. You will see a reference to the MarcTron MtAdmob plugin which was used to display Google Admob ads throughout the app. You will also see references which call functions located in the csharp code file shown below. The first two calls are made from toolbar items labeled “Vid Walkthru” and “Settings.”

Next we have a stacklayout grid set up with two rows – the top row takes all of the space other than 50 pixels. The first row contains an “About” link, image and clickable TapGestureRecognizer. The second grid definition is also laid out in the first row with five columns. The first column is designed to us the remaining width after a width is used for four 40 pixel graphics. Inside of those graphics we are calling functions to send email, open a web site, Facebook and Twitter.

Now we get to use a scrollview to display multiple contentviews with text labels inside of them. These labels display specific details about our app which help the user to get the most benefits. Now let’s get into the functions being called by this screen. The C# code shown below is contained in AboutPage.xaml.cs

namespace NYWineryHopper.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class AboutPage : ContentPage
    {
        public AboutPage()
        {
            InitializeComponent();
        }
        void tapClick_Tapped(object sender, EventArgs e)
        {
            string url = "https://wwwords.biz";
            LoadBrowser(url);
        }

        void tapClick_Email(object sender, EventArgs e)
        {
            Launcher.OpenAsync(new Uri("mailto:slink@winehopper.app?subject=New Content Suggestion&body=The name is ______________ and they are located in ______________\nWhat NY wines do they sell?"));
        }

        void tapClick_Web(object sender, EventArgs e)
        {
            string url = "https://winehopper.app";
            LoadBrowser(url);
        }

        void tapClick_Facebook(object sender, EventArgs e)
        {
            string url = "https://www.facebook.com/stephen.link.737";
            LoadBrowser(url);
        }

        void tapClick_Twitter(object sender, EventArgs e)
        {
            string url = "https://twitter.com/winehopper1";
            LoadBrowser(url);
        }

        void Loadvid(object sender, EventArgs e)
        {
            string url = "https://youtube.com/watch?v=6NYSkh5ucAU&w=320&h=575";
            LoadYTBrowser();
        }

        private async void LoadBrowser(string url)
        {
            await Navigation.PushAsync(new WVPage(url));
        }
        private async void LoadYTBrowser()
        {
            await Navigation.PushAsync(new YTPage());
        }
        private async void LoadSettings(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new SettingsPage());
        }
    }
}

Let’s start at the top of AboutPage with the LoadVid function. This sets the URL to a Youtube video and calls the LoadYTBrowser private function. That function then loads a new page, using Navigation.PushAsync, which is designed with a video player embedded.

The next function called in AboutPage is LoadSettings. This uses the same approach already mentioned to load SettingsPage which allows modification of user settings and saves them for use in the mobile app.

Sending an email uses the native device call OpenAsync to load the default email client to send an email with a few fields prepopulated while the remaining functions set a URL destination and then call the LoadBrowser function which opens a page with an embedded browser to display that page.