Twitter is an excellent place for inspiration, and when I saw that David Barnes had remixed some of my favorite technologies into a fun demo, I knew I had to give it a try. David has taken emojis, HTML, and CSS animations and created an animated mic drop. I highly suggest you read his blog post and try out his sample.

In this post, we’ll be recreating the mic drop animation, but within a cross-platform application using Xamarin.Forms and the included animation methods. Additionally, all the work here was done within JetBrains Rider, a cross-platform IDE, and I highly recommend you check it out.

What We’re Working Towards

Our goal is to create an application that runs on both iOS and Android mobile devices. We’ll start with a screen that shows the closed fist (👊) emoji holding a microphone (🎤). When we click the hand, it will display the open hand (🖐) emoji followed by the microphone dropping. Here is the final app running in the iOS simulator.

Mic Drop in iOS and Android

Are we ready to build it? Let’s Go! If you’re an impatient one, you can download the solution from my GitHub repository.

Application Resources in App.xaml

The first iteration of the application had every property and variable hardcoded in C#. While workable, it can slow down the feedback loop of developing, and more importantly, suck the joy out of experimenting. To foster a developer’s free spirit, we can put many of these variables in the Application.Resources collection. In App.xaml, we place values that we’ll use later in our MainPage.xaml.

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:System="clr-namespace:System;assembly=mscorlib"
             x:Class="MicDrop.App">
    <Application.Resources>
            <System:String x:Key="CloseTitleText">MIC Drop?</System:String>
            <System:String x:Key="OpenTitleText">💥Boom!💥</System:String>
            <System:String x:Key="CloseHandEmoji">👊</System:String>
            <System:String x:Key="OpenHandEmoji">🖐</System:String>
            <System:String x:Key="MicEmoji">🎤</System:String>
            <System:Double x:Key="TitleScale">1.25</System:Double>
            <System:Double x:Key="Bottom">50</System:Double>
            <System:UInt32 x:Key="AnimationLength">3000</System:UInt32>
            <System:UInt32 x:Key="MaxRotation">720</System:UInt32>
    </Application.Resources>
</Application>

Setting System variables is a neat trick for XAML. Note the reference to mscorlib in the Application tag. The definition allows us to instantiate String, Double, and UInt32 tags that hold our values.

We must put these values in our App.xaml if we want Xamarin.Forms Hot Reload to work. I found that resources located on components were causing exceptions around duplicate keys in the resource dictionary.

The Layout in MainPage.xaml

The next step is to create our layout. There are likely many ways to do this, but using Grid was more natural to conceptualize.

<?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:MicDrop"
             x:Class="MicDrop.MainPage">
    
    <Grid x:Name="canvas">
        <!-- Place new controls here -->
        <Label 
            Grid.Row="0"
            x:Name="title"
            VerticalOptions="StartAndExpand"
            HorizontalOptions="CenterAndExpand"
            FontSize="40"
            FontAttributes="Bold"
            Padding="0, 200, 0, 0"
            Text = "{StaticResource CloseTitleText}">
        </Label>
        <Label x:Name="mic"
               Grid.Row="0"
               Text="{StaticResource MicEmoji}"
               Rotation="45"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               VerticalTextAlignment="End"
               FontSize="100"
               IsVisible="True"
        ></Label>
        <Button Text="{StaticResource CloseHandEmoji}"
                Grid.Row="0"
                x:Name="hand"
                BackgroundColor="Transparent"
                FontSize="100"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="OnMicDrop"
        />
    </Grid>
</ContentPage>

Take note of the features in our XAML:

  • We are referencing the StaticResource values mentioned in App.xaml.
  • We’ve placed everything in the same row/column within the Grid.
  • We set some properties to create the best experience across Android and iOS, such as BackgroundColor="Transparent" on the hand button.

Our UI is as simple as it gets.

The C# Code To Drop The Mic

The next step is to handle our mic drop animation. First, we need to reference our application resources. For brevity, let’s look at the OpenTitleText property and how we can access its value.

public string OpenTitleText => Application.Current.Resources[nameof(OpenTitleText)] as string;

We will have the rest of our resource values this way in our MainPage.xaml.cs file. This access pattern will allow us to change values and participate in the Hot Reload features provided by Xamarin.Forms.

Now, let’s see how we implement the animation.

private async void OnMicDrop(object sender, EventArgs e)
{
    if (!_holding) return;
    
    _holding = false;
    hand.Text = OpenHandEmoji;
    title.Text = OpenTitleText;

    canvas.RaiseChild(mic);

    await Task.WhenAll(
        title.ScaleTo(title.Scale * TitleScale, easing: Easing.CubicInOut),
        mic.RotateTo(Rng.Next(1, (int) MaxRotation), AnimationLength, easing: Easing.SinInOut),
        mic.TranslateTo(0, (Height/ 2) - Bottom, AnimationLength, easing: Easing.BounceOut)
    );

    await mic.FadeTo(0);
    
    hand.Text = CloseHandEmoji;
    title.Text = CloseTitleText;
    
    // reset location
    await Task.WhenAll(
        title.ScaleTo(title.Scale / TitleScale, easing: Easing.CubicInOut),
        mic.TranslateTo(0, 0, 0, Easing.Linear),
        mic.RotateTo(45, 0, Easing.Linear),
        mic.FadeTo(1, 0)
    );

    canvas.RaiseChild(hand);
    
    _holding = true;
}

Let’s look at the essential parts of this code:

  • We are using a _holding variable, do make sure an individual can’t initiate the mic drop multiple times.
  • We are using our resource values as we intended.
  • We make a call to RaiseChild which allows us to change the visual stacking order of our elements. In this case, the microphone will go from behind the hand, to in front of it.
  • We can run animations simultaneously using Task.WhenAll, with each animation having its parameters and easing option.
  • When we reach the end of our animation, the mic fades, and we reset our canvas to the initial state.

Let’s look at the sample running again.

Mic Drop in iOS and Android

“💥Boom!💥” indeed. If you want to try running this app, please go to my GitHub repo and clone the solution.

Conclusion

In a previous post, I used motion graphics to add a visual flair to Xamarin.Forms. For those without the resources or desire to work with motion graphics, the built-in Xamarin.Forms animation methods provide a no-frills default. Combining emojis, animations, and layout concepts, we can create a fun little demo cross-platform app.

What are your thoughts? What would you do differently? Would you buy this app (just kidding)? Please let me know in the comments.