Yet Another [à compléter]

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.

XamSvg, Managed SVG Support for Android

As part of the new release of Moyeu, I’m also finally publishing a library that I have been using for some time.

This library is called XamSvg and in a nutshell it’s a managed (partial) implementation of an SVG parser/renderer for, currently only, Xamarin.Android.

The idea stems from the fact that Android has by default no serious way to do scalable graphics in a world with an exploding amount of device densities.

SVG appeared as a good fit because it’s easy to parse (XML), text-based (compress well) and fit well with the Android graphics API. It’s also incidentally the format used by the lovely Inkscape which makes my work even easier.

Before anyone gets their hopes high and starts throwing fancy SVG tigers at the library, know that this is by no mean meant to be a complete implementation of the standard.

As described in the README, the goal is to provide a minimum viable product™ to support traditional shape-based icons.

Still, I haven’t had any problem parsing all the SVG that I have created as almost all the icons in Moyeu are entirely SVG based. In general, if you follow the exporting guide in the README you should be fine.

The other good thing about the library is that it’s very simple to use. You will generally use only one class, SvgFactory and its two methods GetBitmap / GetDrawable:

var bmp = SvgFactory.GetBitmap (Activity.Resources, Resource.Raw.ic_svg, 48, 48);
var drawable = SvgFactory.GetDrawable (Activity.Resources, Resource.Raw.ic_svg);

I recommend the second form as the returned drawable will automatically scale depending on the bounds requested. This means that if you have an ImageView set up using dp units like this:

<ImageView
    android:layout_width="14dp"
    android:layout_height="9dp"
    android:scaleType="fitXY" />

The displayed image will look the same crispy crispness on every devices no matter how many pixel per inches they have.

Another cool thing about the library is that it lets you dynamically adapt colors at runtime. To do so, you need to provide an implementation of the ISvgColorMapper interface which sports the single method Color MapColor (Color c) (instance that can also be retrieved from a Func<Color, Color>).

I use this tricks for the pins that are displayed by Moyeu on the map. Concretely, the pins are all the same base SVG:

On which I can apply tinting with my color mapper:

Color ColorReplacer (Color inColor, float ratio)
{
	Color tone = InterpolateColor (baseLightRedColor, baseLightGreenColor, ratio);
	Color result = inColor;

	if (inColor == fillColor)
		result = tone;
	else if (inColor == borderColor)
		result = Lighten (tone, 0x20);
	else if (inColor == bottomFillColor)
		result = InterpolateColor (baseDarkRedColor, baseDarkGreenColor, ratio);

	return result;
}

In order to have a multi-colored view of the world:

You can find more usage sample of the library in Moyeu source code.

A Big Refresh to Moyeu

Moyeu is an Android application that hopes to provide a better alternative to Boston’s Hubway bike sharing system. You can view the introductory post I made at the time.

This new version sports a good number of new features and general UI refresh.

For starter, the navigation is now exposed as a drawer that also lets you visualize stations that are near you.

Instead of the old info window style, information about a station are presented with a sliding info view in the same fashion than the new Google Maps application. That info view when expanded also shows you a Google Street View shot of the station surroundings for easier pinpointing.

The pins displayed on the map are also now showing the number of bikes available at each station. They also have a better tinting system to provide a direct feedback on each station bike availability.

Just for fun, I also made a little featurette page for the app. Check it out at moyeuapp.net.

For installation, head to the usual corner of the web:

Get it on Google Play

Similardio, Rdio Meets Lastfm

What?

An experiment in bridging Rdio and Lastfm together.

The idea is to gather your most listened to artists on Rdio and generously gather similar talents from Lastfm comprehensive database.

All of this straight from your Android phone.

What does it look like?

It has pretty animations. It has blurring. It has large images.

What should I do with it

Use it as an example for bduncavage/RdioSdkBindings or scavenge any other part of it. All under Apache 2.0 license.

GitHub repository: garuma/Similardio

Android app on Google Play

Blurring Images on Android

One of the most underused Android feature is probably RenderScript (do you even remember what it is?).

As a reminder, RenderScript is essentially Google’s version of OpenCL in that it allows you to write small general-purpose piece of code (called kernel) that executes on the GPU.

As such, it’s very efficient when doing parallelizable work on large data-set. The main hindrance as with any GPGPU scenario is that to interoperate with the CPU, data needs to be copied back and forth between RAM and GPU memory.

One of the main area where RenderScript is useful is with images and pixel-oriented algorithms. Since with recent Android version View instances are hardware-accelerated by default, showing up these GPU-processed images on screen is efficient as they don’t even need to be piggy backed to main memory.

Out of the box, Android ships with a couple of pre-made kernels, mainly picture-related. In that sense it can be considered equivalent to iOS CoreGraphics albeit much less rich in available filters.

One of those default script, ScriptIntrinsicBlur, allows you to blur the content of an image very easily:

Bitmap BlurImage (Bitmap input)
{
	var rsScript = RenderScript.Create (Context);
	var alloc = Allocation.CreateFromBitmap (rsScript, input);

	var blur = ScriptIntrinsicBlur.Create (rsScript, alloc.Element);
	blur.SetRadius (12);
	blur.SetInput (alloc);

	var result = Bitmap.CreateBitmap (input.Width, input.Height, input.GetConfig ());
	var outAlloc = Allocation.CreateFromBitmap (rsScript, result);
	blur.ForEach (outAlloc);
	outAlloc.CopyTo (result);

	rsScript.Destroy ();
	return result;
}

The code will certainly look familiar to those of you who have already used OpenCL. You basically create a context (RenderScript), setup typed buffers (Allocation), create the kernel (ScriptIntrinsicBlur), define its entry point (SetInput) and execute it (ForEach).

Below is the result in a small app to select different blur radius:

You can read up Android basic guide on RenderScript for a more in-depth explanation of each step.

Blur effects are becoming more and more trendy these days, being one of the design focus of iOS 7 and also used extensively by apps such as Rdio. With RenderScript you can now cheaply use that trick in your Android app too.