JetCracker

Life-time learner's blog

Speedometer Gauge with Needle for Android

I am working very hard on my CardioMood app for Android.

As described in one of my previous posts, CardioMood is a health monitoring social service with a stress monitor app. It measures your stress level according to heart rate variability. It also shows a bunch of other parameters, which are represented as different kinds of charts.

Stress Index is a quantitative characteristic of your stress. Normally, the value of Stress Index varies from 50 to 150. The SI value outside of the range could be caused by a number of factors, such as physical or emotional stress, diseases (including heart diseases), and low quality of data obtained from heart rate sensor.

In CardioMood Stress Monitor app, we need to visually represent a calculated value of Stress Index – and that is another problem. I decided to use a speedometer-like gauge.

A simple way: WebView

In our measurement report screen used WebView to visually represent the result.

Android WebView supports almost all HTML and javascript features, which enables developers to render anything and use various javascript libraries already available on the net.

So, WebView gives you an easiest way to add Speedometer gauge to your android app. In our case we used a solution from Geek’s Retreat.

Their implementation is purely javascript. It has a certain number of limitations. For example, you have to specify the exact width and height of the canvas before rendering.

We had hard time with sizing and layouting components in WebView. Soon, we realized that WebView is not reliable – it’s better to use native controls than spend days on fixing issues and supporting diverse screen densities and sizes in HTML.

Hard way: Implementing Android custom view

I decided to take a bull by the horns and convinced our team to stop using WebView. After two days of working, I finally created SpeedometerView – a simple speedometer with needle gauge for Android. It looks similar to it’s javascript brother and has the same features.

CardioMood SpeedometerView in action

Supported features:

  • Major and minor tick marks
  • Custom labels
  • Colored value ranges
  • Animation of arrow (requires Android API level 11+)

Download

Check out a GitHub repo to see source code, release binary and usage example.

UPD: The component was moved to AndroidWidgets library.

GitHub: https://github.com/ntoskrnl/AndroidWidgets

Screenshot of CardioMood with SpeedometerView

Feel free to comment, request features or report bugs.

Advertisements

33 responses to “Speedometer Gauge with Needle for Android

  1. zeeshanakhter2009 February 28, 2014 at 15:16

    Reblogged this on Zeeshan Akhter.

  2. kahou March 25, 2014 at 09:10

    Can you show me how to include your library in an android project?

    • jetcracker April 3, 2014 at 17:42

      Just add the release binary (.aar file) to your libs folder. Then, make sure you added it as a dependency of your project.

      In my case (Android Studio with Gradle):
      1. The .aar file is in my libraries folder of the project
      2. I added the line in build.gradle:

      compile files('lib/SpeedometerView.aar')
      
  3. Sushil July 25, 2014 at 13:16

    i used this SpeedometerView for checking network connection speed but don’t know how to rotate/move the needle according to network speed dynamically. Any help will be appreciated. Thank you.

    • jetcracker July 25, 2014 at 14:59

      Hi!
      There is method:
      public ValueAnimator setSpeed(double progress, long duration, long startDelay)

      Where duration indicates the duration in milliseconds of needle animation, and delay is a delay before the animations starts (also in milliseconds).

      • Sushil July 25, 2014 at 15:11

        Thank you ..

        A) i used :
        public ValueAnimator setSpeed(double progress, long duration, long startDelay)

        but app error –> “Unfortunately stopped”.. there is targetApi ->11 but im running it in kitkat(api 19)…is there any solution for this ???

        B) But for now i am using :
        public void setSpeed(double speed)
        calling it in each 1second interval. There is ticking of needle..

        Is point B will be ok if i do this ?? Thankyou again )

      • jetcracker July 25, 2014 at 16:08

        I think it is not working when the value is 0. There is a mistake in my code.
        For now as a work around this issue you can call setSpeed() like this:

        if (speed <=0)
        speedometerView.setSpeed(0.01d, 500, 0);
        else speedometerView.setSpeed(speed, 500, 0);

      • Sushil July 27, 2014 at 12:45

        Thanks Jetcracker 😉

  4. Sushil July 30, 2014 at 14:18

    Hello JetCracker..

    Is there any solution to this :

    speed = 0.07 ..needle not moving.. ??

  5. Achim August 19, 2014 at 16:35

    Hi
    I tried to use this speedometer in my Modell-Train App
    But in java OnCreate Bundle I get error

    speedometer = (SpeedometerView) v.findViewById(R.id.speedometer);

    cannot resolve symbol “v”

  6. Achim August 21, 2014 at 15:40

    Hi
    I am a beginner and still not very familiar with Android Studio. Maybe I used the given Usage in the wrong place.

    In folder:

    app
      libs
        SpeedometerView.aar

    in build.gradle:

    repositories {
        mavenCentral()
        flatDir {
            dirs 'libs'
        }
    }
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.android.support:appcompat-v7:20.0.0'
        compile(name:'SpeedometerView', ext:'aar')
    

    in java:

    package com.jochens_moba.btregler01;
    
    import android.graphics.Color;
    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import com.cardiomood.android.speedometer.SpeedometerView;
    
    public class ReglerActivity extends ActionBarActivity {
    
        private SpeedometerView speedometer;
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_regler);
    
            // Customize SpeedometerView
            speedometer = (SpeedometerView) v.findViewById(R.id.speedometer);
    
            // Add label converter
            speedometer.setLabelConverter(new SpeedometerView.LabelConverter() {
                @Override
                public String getLabelFor(double progress, double maxProgress) {
                    return String.valueOf((int) Math.round(progress));
                }
            });
            // configure value range and ticks
            speedometer.setMaxSpeed(300);
            speedometer.setMajorTickStep(30);
            speedometer.setMinorTicks(2);
    
            // Configure value range colors
            speedometer.addColoredRange(30, 140, Color.GREEN);
            speedometer.addColoredRange(140, 180, Color.YELLOW);
            speedometer.addColoredRange(180, 400, Color.RED);
    
            speedometer.setSpeed(0.01d, 500, 0);
        }
    }
    

    But still error:

    cannot resolve symbol “v” in line:
        speedometer = (SpeedometerView) v.findViewById(R.id.speedometer);

    Any help is highly appreciated.

    • jetcracker August 21, 2014 at 15:48

      Hi! When you are in the scope of the Activity-class, you should simply write

      findViewById(R.id.speedometer);
      

      v is not declared of course. You can simply call method findViewById() of the Activity.

      • Achim August 21, 2014 at 16:23

        Thank you for your quick replay.

        I changed as advised. But when I try to run this application, I get a lot of compile errors:

        I/dalvikvm﹕ Could not find method com.cardiomood.android.speedometer.SpeedometerView.setLayerType, referenced from method com.cardiomood.android.speedometer.SpeedometerView.init
        W/dalvikvm﹕ VFY: unable to resolve virtual method 9360: Lcom/cardiomood/android/speedometer/SpeedometerView;.setLayerType (ILandroid/graphics/Paint;)V
        I/dalvikvm﹕ Failed resolving Lcom/cardiomood/android/speedometer/SpeedometerView$1; interface 11 ‘Landroid/animation/TypeEvaluator;’
        W/dalvikvm﹕ Link of class ‘Lcom/cardiomood/android/speedometer/SpeedometerView$1;’ failed

        and so on …

        I hope I don’t bother you too much 😉

      • jetcracker August 21, 2014 at 16:29

        According to the Android SDK docs View#setLayerType() was added in API level 11.
        I think in your build.gradle and/or AndroidMinifest.xml you have minSdkVersion lower than 11.

      • Achim August 21, 2014 at 17:10

        You are right, the device I connected to is only API10. SDK and Manifest is minSdkVersion = 11.
        I changed to Emulator, then I got the message: Device connected: emulator-5554
        No other messages appear. But nothing happens on Emulator screen. (In Design mode speedometer rectangle and a text field are clearly visible).
        Anyway, many thanks for your kind help, I think I have to dig a little deeper into Android Studio. But when you have time to make a complete sample project with simple activity just a slider to move the needle which is able to run in Emulator, that would be great help for Android Dummies like me.

  7. Amol Sawant August 25, 2014 at 11:33

    Hello,
    I m using your speedometer. I wrote one thread and continuously passing speed through setSpeed(double spreed) to speedometer. But dont know how the label text changing and increasing its value. Please help me.. Thank you in Advance.

    • jetcracker August 27, 2014 at 00:36

      Hi Amol 🙂
      This piece of code is very important to configure ticks labels:

              // Add label converter
              speedometer.setLabelConverter(new SpeedometerView.LabelConverter() {
      
                  // This method will be called by SpeedometerView when it needs to draw
                  // label over the major tick that corresponds to the specified speed value
                  @Override
                  public String getLabelFor(double speed, double maxSpeed) {
                      // return string value for the label
                      return String.valueOf((int) Math.round(speed));
                  }
              });
      
              // configure value range and ticks:
              // max speed will be 300.0 units
              speedometer.setMaxSpeed(300);
              // major (large) ticks will be shown every 30.0 units
              speedometer.setMajorTickStep(30);
              // between major ticks there will be two minor (small) ticks
              speedometer.setMinorTicks(2);
      

      SpeedometerView needs to know how to convert speed value (float) into label (string). Method getLabelFor() will be invoked for each major tick and must return String or null for no label.

      In this particular example above, we just round the speed value and convert it to string: String.valueOf((int) Math.round(speed)). Method will be called for speed=30, speed=60, speed=90, and so on.

      P.S. Also, make sure you make all updates of your View in UI thread. Trying to update View from a thread different than UI thread will result in Exception or may simple not work.

  8. TigerShark August 26, 2014 at 15:28

    How I install speedometer at eclipse ADT

    • jetcracker August 27, 2014 at 00:45

      Just as any android library. But I don’t use Eclipse…

      I think there is Libraries (or Dependencies) tab somewhere in your Project Properties. It allows to add a folder or jar/aar file to your class path.

      Good luck 🙂

    • jetcracker October 25, 2014 at 22:19

      Now you can add it as a maven library!
      Details here: https://github.com/ntoskrnl/AndroidWidgets

  9. Kishor September 19, 2014 at 15:57

    I can’t find SpeedometerView.aar file anywhere in the downloaded code. I tried running the app without SpeedometerView.aar but is doesent display anything(it shows just black screen.)

    • Kishor September 19, 2014 at 16:03

      found it at https://github.com/ntoskrnl/SpeedometerView/releases/tag/SpeedometerView-v1.0.1.
      Thanks.

      • jetcracker October 25, 2014 at 21:56

        Hi! I moved Speedometer to different library.
        https://github.com/ntoskrnl/AndroidWidgets

  10. Peter September 23, 2014 at 20:10

    How can I animate the needle to some random values for some particular duration? Any sample code please..

  11. jetcracker October 25, 2014 at 22:18

    I know what you mean. There is only method for needle animation when you set a single value for speed. However, you can try the following:

            speedometer.setSpeed(80, 5000, 0);
            speedometer.setSpeed(120, 2000, 5000);
            speedometer.setSpeed(50, 1000, 12000);
    

    For each setSpeed() you should specify animation delay (sum of delays and durations of previous invocations).

    By the way, I pushed the library to maven central repository. More details here: https://github.com/ntoskrnl/AndroidWidgets

  12. Irineu L Filho November 10, 2014 at 17:26

    I have the same error: http://stackoverflow.com/questions/26799149/speedometergauge-speed-values-on-markers how can I fix it?

    • jetcracker November 11, 2014 at 03:28

      Can you please provide a sample code to reproduce this issue? I also want to know what minSdk version you specified. It would be nice if you send me a zip with your project sources.

      Thank you in advance!

  13. KNIGHT MASTER January 20, 2015 at 13:56

    hi jetcracker, i’ve implemented your sample code from here : https://github.com/ntoskrnl/AndroidWidgets. But, i have some problems, the result doesn’t show me tick label. In fact i’ve used LG Nexus 5 ( API 19 ) i also implemented this on some other devices. Is there any solution for this ?

  14. KNIGHT MASTER January 21, 2015 at 16:03

    It works excellent for me on API 19. like your suggestion, to add android-widgets.aar as library in my project.
    Thank you…

    • jetcracker January 21, 2015 at 18:58

      When I find time, I will try to find the problem with maven repository and update it accordingly.

    • ITC_Android February 13, 2015 at 15:08

      Can you please send me the code. It will be very helpful if I get the code, because I’m facing issues…

      • jetcracker February 14, 2015 at 16:38

        Hi! Contact me via skype anton.danshin, we’ll figure out how to make your code work. 🙂

  15. ITC_Android February 13, 2015 at 15:07

    I’m unable to run the code. Please help me.. I need to work similar kind of requirements. Src folder is empty. I have tried to download the code from Speedometer-master and AndroidWidgets but facing same error.

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

%d bloggers like this: