sábado, 28 de marzo de 2020

Xamarin.Forms - Crear Menú Hamburguesa

En este post elaboraremos un ejemplo práctico acerca del desplazamiento que se realiza después de autentificarse el ingreso a una aplicación móvil, es decir se implementará el menú principal para determinar las opciones de nuestra aplicación móvil.

Sin mayores detalles, como se describe en el titulo de este post se creará el  menú hamburguesa 🍔 (no me gusta ese nombre 😂), con relación a la aplicación móvil que se viene desarrollando. Como se menciono en los anteriores ejemplos prácticos, será diseñada y desarrollada en Xamarin.Forms con almacenamiento de datos en SQLite. 

Te puede interesar 👀 las anteriores 😃 secuencias:


Recordemos que todas las pruebas se viene realizando en un equipo móvil físico con Sistema Operativo Android, esto no restringe el uso de emuladores.

Requisitos:
Microsoft Visual Studio Community 2019.
Xamarin.Froms - XAML.
SQLite - Gestión de datos local.

Comencemos:
En el directorio Views del proyecto AppDIAbetes agregamos una nueva Pagina de Contenido:
Clic en agrear nuevo elemento desde el directorio Views, seleccionar la opción Página de Contenido, asignar nombre y clic en agregar.
En el directorio Models del proyecto AppDIAbetes agregamos una nueva Clase:
Clic en agrear nuevo elemento desde el directorio Models, seleccionar la opción Clase, asignar nombre y clic en agregar.
Recordemos que también se puede realizar haciendo uso de la creación de una Página de maestro y detalles, sin embargo esto al crearse adicionaran otras páginas y una clase que complementa para la implementación de la opción. Si desea puedes revisar en nuevo proyecto y adicionar al nuevo proyecto el elemento en mención.
Clic en agrear nuevo elemento desde el proyecto creado, seleccionar la opción
Página de maestro y detalles, asignar nombre y clic en agregar.
Archivos .xaml agregados y el .cs que corresponde a los atributos
Ahora bien, con los 2 nuevos componente (Pagina de Contenido y Clase) agregados en nuestro proyecto se iniciará con la elaboración y ejecución de la parte de diseño de interfaz.

Diseño de Interfaz:
Abrimos los archivos PageMain.xaml y PageMain.xaml.cs (no equivocarse con la MainPage.xaml ) y cambiamos el ContentPage por MasterDetailPage.

Es decir el PageMain.xaml debe quedar por ahora de la siguiente manera:

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="AppDIAbetes.Views.PageMain">
    <MasterDetailPage.Master>
        <ContentPage>
            <StackLayout>
                <Label Text="Welcome to Xamarin.Forms!"
                    VerticalOptions="CenterAndExpand"
                    HorizontalOptions="CenterAndExpand" />
            </StackLayout>
        </ContentPage>
    </MasterDetailPage.Master>

</MasterDetailPage>

Y el PageMain.xaml.cs debe quedar por ahora del siguiente modo:

    public partial class PageMain : MasterDetailPage
    {
        public PageMain()
        {
            InitializeComponent();
        }
    }

Con los cambios realizados, implementaremos las lista de opciones a mostrar en el PageMain.xaml, para la cual agregaremos un ContentPage e insertamos un Grid y su Grid.RowDefinitions, dos secciones con StackLayout, de las cuales uno determinará la cabecera del menu (donde estará el logo y fondo) y por ultimo la otra sección determinara la lista de opciones por intermedio de un ListView.

La propiedad ImageCell del ListView contendrá valor con valores de tipo Binding para la asignación a la entidad de datos:

<ImageCell TextColor="#3399ff" DetailColor="#AED6FF"
           Text="{Binding title}"
           Detail="{Binding detail}"
           ImageSource="{Binding image}">
</ImageCell>

El XAML completo del archivo PageMain.xaml

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="AppDIAbetes.Views.PageMain">
    <MasterDetailPage.Master>
        <ContentPage Title="masterPage">
            <Grid BackgroundColor="Transparent">
                <Grid.RowDefinitions>
                    <RowDefinition Height="200" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid>
                    <Image Source="fondoDIAbetes.jpg" Aspect="AspectFill" WidthRequest="200" />
                    <StackLayout Padding="0,20,0,0" HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
                        <Image Source="DIAbetes.gif"></Image>
                        <Label Text="Buen día Hadson" TextColor="Black" FontSize="Small" HorizontalTextAlignment="Center" />
                    </StackLayout>
                </Grid>
                <StackLayout Margin="0,0,0,0" Grid.Row="1" Spacing="0">
                    <ListView x:Name="listPageMain" ItemSelected="OnListItemSelected" BackgroundColor="White" SeparatorColor="Gray">
                        <ListView.ItemTemplate>
                            <DataTemplate>                               
                                <ImageCell TextColor="#3399ff" DetailColor="#AED6FF"
                                            Text="{Binding title}"
                                            Detail="{Binding detail}"
                                            ImageSource="{Binding image}">
                                </ImageCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackLayout>
            </Grid>           
        </ContentPage>
    </MasterDetailPage.Master>
</MasterDetailPage>

Luego agregaremos los siguiente atributos en la clase Option que fue creado inicialmente:

using Xamarin.Forms;

namespace AppDIAbetes.Models
{
    public class Option
    {
        public string title { get; set; }
        public string detail { get; set; }
        public ImageSource image { get; set; }
        public Page page { get; set; }
    }
}

Después de realizar el diseño de Interfaz y CodeBehind, nuestro Menú Hamburguesa quedara de la siguiente manera:


Desarrollo en el CodeBehind:
En CodeBehind del archivo PageMain.xaml.cs crearemos 2 métodos para logra el desplazamiento en el menú:

El método myPageMain es el encargado de listar y almacenar los datos de cada atributo de la entidad Options para alimentar a al ListView, y por ultimo el segundo método OnListItemSelected se encarga de seleccionar la página de acuerdo a los atributos de cada página carga en el ListView:

using AppDIAbetes.Views.Options;
using AppDIAbetes.Models;
using System.Collections.Generic;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace AppDIAbetes.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class PageMain : MasterDetailPage
    {
        public PageMain()
        {
            InitializeComponent();

            NavigationPage.SetHasNavigationBar(this, false);
            myPageMain();
        }

        public void myPageMain() {
            Detail = new NavigationPage(new PageHome());

            List<Option> options = new List<Option>
            {
                new Option{ page=new PageHome(),title="Inicio", detail="Inicio", image = "ic_ac_home.png" },
                new Option{ page=new PageControl(),title="Monitoreo y Control", detail="Programación de control", image = "ic_ac_control.png" },
                new Option{ page=new PageReport(),title="Mis Reportes", detail="Reportes seamanales", image = "ic_ac_report.png" },
                new Option{ page=new PageRegistry(),title="Ingreso Manual", detail="Ingresa tu monitoreo", image = "ic_ac_registry.png" },
                new Option{ page=new PageAbout(),title="Acerca de", detail="App DIAbetes", image = "ic_ac_about.png" },
                new Option{ page=null,title="Cerrar Sesión", detail="Abandonar App", image = "ic_ac_signoff.png" }
            };
            listPageMain.ItemsSource = options;
        }
        private async void OnListItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            var option = e.SelectedItem as Option;
            if (option.page != null)
            {
                IsPresented = false;
                Detail = new NavigationPage(option.page);
            }
            else if (option.page == null || option.title == "Cerrar Sesión") {

                var result = await DisplayAlert("Confirmar", "Estas seguro de cerrar sesión", "SI", "NO");
                if (result)
                {
                    await Navigation.PushAsync(new MainPage());
                }
                else
                {
                    return;
                }
            }
        }
    }
}

Antes de implementar el método myPageMain se debe crear un sub directorio de nombre Options en el directorio Views y agregar las siguientes Paginas de Contenido:
👉 PageHome.xaml
👉 PageControl.xaml
👉 PageReport.xaml
👉 PageRegistry.xaml
👉 PageAbout.xaml

Así mismo, debe agregar las imágenes en sub directorio drawable que se encuentra en el directorio Resources del proyecto de AppDIAbetes.Android:


 Para finalizar comparto el vídeo 📹 acerca de lo desarrollado de acuerdo a la descripción de este post publicado, todas las pruebas fueron validados en plataforma 📱 para Android.
Nuevamente gratitud a Dios 😊y gracias a todos ustedes por la acogida de este nuevo post, éxitos y bendiciones 🙏 y un gran abrazo a todos ✌...!!!

jueves, 26 de marzo de 2020

App - DÍAbetes

Normalmente todo el diseño y prototipo lo realizo con lápiz y papel, sé que existe muchas herramientas de las cuales podría hacer uso de ellos e ir construyendo todas las pantalla necesarias, pero, es fascinante cuando todo fluye mentalmente y se elabora los prototipos y flujo al mismo tiempo (claro está con lápiz y papel). 

Acerca de la aplicación:
La aplicación móvil esta elaborado en base a tecnología de Microsoft, como Xamarin.Forms, Xamarin.Essentials, SQLite y otras librerías que se ira mencionando durante todo el ciclo del desarrollo e implementación.

Descripción:
DÍAbetes es una aplicación móvil diseñada pensando en las personas con diabetes que necesitan llevar un registro y control diario de realizado por un glucómetro.

Necesidad:
Registrar el control deaacuerdo a tu necesidad y enviar la información a tu médico tratante. 

Estructura:
Componente:
Diseño y desarrollo:
Base de datos:
APIs y Librerías:
Cómo fue elaborado:

miércoles, 18 de marzo de 2020

Enviando correo con API de Xamarin.Essentials

En la API Xamarin.Essential de esta semana, echamos un vistazo a la API de (Email) correo electrónico que nos permitirá abrir la aplicación de correo electrónico predeterminada y precargada con destinatarios, asunto y cuerpo del mensaje. Para lo cual crearemos el proyecto Email.XEssential con Visual Studio 2019 que será nuestro primer ejemplo practico con Xamarin.Essential.

Requisitos para el ejemplo práctico:
Microsoft Visual Studio Community 2019
Xamarin.Froms - XAML
Xamarin.Essentials - API
Sistema cliente de envío - Gmail

Interfaz:
Después de haber creado el proyecto, iniciaremos con la parte del diseño para cual abriremos el archivo MainPage.xaml e ingresamos lo siguiente:

<?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:AwesomeApp"
             x:Class="AwesomeApp.MainPage">
    <StackLayout>
        <Image Source="HadsonparLogo.jpg"
               HorizontalOptions="Center"
               Margin="10"/>
        <Label Text="Visiten el Blog"
               TextColor="Blue"
               TextDecorations="Underline"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               FontSize="Title">
            <Label.GestureRecognizers>
                <TapGestureRecognizer Command="{Binding TapCommand}"           CommandParameter="http://blog.hadsonpar.com/" />
            </Label.GestureRecognizers>
        </Label>
        <Label Text="&#128526;"
               HorizontalOptions="Center"
               FontSize="Title"/>
        <Label Text="Publicamos temas acerca de las siguientes tecnologías:"
               HorizontalOptions="Center"/>
        <Label Text="ORACLE | MICROSOFT | OPEN SOURCE | CLOUD"
               HorizontalOptions="Center"/>
        <Label Text="Pequeñas aplicaciones, pero de gran impacto &#128522;"
               TextColor="Turquoise"
               FontSize="Subtitle"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"/>

        <Label Text="&#127760; Enviar Correo electrónico &#10;API de Xamarin.Essentials"
               Margin="0,0,0,10"
               FontAttributes="Bold"
               FontSize="Small"
               TextColor="#36FF33"
               HorizontalTextAlignment="Center"/>

        <Entry x:Name="txtTo" Placeholder="tu-email@dominio.com" />
        <Entry x:Name="txtSubject" Placeholder="Asunto" />
        <Editor x:Name="txtBody" HeightRequest="50"/>
        <Button x:Name="btnSend" Text="Enviar" Clicked="btnSend_Clicked"/>
       
        <Label Text="&#128588; Welcome to Xamarin.Forms!"
            HorizontalOptions="Center"
            VerticalOptions="CenterAndExpand" />
        <Button Text="Click me" Clicked="Button_Clicked" />
    </StackLayout>
</ContentPage>

Por ahora nos concentramos en la siguientes propiedades:
<Entry x:Name="txtTo" Placeholder="tu-email@dominio.com" />
<Entry x:Name="txtSubject" Placeholder="Asunto" />
<Editor x:Name="txtBody" HeightRequest="50"/>
<Button x:Name="btnSend" Text="Enviar" Clicked="btnSend_Clicked"/>
Desarrollo de código:
Seguidamente abrir el archivo o clase MainPage.xaml.cs y agregamos la referencia Xamarin.Essentials en la clase en mención, así mismo creamos las siguientes instrucciones (tareas y métodos asíncronos):

using Xamarin.Essentials;

Ahora creamos una tarea asíncrona de nombre SendEmail(...) con los siguientes parámetros de entrada subject, body y recipients:

        /// <summary>
        /// Tarea asincrona para realizar el envío del mensaje
        /// </summary>
        /// <param name="subject">Asunto del email</param>
        /// <param name="body">Cuerpo del mensaje del email</param>
        /// <param name="recipients">Destinatarios</param>
        /// <returns></returns>
        private async Task SendEmail(string subject, string body, List<string> recipients)
        {
            try
            {
                //Propiedades del mensaje
                var message = new EmailMessage
                {
                    Subject = subject,
                    Body = body,
                    To = recipients,
                };

                //API que se encarga de abrir el cliente como el Gmail, Outlook u otros para realizar el envío del mensaje
                await Email.ComposeAsync(message);
            }
            catch (FeatureNotSupportedException fnsEx)
            {
                // Email is not supported on this device
                await DisplayAlert("Error", fnsEx.ToString(), "OK");
            }
            catch (Exception ex)
            {
                // Some other exception occurred
                await DisplayAlert("Error", ex.ToString(), "OK");
            }
        }

Luego crea la tarea asíncrona  ValidateForm(), encargado de validar las propiedades de envío de mensaje:

/// <summary>
        /// Validar las propiedades de la pantalla de envio de email
        /// </summary>
        /// <returns></returns>
        private async Task<bool> ValidateForm()
        {
            //Valida si el valor en el Entry txtTo se encuentra vacio o es igual a Null
            if (String.IsNullOrWhiteSpace(txtTo.Text))
            {
                await this.DisplayAlert("Advertencia", "El campo tu-mail es obligatorio.", "OK");
                return false;
            }
            else {
                //Valida que el formato del correo sea valido
                bool isEmail = Regex.IsMatch(txtTo.Text, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase);
                if (!isEmail)
                {
                    await this.DisplayAlert("Advertencia", "El formato del correo electrónico es incorrecto, revíselo e intente nuevamente.", "OK");
                    return false;
                }
            }

            //Valida si el valor en el Entry txtSubject se encuentra vacio o es igual a Null
            if (String.IsNullOrWhiteSpace(txtSubject.Text))
            {
                await this.DisplayAlert("Advertencia", "El campo Asunto es obligatorio.", "OK");
                return false;
            }

            //Valida si el valor en el Entry se encuentra vacio o es igual a Null
            if (String.IsNullOrWhiteSpace(txtBody.Text))
            {
                var res = await DisplayAlert("Advertencia", "Aún no se a ingresado el mensaje, esta seguro de enviarlo", "OK", "Cancel");
                if (res)//True si se preciona OK, se esta confirmado que el correo se enviará sin mensaje
                {
                    return true;
                }
                else
                {//False si se preciona Cancel, y se debe ingresar el mensaje a enviar
                    return false;
                }
            }
            return true;
        }

Para finalizar creamos el método btnSend_Clicked encargado de realizar en envío, previa invocación a la tarea de ValidateForm(), si la validación retorna verdadero (true) invocamos a la tarea SendEmail(...):

        /// <summary>
        /// Botón encargado de realizar en envío
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        async void btnSend_Clicked(object sender, System.EventArgs e)
        {
            if (await ValidateForm()) {
                List<string> toAddress = new List<string>();
                toAddress.Add(txtTo.Text);
                await SendEmail(txtSubject.Text, txtBody.Text, toAddress);
            }
        }

Resultado:
Comparto el vídeo 📹 acerca de lo desarrollado de acuerdo a la descripción de este post publicado, todas la pruebas a nivel de Diseño ✨ y CodeBehind C# 💬 fueron validados en plataforma 📱Android.


Mayor información disponible en:
👉 channel9.msdn.com
👉 docs.microsoft.com

Descarga la fuente de:
En proceso de carga...
Nuevamente agradecer 😊 de antemano a todos por la acogida de este nuevo post publicado, bendiciones 🙏 y fuerte 💪 abrazo...!!!