Beautiful Xamarin – Facebook Clone in Xamarin.Forms

I’ve actually had this project around since this start of the year but I never blogged it. I did this code for my speaking session at Microsoft Ignite in Australia.

Warning – This code is a playground there’s lots of play code and not reflective of a production application. This project is for only used for learning about Xamarin.Forms features.

In this blog post I’ll go over some of the features want to demo with this app, with some screenshots. Over the coming weeks I plan to demonstrate that anyone who says you cannot build fast and beautiful apps in Xamarin.Forms is simply wrong, lying or ignorant. The deal is that you just need to know how Xamarin.Forms work.

Post-Layout Animations/Translations – Right Slide Bar

One of the most powerful features of Xamarin.Forms are the Post-Layout translations. fbforms-sidebar

People are so surprised when I tell them this is done without any custom renders, let’s take a look at how.

In this case I make use of the Grid in Xamarin.Forms, in actual fact the sidebar is layered over the listview which in the background. The Grid only has a single column.

<Grid>
  <FriendList ... (300 Set Width)
  <Header ...(Full Screen Width)
  <ListView ...(Full Screen Width)
</Grid>

So the FriendList normally sits on top of the List but what we actually do is translate the X coordinate so it sits off the screen, just after the page size allocated.

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height);

    friendList.TranslationX = this.Width;
}

Then the awesomely simple part, when a user taps the menu button we just translate the views.

void FriendListTapped(object sender, System.EventArgs e)
{
    if (friendList.TranslationX == Width) // determine if open
    {
        friendList.TranslateTo(Width - 300, 0, 100); //open the friendlist
        myListView.TranslateTo(-300, myListView.TranslationY, 100); //move the listview to allow for friendlist
        header.TranslateTo(-300, header.TranslationY, 100); //move the header to allow for friendlist
    }
    else
    {
        friendList.TranslateTo(Width, 0); //close the friendlist
        header.TranslateTo(0, header.TranslationY, 100); //put the header back
        myListView.TranslateTo(0, myListView.TranslationY, 100);  //put the listview back
    }
}

Disappearing NavigationBar

This one was a little harder and it’s still not working perfectly.

fbforms-navigationbar

In this case our grid has 2 rows, 80 at the top for the header size and a * for the rest.

<Grid.RowDefinitions>
    <RowDefinition Height="80"></RowDefinition>
    <RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>

On the default state the header just sits in the first row.

<Grid x:Name="header" BackgroundColor="{StaticResource BlueHeaderColor}" >

While the ListView actually uses the Grid.RowSpan=”2″ so it goes over multiple rows, I had to do this because the height of the listview needs to be the full height of the screen once the header disappears. I also make use of the ability to set post-layout values in Xaml, setting the TranslationY to 60 on the ListView (this moves it down into the correct position by default).

<local:AdvancedListView BackgroundColor="#D7DBDF" HasUnevenRows="true" TranslationY="60" Grid.RowSpan="2" 			
        x:Name="myListView" 
		ItemsSource="{Binding Items}" ItemTemplate="{StaticResource homeWallListTemplateSelector}" 
		SeparatorVisibility="None"
		> 
</local:AdvancedListView>

So when we want to hide the navigation bar we must hook into the Scrolled event on the listview and translate the Y values on the views depending on the scroll position. This part is really just for a demo, it’s not thought out and very prototype.

void MyListView_Scrolled(Point obj)
{
    var headerHeight = 60;

    if (obj.Y <= 0)
    {
        header.TranslationY = 0;
        myListView.TranslationY = headerHeight;
    }
    else if (obj.Y <= headerHeight)
    {
        header.TranslationY = -obj.Y;
        myListView.TranslationY = -obj.Y + headerHeight;
    }
    else if (obj.Y > headerHeight) //scrolled 
    {
        header.TranslationY = -headerHeight;
        myListView.TranslationY = 0;
    }
}

Like Animations

One other thing I like about this app is the animated likes buttons.

fbforms-like

In this case I cheated a little bit and used a Animated Gif, it worked ok. I also used a few other features.

As with all the other cases I leveraged the Grid. You’ll also notice that I used a few extra controls, AdvancedFrame from FreshEssentials to allow for the rounded edges and a GifImageViewControl.

<ContentView Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="4" x:Name="likeArea"  Opacity="0">
    <fe:AdvancedFrame Padding="15, 4" HasShadow="true" OutlineColor="#EEEEEE" CornerRadius="70" Corners="all"  InnerBackground="White"  >
        <local:GifImageViewControl  Aspect="AspectFill" Source="facebookreactionsanimation.gif"></local:GifImageViewControl>
    </fe:AdvancedFrame>
</ContentView>

As with all the other samples we simply leverage some Translations and in this case we also leveraged the FadeTo animation.

async void Handle_Clicked(object sender, System.EventArgs e)
{
    if (likeArea.TranslationY == -35)
    {
        await likeArea.TranslateTo(0, 0, 100, Easing.Linear);
        await Task.Delay(50);
        await likeArea.FadeTo(0, 50);
    }
    else
    {
        await likeArea.FadeTo(1d, 20);
        await likeArea.TranslateTo(0, -35, 100, Easing.Linear);
    }
}

If you want to check out the code base please find it here: https://github.com/XAM-Consulting/FacebookForms

Thanks

 

Leave a Reply