Aplicaciones bonitas con Xamarin Forms | Pt. 1

Aplicaciones bonitas con Xamarin Forms

Hace algunos días un developer me escribió y me contaba que Xamarin forms era asombroso que para el las aplicaciones era algo feas en cuanto a la UI, yo le respondí y le dije que si se puede solo que se necesita un poquito más de esfuerzo. Pues en la play store o en cualquiera de las tiendas se engancha mucho mas rápido al futuro usuario de nuestra app si tiene una interfaz atractiva y amigable.

Que necesito para comenzar ?

1) Visual Studio 2015 Community (gratis  o una version superior ) o Visual Studio for MAC.

Vamos a hablar de interfaces bonitas

 

XFParallax by DevsDNA

Super pero que es XFParallax by DevsDNA, pues XFParallax by DevsDNA busca implementar el muy popular efecto efecto Parallax muy famoso en la plataforma ios.

Pero Yhorby que te digo que quiero hacer apps bonitas en Xamarin Forms, calma colega que se puede implementar en Xamarin forms.

Como lo hago?

Pues puedes encontrar un proyecto de ejemplo en su repositorio de Github aquí. 

Con esta librer√≠a podemos crear el efecto¬†parallax en las tres plataformas : Android, iOS and Windows ‚Äď con ¬†Xamarin Forms

Pasamos a explicar como funciona la librería.

1. Primero debemos crear ¬†el codigo responsable para crear¬†¬†la vista efecto parallax . Creamos un¬†nuevo ‚ÄúContentView‚ÄĚ llamado ‚ÄúParallaxView‚ÄĚ:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DevsDNA.XFParallax.ParallaxView">
  <ContentView.Content>
    <Grid>
      <ContentView x:Name="Header" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" BackgroundColor="Blue"/>
      <ScrollView x:Name="ParentScroll" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
        <ContentView x:Name="Body"/>
      </ScrollView>
    </Grid>
  </ContentView.Content>
</ContentView>

2. EL Code behind para ‚ÄúParallaxView.xaml.cs‚ÄĚ deberia lucir como este :

namespace DevsDNA.XFParallax
{
    using Xamarin.Forms;
 
    public partial class ParallaxView : ContentView
    {
        private double lastScroll = 0;
 
        public static readonly BindableProperty HeaderContentProperty = BindableProperty.Create(nameof(HeaderContent), typeof(ContentView), typeof(ParallaxView), coerceValue: HeaderContentCoerceValue);
        public static readonly BindableProperty HeaderScrollSpeedProperty = BindableProperty.Create(nameof(HeaderScrollSpeed), typeof(int), typeof(ParallaxView), 2);
        public static readonly BindableProperty BodyContentProperty = BindableProperty.Create(nameof(BodyContent), typeof(ContentView), typeof(ParallaxView), coerceValue: BodyContentCoerceValue);
        public static readonly BindableProperty BodyMarginProperty = BindableProperty.Create(nameof(BodyMargin), typeof(Thickness), typeof(ParallaxView), new Thickness(0), coerceValue: BodyMarginCoerceValue);
 
        public ParallaxView()
        {
            InitializeComponent();
            ParentScroll.Scrolled += ParentScroll_Scrolled;
        }
 
        public ContentView HeaderContent
        {
            get { return (ContentView)GetValue(HeaderContentProperty); }
            set { SetValue(HeaderContentProperty, value); }
        }
 
        public int HeaderScrollSpeed
        {
            get { return (int)GetValue(HeaderScrollSpeedProperty); }
            set { SetValue(HeaderScrollSpeedProperty, value); }
        }
 
        public ContentView BodyContent
        {
            get { return (ContentView)GetValue(BodyContentProperty); }
            set { SetValue(BodyContentProperty, value); }
        }
 
        public Thickness BodyMargin
        {
            get { return (Thickness)GetValue(BodyMarginProperty); }
            set { SetValue(BodyMarginProperty, value); }
        }
        /// 
        <summary>
        /// Important to call this method from Page OnDissapearing to remove event handlers and avoid memory leaks.
        /// </summary>
 
        public void DestroyParallaxView()
        {
            ParentScroll.Scrolled -= ParentScroll_Scrolled;
        }
 
        private static object HeaderContentCoerceValue(BindableObject bindableObject, object value)
        {
            if (bindableObject != null && value != null && value is ContentView)
            {
                ParallaxView instance = (ParallaxView)bindableObject;
 
                instance.Header.Content = (ContentView)value;
            }
            return value;
        }
 
        private static object BodyContentCoerceValue(BindableObject bindableObject, object value)
        {
            if (bindableObject != null && value != null && value is ContentView)
            {
                ParallaxView instance = (ParallaxView)bindableObject;
 
                instance.Body.Content = (ContentView)value;
 
                if (instance.BodyMargin != null)
                {
                    instance.Body.Margin = instance.BodyMargin;
                }
            }
            return value;
        }
 
        private static object BodyMarginCoerceValue(BindableObject bindableObject, object value)
        {
            if (bindableObject != null && value != null && value is Thickness)
            {
                ParallaxView instance = (ParallaxView)bindableObject;
 
                if (instance.Body != null)
                {
                    instance.Body.Margin = instance.BodyMargin;
                }
            }
            return value;
        }
 
        private void ParentScroll_Scrolled(object sender, ScrolledEventArgs e)
        {
            if (lastScroll == 0)
                lastScroll = e.ScrollY;
            else
            {
                CalculateHeaderTranslation(e);
            }
        }
 
        private void CalculateHeaderTranslation(ScrolledEventArgs e)
        {
            double translation = 0;
 
            if (lastScroll < e.ScrollY) { translation = 0 - ((e.ScrollY / HeaderScrollSpeed)); if (translation > 0)
                    translation = 0;
            }
            else
            {
                translation = 0 + ((e.ScrollY / HeaderScrollSpeed));
                if (translation > 0)
                    translation = 0;
            }
            Header.TranslateTo(Header.TranslationX, translation);
            lastScroll = e.ScrollY;
        }
    }
}

3. Ahora podemos usar Parallax en una de nuestras  Content Pages, como se muestra a  continuación:

<?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:DevsDNA.XFParallax.Sample" xmlns:parallax="clr-namespace:DevsDNA.XFParallax;assembly=DevsDNA.XFParallax" x:Class="DevsDNA.XFParallax.Sample.MainPage">
 
  <parallax:ParallaxView x:Name="MainParallax" BodyMargin="0,180,0,0" HeaderScrollSpeed="4">
    <parallax:ParallaxView.HeaderContent>
      <ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="Blue">
        <Image Source="https://www.windowscentral.com/sites/wpcentral.com/files/styles/large/public/field/image/2016/02/microsoft-xamirin.jpg?itok=M_JRL3qE" Aspect="AspectFill" VerticalOptions="Start"/>
      </ContentView>
    </parallax:ParallaxView.HeaderContent> 
    <parallax:ParallaxView.BodyContent>
      <ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="White" HeightRequest="500">
        <ContentView.Margin>
          <!-- need to add specific margin to Windows to show header.-->
          <OnPlatform x:TypeArguments="Thickness" WinPhone="0,180,0,0"/>
        </ContentView.Margin>
        <Grid BackgroundColor="White">
                    <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition />
                </Grid.RowDefinitions>
                     
                <Image HorizontalOptions="Center" VerticalOptions="Start" Margin="0,-50,0,0" HeightRequest="100" WidthRequest="100" Grid.Row="0" Source="http://students.stmaryschs.org.uk/Y9_Scratch_To_VB/images/VS_Logo.png" Aspect="AspectFit"/>
                <Label Text="Xamarin Parallax Effect!" Grid.Row="1" HorizontalOptions="Center"/>
                     
        </Grid>
      </ContentView>
    </parallax:ParallaxView.BodyContent>
  </parallax:ParallaxView>
 
</ContentPage>

4. Ahora en el ¬†code behind invocamos¬†‚ÄúDestroyParallaxView‚ÄĚ en el m√©todo llamado ¬†MainParallax¬†en el metodo ‚ÄúOnDisappearing‚ÄĚ :

public partial class MainPage : ContentPage
  {
      public MainPage()
      {
          InitializeComponent();
      }
 
      protected override void OnDisappearing()
      {
          base.OnDisappearing();
          // To avoid memory leak:
          MainParallax.DestroyParallaxView();
      }
  }

Y así es como tenemos el hermoso efecto Parrallax en nuestra aplicacion Xamarin Forms.

Quieres verlo funcionando ?

Ejecuta tu codigo y dejame saber que tal !!

Cualquier duda o comentario puedes escribirme o dejar un comentario en la entrada !

Xamarin.Forms | Eliminar margenes entre Grids

Xamarin.Forms es una gran ayuda a la hora de desarrollar aplicaciones para las tres principales plataformas móviles (Windows, iOS y Android), pero aveces si no ponemos atencion se nos escapan algunas cositas. Por ejemplo con los Grids, ya que la interpretación que hace para cada una de las plataformas de los controles es muy distinta y por defecto para iOS y Android deja un espacio entre las Grids.

Porque pasa esto ?

Pues porque no hemos indicado el padding a las celdas.

Como resolverlo ?

Para resolver este ‚Äúproblema‚ÄĚ tan s√≥lo tienes que hacer uso de una propiedad de los Grids, ‚ÄúRowSpacing‚ÄĚ

como muestra el siguiente code

<Grid RowSpacing="0">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>;
    </Grid.RowDefinitions>
    <Label Grid.Row="0" Text="Item 1" />
    <Label Grid.Row="1" Text="Item 2" />
    <Label Grid.Row="2" Text="Item 3" />
</Grid>

as√≠ solucionamos ¬†el problema¬†en las tres plataformas y conseguiremos¬†pr√°cticamente la ‚Äúmisma‚ÄĚ visualizaci√≥n en todas las plataformas; dependiendo de los controles que pongas como contenido de cada una de las celdas del Grid.

Concatenar string en un Binding XAML Xamarin Forms

Saludos en esta entrada trabajaré con XAML y XAMARIN FORMS

Imaginemos que tenemos el siguiente código XAML:

<Label Text = "${Binding Price}"
       x:Name = "artPrice"
       HorizontalOptions = "Center"
       VerticalOptions = "Center"
      />

Y queremos que como resultado ese label muestre algo como esto:

$50

pero como resultado cuando ejecutemos nuestra aplicación obtenemos esto:

"${Binding Price}"

Para obtener el resultado deseado nuestro codigo XAML debe estar asi :

<Label Text = "{Binding Price, StringFormat='${0}'}"
       x:Name = "artPrice"
       HorizontalOptions = "Center"
       VerticalOptions = "Center"
      />

Y cuando ejecutemos nuestro label mostrara correctamente el string concatenado y el dato bindeado.

$50

Si tienes alguna duda o alg√ļn comentario, h√°zmelo saber deja un comentario aca.