Xamarin Forms  -  Aplicação Minhas Caminhadas
 Este artigo apresenta a aplicação - Minhas Caminhadas - com o objetivo de mostrar como criar aplicações funcionais e úteis usando o Xamarin Forms.

Que tal criar uma aplicação que você pode usar no seu celular para algo que seja útil no seu dia a dia ?

Pensando nisso eu criei um protótipo de uma aplicação que eu chamei - Minhas Caminhadas - e que tem como objetivo gerenciar trajetos de caminhadas que você pode registrar.

Eu vou apresentar o que seria a primeira parte da aplicação onde vamos registrar as trilhas , exibir detalhes das trilhas e um mapa da trilha. Falta implementar outras funcionalidades.

Para fugir um pouco da abordagem que sempre faço ao criar aplicações Xamarin Forms, que é definir a interface via código XAML, nesta aplicação vou fazer a definição usando código C#.

Eu creio que não é uma abordagem mais adequada mas a título de exercício, nesta aplicação toda a interface vai ser definida via código C#.

O código vai estar comentado e por isso vou ser bem sucinto na descrição das rotinas.

Veja como nossa aplicação deve funcionar nesta primeira parte:

O projeto esta sendo executado em um dispositivo físico ALCATEL Pixi 4 usando o Vysor para exibir a aplicação no computador.

Então ao trabalho...

Recursos usados:

Criando o projeto no Visual Studio 2017 Community

Abra o Visual Studio Community 2017 e clique em New Project;

Selecione Visual C#, o template Cross-Plataform e a seguir Cross-Platform App (Xamarin.Forms);

Informe o nome XF_Analogico e clique no botão OK;

Selecione as plataformas desejadas: Android, iOS e UWP, marque o item Xamarin.Forms e a seguir escolha .NET Standard e clique no botão OK.

Nota: A partira da versão 15.5 do Visual Studio o template PCL foi substituito pelo .NET Standard.

Definindo o modelo de domínio

Vamos criar uma pasta Models no projeto e criar a classe Caminhada com o seguinte código :

    public class Caminhada
    {
        public string Titulo { get; set; }
        public string Notas { get; set; }
        public double Longitude { get; set; }
        public double Latitude { get; set; }
        public double Kilometros { get; set; }
        public string Dificuldade { get; set; }
        public double Distancia { get; set; }
        public string ImagemUrl { get; set; }
    }

Esse será o modelo de domínio da nossa aplicação.

Incluindo uma referência a Xamarin.Forms.Maps no projeto

Vamos incluir no projeto via pacote Nuget uma referência a biblioteca Xamarin.Forms.Maps:

Marcando as permissões requeridas no arquivo Android Manifest

Para poder usar o recurso do Google Maps em nossa aplicação Android abra a janela de propriedades do projeto Android e marque as opções conforme abaixo:

Marque, além dessas opções, a opção Internet :

Definindo o código de inicialização da aplicação :  App.cs

No código de inicialização verificamos se a plataforma for Android e chamamos a página de apresentação SplashPage ou a página principal CaminhadasPage.

using Xamarin.Forms;
namespace XFCaminhadas
{
    public partial class App : Application
    {
        public App()
        {
            // verifica a plataforma
            if (Device.RuntimePlatform == Device.Android)
            {
                MainPage = new SplashPage();
            }
            else
            {
                // a página raiz da nossa app
                var navPage = new NavigationPage(new XFCaminhadas.CaminhadasPage()
                {
                    Title = "Minhas Caminhadas"
                });
                MainPage = navPage;
           }
        }
        protected override void OnStart()
        {
            // Handle when your app starts
        }
        protected override void OnSleep()
        {
            // Handle when your app sleeps
        }
        protected override void OnResume()
        {
            // Handle when your app resumes
        }
    }
}

Definindo a página de apresentação :  SplashPage.cs

Todas as páginas da nossa aplicação serão somente arquivos C# com extensão .cs.

Para incluir uma página selecione o menu Project e a seguir Add New Item e clique em Content Page (C#) informando o nome da página.

Vamos iniciar criando a página SplashPage:

Abra a página SplashPage.cs e inclua o código abaixo nesta página:

using System.Threading.Tasks;
using Xamarin.Forms;
namespace XFCaminhadas
{
    public class SplashPage : ContentPage
    {
        public SplashPage()
        {
            AbsoluteLayout splashLayout = new AbsoluteLayout
            {
                HeightRequest = 600
            };
            var image = new Image()
            {
                //define a imagem usada na tela de apresentação
                Source = ImageSource.FromFile("icon.png"),
                Aspect = Aspect.AspectFill,
            };
            //define as configurações da imagem
            AbsoluteLayout.SetLayoutFlags(image, AbsoluteLayoutFlags.All);
            AbsoluteLayout.SetLayoutBounds(image, new Rectangle(0f, 0f, 1f, 1f));
            splashLayout.Children.Add(image);
            //inclui a imagem no StackLayout
            Content = new StackLayout()
            {
                Children = { splashLayout }
            };
        }
        protected override async void OnAppearing()
        {
            base.OnAppearing();
            // Tempo de espera de alguns segundos para exibir a tela inicial
            await Task.Delay(4000);
            // Instancia a NavigationPage com a MainPage
            var navPage = new NavigationPage(new CaminhadasPage()
            {
                Title = "Minhas Caminhadas"
            });
            Application.Current.MainPage = navPage;
        }
    }
}

O código acima define a tela de apresentação com a imagem a ser exibida por 4 segundos antes de chamar a página principal : CaminhadasPage.cs

Definindo a página das trilhas :  CaminhadasPage

A próxima página a ser criada é a página CaminhadasPage.cs que exibe as trilhas cadastradas em um ListView

Abra o arquivo CaminhasdasPage.cs e inclua o código abaixo:

using System.Collections.Generic;
using Xamarin.Forms;
using XFCaminhadas.Models;
namespace XFCaminhadas
{
    public class CaminhadasPage : ContentPage
    {
        public CaminhadasPage()
        {
            //define a toolbar
            var novaCaminhadaItem = new ToolbarItem
            {
                Text = "Adicionar Caminhada"
            };
            //define o evento Click 
            novaCaminhadaItem.Clicked += (sender, e) =>
            {
                Navigation.PushAsync(new CaminhadaInfoPage());
            };
            //inclui o item na toolbar
            ToolbarItems.Add(novaCaminhadaItem);
            //define uma trilha
            var caminhadaRoteiros = new List<Caminhada>
            {
                new Caminhada
                {
                  Titulo = "3 Kilometros de caminhada, Parque da Represa",
                  Notas = "A caminhada se inicia na entrada da represa ao lado Hospital AMA" +
                          " percorrendo o caminho à direita, cruzando a ponte e contornando a represa. ",
                  Latitude = -20.8107481,
                  Longitude = -49.3545277,
                  Kilometros = 3.1,
                  Distancia = 0,
                  Dificuldade= "Fácil",
                  ImagemUrl = "http://www.macoratti.net/images/represa1.jpg"
                }
            };
            //define as propriedades do Listview e faz o binding
            var itemTemplate = new DataTemplate(typeof(ImageCell));
            itemTemplate.SetBinding(TextCell.TextProperty, "Titulo");
            itemTemplate.SetBinding(TextCell.DetailProperty, "Notas");
            itemTemplate.SetBinding(ImageCell.ImageSourceProperty,"ImagemUrl");
            //define o listview para exibir as trilhas
            var listaCaminhadas = new ListView
            {
                HasUnevenRows = true,
                ItemTemplate = itemTemplate,
                ItemsSource = caminhadaRoteiros,
                SeparatorColor = Color.FromHex("#ddd"),
            };
            // Configura o tratamento de evento
            listaCaminhadas.ItemTapped += (object sender,ItemTappedEventArgs e) =>
            {
                var item = (Caminhada)e.Item;
                if (item == null) return;
                Navigation.PushAsync(new CaminhadaTrilhasPage(item));
                item = null;
            };
            Content = listaCaminhadas;
        }
    }
}

Definindo os detalhes das trilhas :  CaminhadaTrilhasPage.cs

Vamos definir a exibição dos detalhes das trilhas criando a página CaminhadaTrilhasPage.cs

Abra o arquivo CaminhasdaTrilhasPage.cs e inclua o código abaixo:

using Xamarin.Forms;
using XFCaminhadas.Models;
namespace XFCaminhadas
{
    public class CaminhadaTrilhasPage : ContentPage
    {
        public CaminhadaTrilhasPage(Caminhada caminhadaItem)
        {
            Title = "Trilha da Caminhada";
            var inicioCaminhadaTrilha = new Button
            {
                BackgroundColor = Color.FromHex("#008080"),
                TextColor = Color.White,
                Text = "Iniciar esta trilha"
            };
            // define o tratamento de evento
            inicioCaminhadaTrilha.Clicked += (sender, e) =>
            {
                if(caminhadaItem == null) return;
                Navigation.PushAsync(new DistanciaPercorridaPage(caminhadaItem));
                Navigation.RemovePage(this);
                caminhadaItem = null;
            };
            var caminhadaTrilhaImagem = new Image()
            {
                Aspect = Aspect.AspectFill,
                Source = caminhadaItem.ImagemUrl
            };
            var nomeTrilhaLabel = new Label()
            {
                FontSize = 28,
                FontAttributes = FontAttributes.Bold,
                TextColor = Color.Black,
                Text = caminhadaItem.Titulo
            };
            var kilometrosTrilhaLabel = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 12,
                TextColor = Color.Black,
                Text = $"Distância : { caminhadaItem.Kilometros } km"
            };
            var dificuldadeTrilhaLabel = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 12,
                TextColor = Color.Black,
                Text = $"Dificuldade: { caminhadaItem.Dificuldade } "
            };
            var descricaoCompletaTrilha = new Label()
            {
                FontSize = 11,
                TextColor = Color.Black,
                Text = $"{ caminhadaItem.Notas }",
                HorizontalOptions = LayoutOptions.FillAndExpand
            };
            this.Content = new ScrollView
            {
                Padding = 10,
                Content = new StackLayout
            {
                    Orientation = StackOrientation.Vertical,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children ={
                        caminhadaTrilhaImagem,
                        nomeTrilhaLabel,
                        kilometrosTrilhaLabel,
                        dificuldadeTrilhaLabel,
                        descricaoCompletaTrilha,
                        inicioCaminhadaTrilha
                        }
                }
            };
        }
    }
}

Exibindo o mapa da trilha  : DistanciaPercorridaPage.cs

Agora vamos exibir o mapa da trilha , o tempo gasto e a distância percorrida criando a página DistanciaPercorridaPage.cs

Abra o arquivo DistanciaPercorridaPage.cs criado e inclua o código abaixo:

using Xamarin.Forms;
using Xamarin.Forms.Maps;
using XFCaminhadas.Models;
namespace XFCaminhadas
{
    public class DistanciaPercorridaPage : ContentPage
    {
        public DistanciaPercorridaPage(Caminhada caminhadaItem)
        {
            Title = "Distância Percorrida";
            // Instanciando o nosso objeto Map
            var trilhaMapa = new Map();
            // Colocar uma marcação no mapa para um tipo de caminhada escolhida
            trilhaMapa.Pins.Add(new Pin
            {
                Type = PinType.Place,
                Label = caminhadaItem.Titulo,
                Position = new Position(caminhadaItem.Latitude, caminhadaItem.Longitude)
            });
            // centraliza o mapa ao redor da lista de localização das caminhadas
            trilhaMapa.MoveToRegion(MapSpan.FromCenterAndRadius(
                new Position(caminhadaItem.Latitude, caminhadaItem.Longitude),Distance.FromKilometers(1.0)));
            var nomeTrilhaLabel = new Label()
            {
                FontSize = 18,
                FontAttributes = FontAttributes.Bold,
                TextColor = Color.Black,
                Text = caminhadaItem.Titulo
            };
            var distanciaCaminhadaTrilhaLabel = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 20,
                TextColor = Color.Black,
                Text = "Distância Percorrida",
                HorizontalTextAlignment = TextAlignment.Center
            };
            var distanciaTotalPercorrida = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 20,
                TextColor = Color.Black,
                Text = $"{ caminhadaItem.Distancia } km",
                HorizontalTextAlignment = TextAlignment.Center
            };
            var tempoTotalGastoLabel = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 20,
                TextColor = Color.Black,
                Text = "Tempo Gasto:",
                HorizontalTextAlignment = TextAlignment.Center
            };
            var tempoTotalGasto = new Label()
            {
                FontAttributes = FontAttributes.Bold,
                FontSize = 20,
                TextColor = Color.Black,
                Text = "0h 0m 0s",
                HorizontalTextAlignment = TextAlignment.Center
            };
            var btnCaminhadas = new Button
            {
                BackgroundColor = Color.FromHex("#008080"),
                TextColor = Color.White,
                Text = "Encerrar esta trilha"
            };
            // trata o evento Click
            btnCaminhadas.Clicked += (sender, e) =>
            {
                if (caminhadaItem == null) return;
                Navigation.PopToRootAsync(true);
                caminhadaItem = null;
            };
            this.Content = new ScrollView
            {
                Padding = 10,
                Content = new StackLayout
                {
                    Orientation = StackOrientation.Vertical,
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    Children = {
                                trilhaMapa,
                                nomeTrilhaLabel,
                                distanciaCaminhadaTrilhaLabel,
                                distanciaTotalPercorrida,
                                tempoTotalGastoLabel,
                                tempoTotalGasto,
                                btnCaminhadas
                                }
                }
            };
        }
    }
}

Cadastrando uma nova Trilha na página :  CaminhadaInfoPage.cs

Para incluir uma nova trilha registrando suas informações vamos criar a página CaminhadaInfoPage.cs.

Abra essa página e inclua o código abaixo:

using Xamarin.Forms;
namespace XFCaminhadas
{
    public class CaminhadaInfoPage : ContentPage
    {
        public CaminhadaInfoPage()
        {
            // Define o titulo da pagina
            Title = "Nova Caminhada";
            // Define os campos da nova caminhada
            var caminhadaTitulo = new EntryCell
            {
                Label = "Titulo:",
                Placeholder = "Titulo da Trilha"
            };
            var caminhadaNotas = new EntryCell
            {
                Label = "Notas:",
                Placeholder = "Descricao"
            };
            var caminhadaLatitude = new EntryCell {Label = "Latitude:",Placeholder = "Latitude",Keyboard = Keyboard.Numeric};
            var caminhadaLongitude = new EntryCell{Label = "Longitude:",Placeholder = "Longitude",Keyboard = Keyboard.Numeric};
            var caminhadaKilometros = new EntryCell{Label = "Quilometros:",Placeholder ="Kilometros",Keyboard = Keyboard.Numeric};
            var caminhadaDificuldade = new EntryCell{Label = "Nível Dificuldade:",Placeholder ="Caminhada Dificuldade"};
            var caminhadaImageUrl = new EntryCell{Label = "ImageUrl:",Placeholder ="URL da Imagem"};
            
            // Define nossa TableView
            Content = new TableView
            {
                Intent = TableIntent.Form,Root = new TableRoot
                {
                    new TableSection(){
                        caminhadaTitulo,
                        caminhadaNotas,
                        caminhadaLatitude,
                        caminhadaLongitude,
                        caminhadaKilometros,
                        caminhadaDificuldade,
                        caminhadaImageUrl
                }}};
            var salvarCaminhadaItem = new ToolbarItem
            {
                Text = "Salvar"
            };
            salvarCaminhadaItem.Clicked += (sender, e) =>
            {
                Navigation.PopToRootAsync(true);
            };
            ToolbarItems.Add(salvarCaminhadaItem);
        }
    }
}

E é só isso...

Vimos que podemos definir toda a interface, tratamento de eventos via Código C# sem usar código XAML.

Uma melhor prática seria definir a interface no código XAML e usar MVVM para remover todo o código da interface dos arquivos code-behind.

Como eu disse o projeto ainda não esta completo precisamos incluir funcionalidades para definir o tempo gasto na trilha , a distância percorrida e outros recursos. Fica como um exercício...

Pegue o código do projeto portable aqui :  XFCaminhadas.zip (sem as referências)

"E estava ali um homem que, havia trinta e oito anos, se achava enfermo.Jesus disse-lhe: Levanta-te, toma o teu leito, e anda.Logo aquele homem ficou são; e tomou o seu leito, e andava. E aquele dia era sábado."
João 5:5-9

Referências:


José Carlos Macoratti