My scale is an android application to measure things with excellent UI which makes you feel like you are working with a scale, which has not measurement limit.
A scale is shown, user can scroll it and select any reading according to one’s weight or height etc.
MyScaleView
Create a class MyScaleView.java and extend this class with View class. All logics will be done in overide method onDraw(Canvas canvas) of view class, ehere we pla with the canvas to draw scale.
package com.android.myscale;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MyScaleView extends View {
static int screenSize = 480;
static private float pxmm = screenSize / 67.f;
int width, height, midScreenPoint;
float startingPoint = 0;
float downpoint = 0, movablePoint = 0, downPointClone = 0;
private float mainPoint = 0, mainPointClone = 0;
boolean isDown = false;
boolean isUpward = false;
private boolean isMove;
private onViewUpdateListener mListener;
private Paint gradientPaint;
private float rulersize = 0;
private Paint rulerPaint, textPaint, goldenPaint;
private int endPoint;
boolean isSizeChanged = false;
float userStartingPoint = 0f;
private int scaleLineSmall;
private int scaleLineMedium;
private int scaleLineLarge;
private int textStartPoint;
private int yellowLineStrokeWidth;
boolean isFirstTime = true;
public MyScaleView(Context context, AttributeSet foo) {
super(context, foo);
if (!isInEditMode()) {
init(context);
}
}
private void init(Context context) {
yellowLineStrokeWidth = (int) getResources().getDimension(R.dimen.yellow_line_stroke_width);
gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rulersize = pxmm * 10;
rulerPaint = new Paint();
rulerPaint.setStyle(Paint.Style.STROKE);
rulerPaint.setStrokeWidth(0);
rulerPaint.setAntiAlias(false);
rulerPaint.setColor(Color.WHITE);
textPaint = new TextPaint();
Typeface typeface = Typeface.createFromAsset(context.getAssets(), "fonts/segoeuil.ttf");
textPaint.setTypeface(typeface);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setStrokeWidth(0);
textPaint.setAntiAlias(true);
textPaint.setTextSize(getResources().getDimension(R.dimen.txt_size));
textPaint.setColor(Color.WHITE);
goldenPaint = new Paint();
goldenPaint.setStyle(Paint.Style.FILL_AND_STROKE);
goldenPaint.setColor(context.getResources().getColor(R.color.yellow));
goldenPaint.setStrokeWidth(yellowLineStrokeWidth);
goldenPaint.setStrokeJoin(Paint.Join.ROUND);
goldenPaint.setStrokeCap(Paint.Cap.ROUND);
goldenPaint.setPathEffect(new CornerPathEffect(10));
goldenPaint.setAntiAlias(true);
scaleLineSmall = (int) getResources().getDimension(R.dimen.scale_line_small);
scaleLineMedium = (int) getResources().getDimension(R.dimen.scale_line_medium);
scaleLineLarge = (int) getResources().getDimension(R.dimen.scale_line_large);
textStartPoint = (int) getResources().getDimension(R.dimen.text_start_point);
}
public void setUpdateListener(onViewUpdateListener onViewUpdateListener) {
mListener = onViewUpdateListener;
}
@Override
public void onSizeChanged(int w, int h, int oldW, int oldH) {
width = w;
height = h;
screenSize = height;
pxmm = screenSize / 67.f;
midScreenPoint = height / 2;
endPoint = width - 40;
if (isSizeChanged) {
isSizeChanged = false;
mainPoint = midScreenPoint - (userStartingPoint * 10 * pxmm);
}
gradientPaint.setShader(new LinearGradient(0, 0, width, rulersize, getResources().getColor(R.color.green),
getResources().getColor(R.color.transparent_white), android.graphics.Shader.TileMode.MIRROR));
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawRect(0f, midScreenPoint - (rulersize / 2), width, midScreenPoint + (rulersize / 2), gradientPaint);
startingPoint = mainPoint;
for (int i = 1;; ++i) {
if (startingPoint > screenSize) {
break;
}
startingPoint = startingPoint + pxmm;
int size = (i % 10 == 0) ? scaleLineLarge : (i % 5 == 0) ? scaleLineMedium : scaleLineSmall;
canvas.drawLine(endPoint - size, startingPoint, endPoint, startingPoint, rulerPaint);
if (i % 10 == 0) {
System.out.println("done " + i);
canvas.drawText((i / 10) + " cm", endPoint - textStartPoint, startingPoint + 8, textPaint);
}
}
canvas.drawLine(0f, midScreenPoint, width - 20, midScreenPoint, goldenPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("touch event fire");
mainPointClone = mainPoint;
if (mainPoint < 0) {
mainPointClone = -mainPoint;
}
float clickPoint = ((midScreenPoint + mainPointClone) / (pxmm * 10));
if (mListener != null) {
mListener.onViewUpdate((midScreenPoint + mainPointClone) / (pxmm * 10));
}
System.out.println("click point" + clickPoint + "");
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isMove = true;
isDown = false;
isUpward = false;
downpoint = event.getY();
downPointClone = event.getY();
break;
case MotionEvent.ACTION_MOVE:
movablePoint = event.getY();
if (downPointClone > movablePoint) {
/**
* if user first starts moving downward and then upwards then
* this method makes it to move upward
*/
if (isUpward) {
downpoint = event.getY();
downPointClone = downpoint;
}
isDown = true;
isUpward = false;
/**
* make this differnce of 1, otherwise it moves very fast and
* nothing shows clearly
*/
if (downPointClone - movablePoint > 1) {
mainPoint = mainPoint + (-(downPointClone - movablePoint));
downPointClone = movablePoint;
invalidate();
}
} else {
// downwards
if (isMove) {
/**
* if user first starts moving upward and then downwards,
* then this method makes it to move upward
*/
if (isDown) {
downpoint = event.getY();
downPointClone = downpoint;
}
isDown = false;
isUpward = true;
if (movablePoint - downpoint > 1) {
mainPoint = mainPoint + ((movablePoint - downPointClone));
downPointClone = movablePoint;
if (mainPoint > 0) {
mainPoint = 0;
isMove = false;
}
invalidate();
}
}
}
break;
case MotionEvent.ACTION_UP:
System.out.println("up");
default:
break;
}
return true;
}
public void setStartingPoint(float point) {
userStartingPoint = point;
isSizeChanged = true;
if (isFirstTime) {
isFirstTime = false;
if (mListener != null) {
mListener.onViewUpdate(point);
}
}
}
}
Use MyScaleView.java class in your xml to create the view
Crate a xml file activity_my_scale.xml
<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:background=”#123456″
android:gravity=”right|center_vertical”
android:orientation=”horizontal” >
<TextView
android:id=”@+id/txt_height”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textAppearance=”?android:attr/textAppearanceLarge”
android:textColor=”@android:color/white” />
<com.android.myscale.MyScaleView
android:id=”@+id/my_scale”
android:layout_width=”200dp”
android:layout_height=”match_parent”
android:layout_gravity=”right”
android:background=”#123456″ />
</LinearLayout>
MyScaleActivity class
Create a class My scaleActivity
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MyScaleActivity extends Activity {
private TextView txtValue;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_scale);
final MyScaleView rulerViewMm = (MyScaleView) findViewById(R.id.my_scale);
txtValue = (TextView) findViewById(R.id.txt_height);
rulerViewMm.setStartingPoint(70);
rulerViewMm.setUpdateListener(new onViewUpdateListener() {
@Override
public void onViewUpdate(float result) {
float value = (float) Math.round(result * 10f) / 10f;
txtValue.setText(value + ” cm”);
}
});
}
}
Thats all!
A scale will be shown and you can select any reading just by scrolling it.
nice job, save my day, its realy helpful
LikeLike
Good one, but reading should start from Zero
LikeLike
Great….(y) …..
LikeLike
super. simple and helpfull
LikeLike
please upload java and xml files. I did not work it
LikeLike
Updated, Please check
LikeLike
Hi nice tutorial,Can you post the source code,If you post source code that would be more helpful to me.
LikeLike
Hello joe, I have posted the source code, Please check
LikeLike
Really very helpful, very brief and easy to understand….looking forward with such blogs from you kimmi ….keep up(y)
LikeLike
send me the your code
LikeLike
Hi kimmi i tried your code it showed the view but touch listener not working.in code there is some typo mistake in TouchEvent
what is it mean if (mainPoint movablePoint)
LikeLike
please attach the code plzzzzzzzzzzzzzzzzzzzzzzzzzz
LikeLike
Hello Partik, I have posted the source file, Please check
Thanks
LikeLike
where i can get the whole code for this not works properly
LikeLike
Thank U
LikeLike
Its Not Work Properly Dude.
LikeLike
where i can download the code.this code not working properly
LikeLike
Hello you made my day.thank u
LikeLiked by 1 person
what if i want it in horizontal at bottom. pls rply asap
LikeLike
@Amit, Soon I will share my second blog with Horizontal scrolling of scale
LikeLike
Nice article. Very helpful. Keep the good work up!
LikeLike
Very nice article. really useful. can you tell me how can we provide the upper and lower limit for scaling ?
LikeLike
@Karan, I will work on this. And will update the article
Thanks
LikeLike
Hello! Nice tutorial. Can you help me with this: lets say i have another scale (exact copy) next to the first one. How can i make two scales move simultaneously when i scroll just one?
LikeLike
I’ll work on this and will update the code
soon
LikeLike
what is 480 in your code?
LikeLike
480 is static screen size. you can evaluate screen size programmatically on which part you want to show your scale.
LikeLike