SpeedometerDemo

Speedometer, Gauge, Speedometer Dial

Step 1 –Start Xcode and create a View based application with name “SpeedometerDemo”.

Step 2 —- Open “SpeedometerDemoViewController.h” and put the following code in it.


@interface SpeedometerDemoViewController : UIViewController {
 UIImageView *needleImageView;
 float speedometerCurrentValue;
 float prevAngleFactor;
 float angle;
 NSTimer *speedometer_Timer;
 UILabel *speedometerReading;
 NSString *maxVal;

}
 @property(nonatomic,retain) UIImageView *needleImageView;
 @property(nonatomic,assign) float speedometerCurrentValue;
 @property(nonatomic,assign) float prevAngleFactor;
 @property(nonatomic,assign) float angle;
 @property(nonatomic,retain) NSTimer *speedometer_Timer;
 @property(nonatomic,retain) UILabel *speedometerReading;
 @property(nonatomic,retain) NSString *maxVal;

-(void) addMeterViewContents;
-(void) rotateIt:(float)angl;
-(void) rotateNeedle;
-(void) setSpeedometerCurrentValue;
-(void) calculateDeviationAngle;

The methods declared are:

addMeterViewContents – This method is used to add view contents.

rotateIt:(float)angl – This method is used the set the needle in default position which is 0;

rotateNeedle – This method rotates the needle.

setSpeedometerCurrentValue – This method generates random value by which the needle should rotate.

calculateDeviationAngle – This method calculates the angle of deviation by which the needle should rotate.

Put the following code in the “SliderDemoViewController.m” file.


@implementation SpeedometerDemoViewController
 @synthesize needleImageView;
 @synthesize speedometerCurrentValue;
 @synthesize prevAngleFactor;
 @synthesize angle;
 @synthesize speedometer_Timer;
 @synthesize speedometerReading;
 @synthesize maxVal;

 - (void)viewDidLoad {

// Add Meter Contents //
 [self addMeterViewContents];

[super viewDidLoad];
 }
 - (void)dealloc {
 [maxVal release];
 [needleImageView release];
 [speedometer_Timer release];
 [speedometerReading release];
 [super dealloc];
 }

#pragma mark -
#pragma mark addMeterViewContents Methods

-(void) addMeterViewContents
 {

UIImageView *backgroundImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320,460)];
 backgroundImageView.image = [UIImage imageNamed:@"main_bg.png"];
 [self.view addSubview:backgroundImageView];
 [backgroundImageView release];

UIImageView *meterImageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 40, 286,315)];
 meterImageView.image = [UIImage imageNamed:@"meter.png"];
 [self.view addSubview:meterImageView];
 [meterImageView release];

//  Needle //
 UIImageView *imgNeedle = [[UIImageView alloc]initWithFrame:CGRectMake(143,155, 22, 84)];
 self.needleImageView = imgNeedle;
 [imgNeedle release];

self.needleImageView.layer.anchorPoint = CGPointMake(self.needleImageView.layer.anchorPoint.x, self.needleImageView.layer.anchorPoint.y*2);  // Shift the Needle center point to one of the end points of the needle image.
 self.needleImageView.backgroundColor = [UIColor clearColor];
 self.needleImageView.image = [UIImage imageNamed:@"arrow.png"];
 [self.view addSubview:self.needleImageView];

// Needle Dot //
 UIImageView *meterImageViewDot = [[UIImageView alloc]initWithFrame:CGRectMake(131.5, 175, 45,44)];
 meterImageViewDot.image = [UIImage imageNamed:@"center_wheel.png"];
 [self.view addSubview:meterImageViewDot];
 [meterImageViewDot release];

// Speedometer Reading //
 UILabel *tempReading = [[UILabel alloc] initWithFrame:CGRectMake(125, 250, 60, 30)];
 self.speedometerReading = tempReading;
 [tempReading release];
 self.speedometerReading.textAlignment = UITextAlignmentCenter;
 self.speedometerReading.backgroundColor = [UIColor blackColor];
 self.speedometerReading.text= @"0";
 self.speedometerReading.textColor = [UIColor colorWithRed:114/255.f green:146/255.f blue:38/255.f alpha:1.0];
 [self.view addSubview:self.speedometerReading ];

// Set Max Value //
 self.maxVal = @"100";

/// Set Needle pointer initialy at zero //
 [self rotateIt:-118.4];   // Set the needle pointer initially at zero //

// Set previous angle //
 self.prevAngleFactor = -118.4;  // To keep track of previous deviated angle //

// Set Speedometer Value //
 [self setSpeedometerCurrentValue];
 }

#pragma mark -
 #pragma mark calculateDeviationAngle Method

-(void) calculateDeviationAngle
 {

if([self.maxVal floatValue]>0)
 {
 self.angle = ((self.speedometerCurrentValue *237.4)/[self.maxVal floatValue])-118.4;  // 237.4 - Total angle between 0 - 100 //
 }
 else
 {
 self.angle = 0;
 }

if(self.angle<=-118.4)
 {
 self.angle = -118.4;
 }
 if(self.angle>=119)  // 119 deg is the angle value for 100
 {
 self.angle = 119;
 }

// If Calculated angle is greater than 180 deg, to avoid the needle to rotate in reverse direction first rotate the needle 1/3 of the calculated angle and then 2/3. //
 if(abs(self.angle-self.prevAngleFactor) >180)
 {
 [UIView beginAnimations:nil context:nil];
 [UIView setAnimationDuration:0.5f];
 [self rotateIt:self.angle/3];
 [UIView commitAnimations];

[UIView beginAnimations:nil context:nil];
 [UIView setAnimationDuration:0.5f];
 [self rotateIt:(self.angle*2)/3];
 [UIView commitAnimations];

}
 self.prevAngleFactor = self.angle;

// Rotate Needle //
 [self rotateNeedle];

}

#pragma mark -
 #pragma mark rotateNeedle Method
 -(void) rotateNeedle
 {
 [UIView beginAnimations:nil context:nil];
 [UIView setAnimationDuration:0.5f];
 [self.needleImageView setTransform: CGAffineTransformMakeRotation((M_PI / 180) * self.angle)];
 [UIView commitAnimations];

}

#pragma mark -
 #pragma mark setSpeedometerCurrentValue

-(void) setSpeedometerCurrentValue
 {
 if(self.speedometer_Timer)
 {
 [self.speedometer_Timer invalidate];
 self.speedometer_Timer = nil;
 }
 self.speedometerCurrentValue =  arc4random() % 100; // Generate Random value between 0 to 100. //

self.speedometer_Timer = [NSTimer  scheduledTimerWithTimeInterval:2 target:self selector:@selector(setSpeedometerCurrentValue) userInfo:nil repeats:YES];

self.speedometerReading.text = [NSString stringWithFormat:@"%.2f",self.speedometerCurrentValue];

// Calculate the Angle by which the needle should rotate //
 [self calculateDeviationAngle];
 }
 #pragma mark -
 #pragma mark Speedometer needle Rotation View Methods

-(void) rotateIt:(float)angl
 {
 [UIView beginAnimations:nil context:nil];
 [UIView setAnimationDuration:0.01f];

[self.needleImageView setTransform: CGAffineTransformMakeRotation((M_PI / 180) *angl)];

[UIView commitAnimations];
 }

addMeterViewContents – In this method we set and add different images like needle,speedometer etc, with respect to the view frame.
In this method we also move the needle center to one of its end points in order to rotate a needle by a well defined axis and for this we set its anchor points y co-ordinate twice its current y co-ordinate.

rotateIt:(float)angl – In this method first we find min and max angle by addHoc process and then set the needle in default position which is 0;

calculateDeviationAngle – In this method we calculate the angle of deviation by which the needle should rotate.

rotateNeedle – In this method we rotate the needle by the calculate angle of deviation.

setSpeedometerCurrentValue – In this method we generate random value between 0 and 100 using arc4random function.

Step 3: Save,build and run the project. Now you can see custom speedometer with a moving needle on random generated values, with the value displayed on the label below.

You can download the source code SpeedometerDemo.