Yet Another [à compléter]

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.

Android Tip: ViewPager With Protruding Children

ViewPager is a widget part of the Support package that lets you display an horizontal list of “page”. In a nutshell, it’s to HorizontalScrollView what a ListView is to a vertical ScrollView.

By default pages are laid out to span the entire surface of the pager. In our case what we want to do is something akin to how the search results in the Apple’s AppStore iPhone app are displayed, a card-like style with adjacent items slightly taking over the surface edges:

Getting this to work with the default ViewPager class is a bit tricky. We have basically to change 3 things:

  • The global padding of the pager
  • The spacing between each page
  • The width of a single page

The first one might seem straightforward, you would just go and add both a android:paddingLeft and android:paddingRight onto the pager XML declaration. The problem is that by doing so, the clip rectangle is also moved by that same padding so it looks like the pages are cut in the middle of nowhere.

Fortunately, every ViewGroup subclass accept the android:clipToPadding attribute (doc) which allows to alter exactly that. By setting this one to false, the clip rect will remain equal to the container bounds but padding will still be taken into account during the layout phase.

The spacing between pages is a property settable on the pager itself, PageMargin (doc). This value should be about half the size of the left padding value.

Finally, to change the width of the pages, you override the GetPageWidth method of your PagerAdapter subclass (doc). The right value you use depends on the sizing you put beforehand so slightly tune it until you find the desired effect.

Applying those 3 techniques we arrive at the following result:

For reference sake, here are the XML and code used for that output:

<android.support.v4.view.ViewPager
  	android:id="@+id/pager"
  	android:gravity="center"
  	android:layout_width="match_parent"
  	android:layout_height="0px"
  	android:paddingLeft="24dp"
  	android:paddingRight="12dp"
  	android:layout_weight="1" />
var pager = view.FindViewById<ViewPager> (Resource.Id.pager);
pager.SetClipToPadding (false);
pager.PageMargin = 12.ToPixels ();
pager.Adapter = new MyPageAdapter (ChildFragmentManager);

class MyPageAdapter : FragmentStatePagerAdapter
{
	public override float GetPageWidth (int position)
	{
		return 0.93f;
	}
	
	// ...
}

FrameLayout, Your Best UI Friend

You have probably already used FrameLayout (doc) for what it’s named, adding a decoration around other content element. It can actually be much more than that and is probably one of the most versatile container of all.

The secret of FrameLayout is how it layouts its children. Although normally designed to contain one item, it will happily stack up other element on top of each other. Thus FrameLayout is essentially a way to manipulate the Z-order of views on the screen.

This is super useful for a couple of UI tricks from HUD-like elements to sliding panels to more complex animated transitions. In this post we will see an example for each of those.

Overlay Elements

As I mentioned, FrameLayout will automatically stacks its children on top of each other. This makes it really easy to implement overlay or HUD element in your interface.

The idea is to wrap the part of the UI into an outer FrameLayout instance. Generally this will be the root element of your layout. You can then add below the main layout definition the other elements you want to overlay.

These elements will generally have a fixed size or be set as wrap_content. You can then place them at the right position on screen using the layout_gravity and layout_margin XML attributes.

In the following screenshot, my main content is a Google Map view. I have then added two overlays above it, one that replicate a toast message (center-bottom corner) and a TextView displaying the last time the data was loaded (upper-right corner).

This is simply achieved with the following layout:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content -->
    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- "Loaded" flash bar layout -->
    <FrameLayout
        android:id="@+id/FlashBarLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal|bottom"
        android:layout_marginBottom="72dp">
        <!-- flash bar content -->
    </FrameLayout>
    <!-- Last loaded time layout -->
    <TextView
        android:id="@+id/UpdateTimeText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|right"
        android:layout_marginTop="4dp"
        android:layout_marginRight="4dp" />
</FrameLayout>

Being just normal views, you can manipulate the overlays as usual. For instance you will probably want to implement some sort of animations for transition between visibility states if the overlay is transient.

Sliding Panels

Sliding panels (aka drawers, aka fly-out menus) are the rage these days. They mainly consist of a panel that is placed, depending on the desired spatial effect, above or below another piece of content. Again this falls back to placing elements using a FrameLayout object.

The trick then is to use the translationX and translationY properties of the panel View to move the element back and forth.

Alternatively, View also exposes the OffsetTopAndBottom and OffsetLeftAndRight methods (working on display list directly) but those are not as easy to animate. Indeed, with the translation properties you can directly use ObjectAnimator or ViewPropertyAnimator.

The panel is initially “hidden” by setting its translationY property to its height (i.e. top side forced to the bottom of the screen). We create the initial appearing effect with the following code piece inside the panel class:

// As its name imply, this interpolator will let the view go slightly overboard
// and then spring it back to its place
var intp = new Android.Views.Animations.OvershootInterpolator ();
var d = Context.Resources.GetInteger (Android.Resource.Integer.ConfigMediumAnimTime);
// Only the header part of the view should be visible, we thus just make
// the bottom of the view translated off-screen
var tY = Height - FindViewById (Resource.Id.PaneHeaderView).Height;

this.Animate ().TranslationY (tY).SetDuration (d).SetInterpolator (intp).Start ();

A common idiom of those panel is also to draw a shadow on the edge where they meet the content. This can be implemented very efficiently by overriding the DispatchDraw method of the sliding panel View and drawing a black linear GradientDrawable at the right place (use the Translate method on Canvas for the right positioning).

protected override void DispatchDraw (Android.Graphics.Canvas canvas)
{
    base.DispatchDraw (canvas);
    if (shadowDrawable == null)
        shadowDrawable = new GradientDrawable (GradientDrawable.Orientation.BottomTop,
                                               new[] { Color.Argb (0x60, 0, 0, 0), Color.Argb (0, 0, 0, 0) });
    // The reserved area for the shadow is set with top padding on the view.
    shadowDrawable.SetBounds (0, 0, Width, PaddingTop);
    shadowDrawable.Draw (canvas);
}

Transitions

With the move to a Fragment world, everything becomes just another View to manage and thereby removing the need for Activity.

When you think about the different “screen” of you application as individual fragments it becomes very easy to manipulate them in fun ways. Notably, being just managed View objects, you can apply any of the animations techniques you are already familiar with to implement very nifty transition effects.

At the core of such system, you will find again the same idea of a central, expanded FrameLayout surface where your Fragment are added.

The idea is to pile the Fragment views on top of each other like a deck of card. The current screen is thus the first card of the pile and application transitions are then simply how you want the middle cards to be put on top.

I’m using this analogy of the card deck because the method we are going to use here is View.BringToFront. This method will move the view at the last position inside its parent array. The end result of that operation of course depends on the type of container but in the case of FrameLayout it will make the View be drawn on top.

Note that this method doesn’t force a relayout which is fine for FrameLayout since children individual bounds aren’t dependent on each other but in the case of e.g. LinearLayout you will have to call RequestLayout for the modification to happen.

We will assume the layout of our main Activity is a single full-size FrameLayout container. Our application is composed of two screens represented as two fragments.

Initially, we create and attach directly those fragments to our content frame, hiding the second one to get into an initial state:

FirstFragment fragment1;
SecondFragment fragment2;

Fragment currentFragment;

protected override void OnCreate (Bundle bundle)
{
	SetContentView (/* ... */);
	
	fragment1 = new FirstFragment (this);
	fragment2 = new SecondFragment (this);
	
	SupportFragmentManager.BeginTransation ()
		.Add (Resource.Id.content_frame, fragment2, SecondFragment.Name)
		.Hide (fragment2)
		.Add (Resource.Id.content_frame, fragment1, FirstFragment.Name)
		.Commit ();
	currentFragment = fragment1;
}

When we want to change the Fragment that is shown, we will make sure that both views are on top of the drawing pile with the current one being on top of the other using BringToFront. We then swap the two fragments in a FragmentTransaction:

void SwitchTo (Fragment fragment, string name)
{
	if (fragment.IsVisible)
		return;
	var t = SupportFragmentManager.BeginTransaction ();
	t.SetCustomAnimations (Resource.Animator.frag_slide_in,
	                       Resource.Animator.frag_slide_out);

	// Make sure the next view is below the current one
	fragment.View.BringToFront ();
	// And bring the current one to the very top
	currentFragment.View.BringToFront ();

	// Hide the current fragment
	t.Hide (currentFragment);
	t.Show (existingFragment);
	currentFragment = existingFragment;

	// You probably want to add the transaction to the backstack
	// so that user can use the back button
	t.AddToBackStack (null);
	t.Commit ();
}

To add a bit of woosh, we are using customs animations to mark the transition between the two fragments to get this result:

These animations need to be defined in an XML resource using either property animator (aka from Android.Animations) if you are using framework Fragment or using view animations (aka from Android.View.Animations) if you are using Fragment from the support package.

To register custom animations, we call the SetCustomAnimations method on FragmentTransaction like so:

t.SetCustomAnimations (Resource.Animator.frag_slide_in,
                       Resource.Animator.frag_slide_out);

The first animation will be run on any fragment added/attached/shown while the second animation will be played on fragments hidden/detached/removed. Both are ran at the same time but you can use the animation startOffset attribute to delay one or the other.

For instance in my example, my frag_slide_out animation is defined like so:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:interpolator/accelerate_cubic">
   <translate
      android:fromXDelta="0"
      android:toXDelta="100%"
      android:duration="300" />
   <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.3"
        android:duration="300" />
</set>

Conclusion

Everything I have presented here is part of a big refresh to Moyeu. You can view the full source code on the GitHub repository at garuma/Moyeu.