Creating a Google Fit style circular animated view

Google’s health tracking platform, Google Fit, provides data visualization using a circular view to display feedback to users. This circular view is smoothly animated and presents a variety of data about the current status of the users fitness goals.

This article takes you through the steps required to build the chart shown in the clip below and add it into your Android App.

DecoView

DecoView was designed as a fully configurable library for animating arc based charts. Continue reading this article to find out how to reproduce the Google Fit user experience in your app with DecoView. DecoView is open source and available on GitHub.

DecoView is subclassed from the Android View class. Just like other View subclasses, such as TextView and ImageView, it can be added and configured from your layout XML then controlled in your Activity code.

Faux Fit: DecoView sample project

The source code is available from the Faux Fit project on GitHub.

Step 1: Include the DecoView library in your project

DecoView is hosted on the JitPack.io repository. The first step is to add the required repository into your build.gradle file

repositories {
    // ...
    maven { url "https://jitpack.io" }
}

Next, add the gradle dependency for DecoView

dependencies {
    compile 'com.github.bmarrdev:android-DecoView-charting:v0.9.3'
}

Step 2: Add a DecoView to your XML layout

Open your Activity layout file and add a DecoView by inserting the following declaration.

<com.hookedonplay.decoviewlib.DecoView
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    custom:dv_lineWidth="26dp"
    android:id="@+id/dynamicArcView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Note the use of the custom:dv_lineWidth attribute to set the default width of the arcs. You can always override this value for any of the data series you add later.

Step 3: Configure the DecoView by adding a data series

After adding a DecoView to your XML layout you will not see anything in your app unless you add one or more data series.

The first data series we are adding is going to be used as a background track to show the path where the other data series will follow as they are animated. To add this background arc add the following code to your Activity source file. Note how we set the color to a very light gray (hex code #FFE2E2E2).

DecoView decoView = (DecoView) findViewById(R.id.dynamicArcView);

SeriesItem seriesItem = new SeriesItem.Builder(Color.parseColor("#FFE2E2E2"))
    .setRange(0, 50, 0)
    .build();

int backIndex = decoView.addSeries(seriesItem);

Tip: While we are setting the color to be fully opaque here, DecoView supports alpha transparency in all functions that take a Color value

Next you need to add an actual data series in your Activity code. This may be used to visualize a data value such as the number of calories the user has burnt or number of minutes spent walking.

final SeriesItem seriesItem = new SeriesItem.Builder(Color.parseColor("#FFFF8800"))
        .setRange(0, 50, 0)
        .build();

int series1Index = decoView.addSeries(seriesItem);

Step 4: Add a listener to monitor value changes

First you need to add a TextView to your XML layout. Then you can attach a new SeriesItem.SeriesItemListener() that will be called whenever the current position of the data series is changed. If you issue an event to move the series this callback will be called multiple times for the one event.

We will calculate the percentage the data series is filled and update our TextView with this percentage value.

final TextView textPercentage = (TextView) findViewById(R.id.textPercentage);
seriesItem.addArcSeriesItemListener(new SeriesItem.SeriesItemListener() {
    @Override
    public void onSeriesItemAnimationProgress(float percentComplete, float currentPosition) {
        float percentFilled = ((currentPosition - seriesItem.getMinValue()) / (seriesItem.getMaxValue() - seriesItem.getMinValue()));
        textPercentage.setText(String.format("%.0f%%", percentFilled * 100f));
    }

    @Override
    public void onSeriesItemDisplayProgress(float percentComplete) {

    }
});

Tip: When implementing the DecoView progress listeners be aware that they will be called many times for each event. Avoid heavy processing in the listener to prevent jank, and avoid new allocations to prevent memory churn.

Step 5: Create timed events to animate the DecoView data series

We need to set the background track to be at the maximum value, this enables it to be drawn as a complete circle. We could have set this as the initial position for the track when it was constructed, however we want to see an animation filling the background track so we use an event to reveal the background track. While it is possible to fully customize this animation we will keep it simple and just set the minimum information required; that is the position to move the value and the index of the data series to execute the event.

decoView.addEvent(new DecoEvent.Builder(50)
        .setIndex(backIndex)
        .build());

It is possible to animate the DecoView at any time in response to a user action, such as pressing a button or using a swipe gesture. This is what we have just created with an event to be executed immediately.

It is also possible to delay events to happen at a future time. We will construct then event using setDelay(5000) to delay the animation of the main data series. We need to set the current value between the minimum (0) and maximum (50) values specified on creation of the data series.

Here is how to move the current position to 16.3f (out of 50) and delay the event to start after 5 seconds. After 10 seconds we will then move the position to 30.

decoView.addEvent(new DecoEvent.Builder(16.3f)
        .setIndex(series1Index)
        .setDelay(5000)
        .build());

decoView.addEvent(new DecoEvent.Builder(30f)
        .setIndex(series1Index)
        .setDelay(10000)
        .build());

Note: All time values in DecoView are specified in Milliseconds, 5000ms == 5 seconds

Step 6. Run your app to test your DecoView

You should now have the DecoView animating and looking similar to the image below when you run your app.

DecoView basic sample

Step 7. Add more data series, custom reveal animations and event listeners

To finish off building the Faux Fit sample you need to:

  • Add two more data series. This can be done using the same method used to create the existing series
  • Add custom reveal and hide effects
  • Create a animation loop by adding a listener to recreate all the events when the last one has completed

The code required to complete these final tasks can be viewed in the Faux Fit Activity found within the GitHub project. You should end up with an Activity something like the snapshot below.

Faux Fit DecoView Sample

License

Copyright 2015 Brent Marriott

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

References

DecoView on GitHub: https://github.com/bmarrdev/android-DecoView-charting

Faux Fit sample on GitHub: https://github.com/bmarrdev/fauxfit-decoview-sample

3 Comments

Filed under Android Libraries, Android Studio, Animation, Charting

3 responses to “Creating a Google Fit style circular animated view

  1. HackedHick

    I was just about to code this up as I couldn’t find a good library. Saved me so much time I get to leave early today!

    Liked by 1 person

  2. Richeek Dey

    Hi do I modify this to received live data?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s