Yet Another [à compléter]

Ada Lovelace Day 2014

Today is Ada Lovelace day, a special occasion to recognize women in our community. I want to take this opportunity to also highlight someone exceptional I have known for a while.

Her name is Andrea Magnorsky.

Andrea Magnorsky

Andrea is an Irish .NET programmer. She’s currently following one of her passion – game development – and is closing production with her studio Digital Furnace (ex-BatCat) on their next title Onikira.

To say that Andrea is a community person is an understatement. In the span of a few years she has not only created popular event/group like Global Gamecraft (game jam contest) or Dublin ALT.NET but she is also continously looking for new ways to teach people through numerous talks and meetups like Functional Kats.

She is curious of everything and always avid to learn. These days you can see her sailing along with F# and functional programming for instance.

It’s no surprise that she was recognized several times in Ireland as a top person in her field. Microsoft also recently awarded her an MVP award.

It’s thanks to people like Andrea that I’m happy to be part of the community that is software development.

Muncho

Muncho would have loved to conclude this but he had another emergency

A Tale of Connected Dots

This past week, we organized Evolve 2014 in Atlanta to talk about all things mobile with Xamarin.

Being a mobile conference, we of course made our own app so that attendees could track out the sessions and the geography of the event.

We also launched something a bit different in the form of a treasure hunt app. Thanks to Estimote, we used a combination of iBeacon and QR codes spread throughout the conference intertwined with challenges along the way until you reach the end of the quest and a special prize.

The main interface of that quest app is a serie of connected dots:

Evolve Quest screenshot

As you progress through the game, the content scrolls naturally to reveal more odd-shaped arrangement of those dots.

Originally, this screen was just a big tall image containing everything. This is suboptimal on Android for a couple of reason like some graphic chip not supporting big “texture” or simply the need to rescale at runtime on most screen.

Ultimately it’s also not fun because there is really nothing you can do with a big image.

Hint: this is NOT what we shipped (on Android at least).

Rather, what attendees could see on their Android phone at the conference was this:

A much more satisfying, softly animated, connected system of dots. The current game position is also highlighted with a discrete pulse.

We will open-source the entire Quest application at some point but I wanted to share how we did that specific bit that is entirely exclusive to Android.

View Source Code

Since this is a really custom animation, it’s a bit different than the other type of animation samples I have already shown.

For this type of thing, I usually rely on a very simple animator that gives me a floating value between 0 and 1 so that I can do my own tweening in code. I also manage to pass this value by hijacking one of the standard view animatable property so that I don’t need to expose more information to the Java bridge:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Interpolator instantiation
shiverAnimator = ObjectAnimator.OfFloat (this, "scaleX", 0, 1);
shiverAnimator.RepeatCount = ValueAnimator.Infinite;
shiverAnimator.AnimationRepeat += (sender, e) => shiverIndex++;

// Property hijack
public override float ScaleX {
	get { return currentShiverInterpolation; }
	set {
		currentShiverInterpolation = value;
		Invalidate ();
	}
}

In our case, I then use this value to compute for each drawing pass an offset that is added to the base position of every dots:

1
2
3
4
5
6
7
8
9
10
11
// Expressed in dp units
int[] shiverOffsets = new[] { 9, 3, -8, 4, -7, 6 };

// Extra applied offset code
int ApplyShivering (int dotIndex, int value)
{
	var off = shiverOffsets [(dotIndex + shiverIndex) % shiverOffsets.Length]
		* currentShiverInterpolation;
	value += (int)Math.Round (off);
	return value;
}

The wave that you see on the highlighted pin comes from a GradientDrawable that I create from a shape drawable XML definition as follow:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="ring"
	android:useLevel="false"
	android:innerRadiusRatio="2">
	<solid android:color="#99ffffff" />
</shape>

The reason for using a drawable like this is to avoid redoing common drawing code and also taking advantage of the ring shape type automatic radius scaling (notice the innerRadiusRatio attribute) to create a nice spreading effect as the ring grows larger.

The ring size and color is dynamically computed from a slightly interpolated (quadratic or accelerated) value coming from our shared shiver interpolator:

1
2
3
4
5
6
7
8
9
10
11
var dur = shiverAnimator.Duration / 4;
var fraction = (float)(shiverAnimator.CurrentPlayTime % dur) / dur;
// Cheap interpolation
fraction *= fraction;

var rippleRad = (int)(radius * (5 * fraction + 1)) - 8;
ripple.SetBounds (x - rippleRad, y - rippleRad, x + rippleRad, y + rippleRad);

var color = Color.Argb ((int)Math.Round (0x99 * (1 - fraction)),
                        0xFF, 0xFF, 0xFF);
((GradientDrawable)ripple).SetColor (color.ToArgb ());

If you have been to my Mastering Time and Space session, you’ll likely also have detected the presence of a custom interpolator in there that is set on the shared shivering animator. The code is following:

1
2
3
4
5
6
7
8
class TriangleWave : Java.Lang.Object, ITimeInterpolator
{
	public float GetInterpolation (float input)
	{
		var t = input * 2;
		return (float)(2 * Math.Abs (t - Math.Floor (t + 0.5)) * (1 - 2 * Math.Floor (t)));
	}
}

This interpolator generates a triangle pattern that is repeatable (i.e. it both starts and ends at the same position for the dot) so that the animation can run continuously:

Triangle curve

Build Your Own Continuous Integration Pole

If you live in Boston and happen to walk around the Commons when evening falls, you may have noticed a strange glow coming from the top of one the building along the park:

A Mysterious Glow on Boston

This eerie light comes from our designer pole, an experiment I did to provide cheap feedback over our build status in our continuous integration system:

Le Pole

The setup is based around 3 main components: a Raspberry Pi, a 5V relay module board and a basic 12V RGB LED strip. You can buy all those parts directly from Amazon for about $112 total (of which $77 was for a premium Raspberry Pi package but it’s up to you).

Setup

No matter the RGB LED strip “brand” you end up buying (it all seems to be from the same generic supplier), the wiring is pretty simple and consist of a common ground and a wire for each color channel (red, green, blue) so 4 wires in total.

Thus in the simplest form we can very easily turn on and off those channels using a bunch of relays. Each build status (success, test failure and build failure) will be mapped to a specific color (green, blue, red respectively).

A relay is the basic building block to control a power circuit (the 12V DC from the LED strip power adapter) from a control circuit (the 3.3V DC of the Raspberry Pi). There are a bunch of different designs available (magnetic, solid state, …) depending on the amount of power you are controlling. For this type of setup pretty much anything should work (it’s just LEDs after all).

A relay module

Those relays are then mounted on a board like the one in the picture to conveniently expose a control interface that you can plug to your Raspberry Pi GPIO ports. That’s the final product you can buy (unless you want to do your own PCB).

Below is a close-up of the wiring between all the different pieces, the GPIO ports are exported to the breadboard and then connected onto the relay module control circuit.

Close-up wiring

I also made a more schematic version so that you can see which GPIO ports are used:

Wiring schema

The common of the LED strip (the white cable) is connected directly to the power source (we don’t care about controlling it). All the other color wires go in and out of their own relay.

If you are short on connectors, you may have noticed a little trick I use which is to go scavenge your old computers for IDE connectors (what you used to plug your old harddrive, floppy disk readers and the likes). They fit perfectly well and have the same type of wire that standard Dupont cables.

Below is the part of the code that controls the relay module to turn on and off the LEDs:

using System;
using System.Threading;
using RaspberryPiDotNet;

namespace WrenchBerry
{
	public static class Ledder
	{
		public enum Color {
			Green,
			Orange,
			Red
		}

		static GPIOPins[] pinMapping = new GPIOPins[] {
			GPIOPins.V2_GPIO_17,
			GPIOPins.V2_GPIO_27,
			GPIOPins.V2_GPIO_22,
		};

		public static void FlashLed (Color color, int times = 3)
		{
			var pin = pinMapping [(int)color];
			for (int i = 0; i < times; i++) {
				GPIO.Write (pin, true);
				Thread.Sleep (500);
				GPIO.Write (pin, false);
				Thread.Sleep (500);
			}
		}

		public static void TurnOn (Color color)
		{
			var pin = pinMapping [(int)color];
			GPIO.Write (pin, false);
		}

		public static void TurnAllColorOff ()
		{
			foreach (var pin in pinMapping)
				GPIO.Write (pin, true);
		}
	}
}

The code use the RaspberryPi.Net library to directly access the chip memory controlling the GPIO pins.

The main program is then a super-simplistic infinite loop over the CI results:

using System;
using System.IO;
using System.Linq;

namespace WrenchBerry
{
	class MainClass
	{
		const Ledder.Color NoColor = (Ledder.Color)(-1);
		static Ledder.Color currentColor = NoColor;

		public static void Main (string[] args)
		{
			var lane = args [0];

			while (true) {
				try {
					var builds = CISystem.GetStateListFromLane (lane);
					if (builds == null || builds.Length == 0 || !builds.Any (IsFinishedState)) {
					    Console.WriteLine ("Lane or fetching is fucked up");
					    return;
					}
					var firstBuilt = builds.First (IsFinishedState);
					Console.WriteLine (DateTime.Now.ToString ("u") + " - " + firstBuilt);

					Ledder.Color color = GetColorForState (firstBuilt);

					if (color != NoColor && currentColor != color) {
					    Ledder.TurnAllColorOff ();
					    Ledder.FlashLed (color);
					    Ledder.TurnOn (color);
					}
					currentColor = color;
				} catch (Exception e) {
					Console.WriteLine (e);
				}

				System.Threading.Thread.Sleep ((int)TimeSpan.FromMinutes (2).TotalMilliseconds);
			}
		}

		static Ledder.Color GetColorForState (DBState state)
		{
			Ledder.Color color = NoColor;
			switch (state) {
			case DBState.Failed:
				color = Ledder.Color.Red;
				break;
			case DBState.Issues:
				color = Ledder.Color.Orange;
				break;
			case DBState.Success:
				color = Ledder.Color.Green;
				break;
			}
			return color;
		}

		static bool IsFinishedState (DBState state)
		{
			return state == DBState.Failed || state == DBState.Issues || state == DBState.Success;
		}
	}
}

All that’s left to do is to make yourself a nice little storage area and, why not, spice up the system a little bit. For instance in our setup (pictured below) I also hooked up a small speaker.

Final Setup

As an example our current playlist consist of: the Imperial March (build failure), Mass Effect Reaper sound (test failure) and, last but not least, our friend He-Man (build success).

Happy (hardware) hacking!

Scrolling-based Effects in Android UI

Scrolling is a central behavior of a lot of common elements in Android UIs with widgets like ScrollView, ViewPager or ListView.

It also has the nice property that, knowing the scroll extents, it’s very easy to infer a floating ratio (i.e. a value between 0 and 1) from a given intermediary scroll state.

This last property makes scrolling very similar to animations, replacing the need for a time-based interpolator by this scroll-state inferred value.

In addition, since scroll events are generally triggered in response to a continuous user action, those intermediates values can be used to implement nifty navigation effects.

I have already talked about one of such effect earlier, the infamous parallax, that a lot of people are already using but there is much more opportunities around.

In the last release of my pet app Bikr for instance, I added a new statistics screen:

Stats screen

As is common in Android land, the navigation is implemented using ActionBar’s tabs at the top of the screen. This is coupled with a ViewPager instance as the root fragment layout so that screens can be accessed both by swiping and by tabs selection.

The statistics panel itself consists of a subclass of ScrollView that snaps to each of its subsection scroll offset to display multiple sub-pages.

Since both of those elements can generate scroll states, the rest of the UI take advantage of it by dynamically refreshing itself based on those value changes.

For the ViewPager for example, the tab icons are progressively made more transparent or opaque. The overall gradient background is also subtly inverted to influence the reading direction of the user upwards instead of downwards:

View Code

The scroll information of the statistics ScrollView is linked to a custom scrollbar knob that is aligned to the subsection title. I use the intermediary scroll values in that case to both infer the knob vertical position and dynamically adjust its size:

View Code: Event - Drawing

Bikr, the Fun UI Parts

A couple of days ago, I released Bikr my new Android app to effortlessly track your bicycle rides.

Right from the start the development motto was that the app should be as simple and straightforward as the problem it solves: keeping track of users rides without needing their input.

This lead to a very clean UI with no apparent settings and interaction requirements kept to a bare minimum while still making it a delightful experience.

In the rest of this post I’m going to show you some UI tidbits that got implemented in Bikr as a result.

On-boarding

View Source Code

As I mentioned in the introduction, the need for user involvement was voluntarily maintained low as the whole experience is supposed to be automatic.

As a matter of fact, the only actionable element of the entire main UI is the switch at the top-right of the screen that enable or disable globally the service.

This gave me the inspiration for this on-boarding:

Tank Fill screencast

The idea is to overlay on top of our main UI that same switch with a short explanation text and let the user initializes himself the service before being able to proceed further.

The effect is implemented by using Android view caching mechanism, retrieving the composited top-most bitmap and using Renderscript to blur the image as a background much like I described in this article.

Tank Filling Animation

View Source Code

When the app starts, each circle fills out to show you how far you are in reaching the same level than the previous day, week or month (accordingly).

When thinking about it I almost right away draw a parallel between this and filling a container with water.

This animation thus reproduce the familiar bubbling at the surface of a liquid when poured rapidly:

Tank Fill screencast

I use a sine function to distribute the bubbles uniformly across the vertical top band of the liquid and then animate them to grow out and “burst” at the surface as they get closer to the top.

Wave Simulation

View Source Code

Although the circles are not actual actionable items, when showing the app to friends they would unconsciously reach and try to interact with them.

In the spirit of rewarding the user for experimentation and not unsettling them, the water analogy is continued here by implementing a simple wave simulation that generates ripples where the user is tapping.

I also use a nice springy touch feedback that will influence the force of the final ripple to give even more touch satisfaction:

Tank Fill screencast

The simulation algorithm itself is based on the work of Matthias Müller.

Bikr, Delicious Ride Tracker

Today I’m introducing Bikr, a new Android application to track your bicycle rides.

It’s a no fuss, down to fundamental app that records how many miles you cycle and gives you a roundup per day, week and month. It will also show how you compare with the previous corresponding metrics (i.e. yesterday, previous week, previous month).

Best of all is that you don’t have to do anything. Thanks to Google Activity Recognition APIs, the app will take care of itself meaning you can just bike and forget about it.

The app is built using Xamarin as you would expect and you can find the entire source code at garuma/bikr on GitHub. As usual, code is under the Apache 2.0 license which basically mean you can reuse whatever you want.

It’s also available for download on the Play Store.

This is a joint release with James Montemagno’s MyStepCounter Android app, check it out too!

Using Parallax for Fun and Profit

The idea of a parallax is to give the illusion of depth thanks to targets seemingly moving at a different pace. You have probably already noticed the effect in real life when riding on a straight line e.g. staring at individual scenery items from a train window.

The idea is basically that the closer an object is to you, the faster it seems to move to your eyes. The extreme being the background (like distant mountains) which doesn’t seem to move at all.

This effect, called Parallax, is used proficiently on iOS and Android launchers when scrolling through your apps to make it look like your wallpaper is further away from your icons as they move.

We can re-create parallax pretty easily on Android using the ViewPager class of the support package as a foundation for handling the touch events and displaying our content.

Our goal here is to create an awesome on-boarding screen to present your app. Each “slides” will have its own background and a couple of visual elements (text, device frame, other widgets) that will be arranged in different virtual layer (i.e. some will move faster than others).

Check out an example below of such a screen and the slightly different position offsets applied to each elements:

The core idea is to setup a ViewPager taking up all the screen space (you can even use the new KitKat translucent window chrome like in the screencast with the Holo.*.NoActionBar.Translucent style) and then create a generic FrameLayout-based layout (remember how FrameLayout is your friend?) for the page. You don’t need to add an ImageView for the background since we will directly use the background property of the FrameLayout.

It’s also not necessary to have pre-scaled those background images since setting them as the background drawable of the main FrameLayout will automatically make them fit but it’s better if their dimensions are close to the form factor of the device (16/9 portrait usually) so that they don’t appear squashed (if you want to get fancy you might want to dynamically blur those too).

Afterwards, just sprinkle the layout with TextView, ImageView or whatever other view you may want to showcase your app using the layout_gravity and layout_margin attributes to align them on the screen. Here is the example, very dumb, layout I’m using for the demo:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/backgroundFrame"
    android:background="@drawable/onboarding_bg_1">
    <TextView
        android:text="A Big Title About Something"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/bigTitle"
        android:layout_gravity="center_horizontal|top"
        android:layout_marginTop="64dp"
        android:textColor="#ffffffff"
        android:textSize="24sp"
        android:shadowColor="#ff000000"
        android:shadowDx="0"
        android:shadowDy="1"
        android:shadowRadius="0.5" />
    <TextView
        android:text="A Subtitle About the Thing"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/bigSubtitle"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="64dp"
        android:textColor="#ffffffff"
        android:textSize="20sp"
        android:shadowColor="#ff000000"
        android:shadowDx="0"
        android:shadowDy="1"
        android:shadowRadius="0.5" />
    <ImageView
        android:src="@android:drawable/ic_menu_gallery"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:id="@+id/centerImage"
        android:layout_gravity="center" />
</FrameLayout>

Once you have wired your ViewPager with an Adapter feeding the right content, we are going to create a PageTransformer which is where the parallax magic is gonna be created. Implementing this interface requires only one method which is called for every scroll offset of a given page View together with a value indicating its position relative to the center of the screen.

That relative position is very handy because it’s clamped between -1 (left of the screen) and +1 (right of the screen) with the zero value in the middle. That means we can derive a very simple parallax equation based on its value:

public class OnBoardingPageTransformer : Java.Lang.Object, ViewPager.IPageTransformer
{
	float parallaxCoefficient;
	float distanceCoefficient;
	IEnumerable<int>[] viewLayers;

	public OnBoardingPageTransformer (float parallaxCoefficient,
	                                  float distanceCoefficient,
	                                  params IEnumerable<int>[] viewLayers)
	{
		this.parallaxCoefficient = parallaxCoefficient;
		this.distanceCoefficient = distanceCoefficient;
		this.viewLayers = viewLayers;
	}

	public void TransformPage (View page, float position)
	{
		float coefficient = page.Width * parallaxCoefficient;
		foreach (var layer in viewLayers) {
			foreach (var viewID in layer) {
				var v = page.FindViewById (viewID);
				if (v != null)
					v.TranslationX = coefficient * position;
			}
			coefficient *= distanceCoefficient;
		}
	}
}

The trick is then to have a way to define layers and then let the user supply a couple of arguments to parametrize the effect. In the above class, we achieve this by letting the user gives a list of view IDs for each layer they want to create. You can then set the instance on your ViewPager by calling the SetPageTransformer method.

As a final piece of information, know that this technique only work on Android 3.0+ because ViewPager assumes you are using animatable properties.