Tuesday, February 17, 2015

I must admit that I've kind of missed this whole animation thingy that Xamarin put into Xamarin Forms. I've used the Animation classes to animate single properties, but haven't really put any time into exploring the extension methods for the View class. (poorly documented here).

The animation extension methods lets you move, rotate and scale stuff with different duration and easing functions. Duration and easing are optional parameters that you can pass into each animation function. An easing is a function of the rate of change during an animation. For example the BounceIn easing will overshoot its target and "bounce back" to the value required. Hence, bounce...

Anyway, let's move through each function!

The sandbox

So I started out with a single button in a single XAML view. Centered in all directions and just perfect. I've totally ignored all MVVM stuff and directly referenced the button control by name (theButton).

Step one - Let's move it!

I added code in the code behind to handle the Click event (don't worry, we'll do it MVVM style later on in another post). This simply moves the button itself to a absolute position. You could of course move any other object that inherits from VisualElement. An important thing to think about is that it will move the object to the bounding box's upper left corner. Also, you must supply enough space yourself to make sure that the contents of the view has enough room to display itself.

Step two - Translate this!

Another way to move the button without having to care about the width and height is to use the TranslateTo extension method. The important thing here is that the movement is relative. So translating by {0,0} doesn't do a thing. The example below moves the button left and up by 50.

awaittheButton.TranslateTo(-50,-50);

In order to use the TranslateTo extension method you need to keep track of where you start from.

Step three - Scaling and ContinueWith!

You can string animations together since all calls are using async/await. The first way of doing this is to simply declare the method async and add await before each call. (gotta love C#).

awaittheButton.ScaleTo(3);awaittheButton.ScaleTo(1);

So then this should work...

awaittheButton.ScaleTo(3).ContinueWith((a)=>theButton.ScaleTo(1));

It does not... It works the first time you click the button, but the second time it gets stuck after the initial upscaling.

Step four - RelScale does what?

All the Rel* functions simply add to what ever value the control has before. The code below adds 4 to the scale each time you click it. It becomes really large after a while.

awaittheButton.RelScaleTo(4);

This also goes for RelRotate and is pretty much what TranslateTo also does.

Step five - Fade to black

The fade function let's you control the opacity to what ever value you'd like. Nothing fancy, but very useful. To make the button disappear, just fade to 0. The upper limit is one (1) and that means that it's totally visible.

awaittheButton.FadeTo(0);

Step six - Rotation

The last of the animation extension methods. Rotates the control to 40 absolute degrees. The RelRotate adds the given value to the current rotation.

awaittheButton.RotateTo(40);

Another cool rotate function the RotateXTo and RotateYTo that gives you a 3D effect. Combine it with a FadeTo(0) to make your buttons fold and disappear! :)

Combining them

Can you combine different animations? Well, yes you can! Simply omit the await keyword to continue execution.

theButton.TranslateTo(-10,-150);awaittheButton.FadeTo(0);

You might wonder why I don't use a fancier way to do the await, like in the example below? It simply doesn't work. The animation "locks up" half way through. Another issue for Bugzilla.

Monday, February 16, 2015

When I first was faced with the requirement to create a kind of accordion-like area that open and closes by the click of a button, I thought to my self that that would be easy...

The solution was pretty easy, but accepting that the most simple solution didn't work was not.

The requirement was based on the image below. When you tap the surface titled "Tap me!" the red surface was going to animate it's height and disappear. I know I'm not going to earn any design awards from this! :)

Grids to the rescue!

I defined a simple three-row grid that gives the layout displayed in the image above.

Attempt one - binding to the height property

I then created a view model with a TopRowHeight property that I bound to the first RowDefinition.

<RowDefinitionHeight="{Binding TopRowHeight}"/>

This did not work at all. Even though the documentation states that the HeightProperty is bindable it simply does not call the getter. I tried returning an int, float, double and GridLength and any binding mode possible.

The solution - xaml

So what I ended up doing was to give the RowDefinition a name instead. For this example, it's important to keep the Height="200" since it decides what height to open up to again.

Friday, February 13, 2015

Wouldn't it be great if you could control the theme of your Windows Phone 8 (silverlight) app? Well, just install the PhoneThemeManager package from nuget written by Jeff Wilcox and add a single line of code to your app.

ThemeManager.ToDarkTheme();

Read more about it at http://www.jeff.wilcox.name/2012/01/phonethememanager/. Oh, and it seems like the reference isn't added sometimes so just add a reference and drill down into the packages folder until you find the correct dll. In this case JeffWilcox.PhoneThemeManager.dll in the windowsphone8 folder.

Windows Phone 8.1 solves this by letting you request a theme by writing something like