Beautiful Xamarin Apps

Beautiful Xamarin Apps

Short introduction

When creating mobile application developer should not only think about functionality. Of course this is crucial element but there is also one more important element – design. There are so many applications in stores so you have to interest potencial user. Screenshots are visible before someone download your application. Besides that users like applications with great functionality and nice look. With Xamarin you are able to create native mobile apps with beautiful look and that is why I decided to write this article and show some great tools to achieve that.

What do I need to start?

1) Visual Studio 2015 Community (for free or choose higher version) or Visual Studio for MAC

 

Let’s start

 

XFParallax by DevsDNA

Parallax effect – very popular on iOS platform. What about Xamarin Forms? You can achieve it with DevsDNA’s Parallax!

There is whole sample available on DevsDNA GitHub.

With this library you can create parallax effect on three platforms: Android, iOS and Windows – with single Xamarin Forms.

1. First of all you need code responsible for creating parallax view. Create new “ContentView” called “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. Code behind for “ParallaxView.xaml.cs” file should look like below:

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. Now you can use Parallax in one of your Content Pages 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" 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. In code behind there has to be “DestroyParallaxView” method called on MainParallax in “OnDisappearing” method:

  public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnDisappearing()
        {
            base.OnDisappearing();
			// To avoid memory leak:
            MainParallax.DestroyParallaxView();
        }
    }

That’s it! Now you have beautiful parallax effect in you Xamarin application.

 

Animations with Lottie for Xamarin

Animations are strong advantage when talking about design and user experience. Your application is much more attractive with beautiful and smoth animations. That’s why Lottie animation framework was created. Thanks to Xablu and its Xamarin Consultant – Martijn van Dijk there is Lottie for Xamarin library.

Below I collected the most important information you should know:

 

You can find great samples on LottieXamarin GitHub.

For this article I would like to discuss one simple animation sample for Xamarin Forms application.

1. Download sample app from GitHub above.

2. Open it in Visual Studio or Xamarin Studio

3. Open “Example.Forms” folder

4. Open “MainPage.xaml” file. As you can see below there is “AnimationView” object used to generate animation from JSON file:

  <forms:AnimationView 
   x:Name="AnimationView" 
   Animation="LottieLogo1.json" 
   Loop="True" 
   AutoPlay="True" 
   VerticalOptions="FillAndExpand" 
   HorizontalOptions="FillAndExpand" />

Note that animation JSON has to be placed in selected place:

  • On Android in Assets folder in solution (or other folder but then you have to provide specific path to it)
  • On iOS it has to be placed in project main root (or other folder in “Resources” but then you have to provide specific path to it)

Xamarin Forms Tab Badge

It is worth to mention great sample created by xabre connected with tab badges on iOS and Android. It is available on GitHub here.

You can change text of your badges and also color:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:plugin="clr-namespace:Plugin.Badge.Abstractions;assembly=Plugin.Badge.Abstractions" x:Class="Plugin.Badge.Sample.TabXaml">
  <TabbedPage.Children>
    <ContentPage Title="Tab1" Icon="icontab1.png" 
     plugin:TabBadge.BadgeText="{Binding Count}"
     plugin:TabBadge.BadgeColor="{Binding Color}">
      <StackLayout>...</StackLayout>
    </ContentPage>
    ...
  </TabbedPage.Children>
</TabbedPage>

You have of course full access from C# code too.

This library is available via NuGet: Tab Badge for Xamarin.Forms.

 

Sum up

As you can see there are many great samples and libraries to enhance you Xamarin application design. Of course in this article I did not include all of them but it is worth to follow Xamarin community news to get information about latest libraries. Now lets create some beautiful Xamarin apps!

Advertisements