android自己写的类似刻度尺的东西

http://www.iteye.com/topic/1113856


刚学android不久,因为公司项目要求,写了个类似刻度尺的东西,拿出来献丑,希望大家给点意见。

先上代码,注:KeduView中的浮点数计算我没处理(因为精度问题,浮点数直接计算出来的结果可能不对)。StaffView中的浮点数计算我进行了处理,我在Arithmetic中封装了加减乘除方法:

Java代码   收藏代码
  1. package com.hyx.suiyipaint;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Context;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.BitmapFactory;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Color;  
  9. import android.graphics.Matrix;  
  10. import android.graphics.Paint;  
  11. import android.graphics.Rect;  
  12. import android.os.Bundle;  
  13. import android.view.KeyEvent;  
  14. import android.view.MotionEvent;  
  15. import android.view.SurfaceHolder;  
  16. import android.view.SurfaceView;  
  17. import android.view.View;  
  18. import android.widget.ImageView;  
  19. import android.widget.LinearLayout;  
  20.   
  21. public class KeduActivity extends Activity {  
  22.       
  23.     private ImageView kedu_tiao;  
  24.     private LinearLayout kedu_linear;  
  25.     private LinearLayout staff_linear;  
  26.       
  27.     private KeduView kedu;  
  28.     private StaffView staff;  
  29.   
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.kedu);  
  34.           
  35.         kedu_linear = (LinearLayout)findViewById(R.id.kedu_linear);  
  36.         kedu = new KeduView(this, 0f, 0.1f);  
  37.         kedu_linear.addView(kedu);  
  38.         staff_linear = (LinearLayout)findViewById(R.id.staff_linear);  
  39.         staff = new StaffView(this7.5f, 0.5f, "cm");  
  40.         staff_linear.addView(staff);  
  41.           
  42.         kedu_tiao = (ImageView)findViewById(R.id.kedu_tiao);  
  43.         kedu_tiao.setOnTouchListener(keduListener);  
  44.           
  45.     }  
  46.       
  47.     private ImageView.OnTouchListener keduListener = new ImageView.OnTouchListener(){  
  48.         private float initx = 0;  
  49.         @Override  
  50.         public boolean onTouch(View v, MotionEvent event) {  
  51.             switch(event.getAction()){  
  52.                 case MotionEvent.ACTION_DOWN:  
  53.                     initx = event.getX();  
  54.                     break;  
  55.                 case MotionEvent.ACTION_MOVE:  
  56.                     float lastx = event.getX();  
  57.                     if(lastx > initx + 5){  
  58.                         kedu.draw(1);  
  59.                         initx = lastx;  
  60.                     }else if(lastx < initx -5){  
  61.                         kedu.draw(-1);  
  62.                         initx = lastx;  
  63.                     }  
  64.                     break;  
  65.             }  
  66.             return true;  
  67.         }  
  68.     };  
  69.       
  70.     class KeduView extends SurfaceView implements SurfaceHolder.Callback, Runnable{  
  71.           
  72.         private SurfaceHolder mSurfaceHolder = null;    
  73.         private Canvas canvas;  
  74.         //画布背景  
  75.         private Bitmap background;  
  76.         //刻度游标  
  77.         private Bitmap pointer;  
  78.   
  79.         //总刻度数  
  80.         private static final int KEDU_COUNT = 25;  
  81.         //刻度最小值  
  82.         private float init_min;  
  83.         //每个刻度的单位值  
  84.         private float interval;  
  85.   
  86.         public KeduView(Context context, float init_min, float interval) {  
  87.             super(context);  
  88.             mSurfaceHolder = this.getHolder();    
  89.             mSurfaceHolder.addCallback(this);    
  90.             this.setFocusable(true);  
  91.             background = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_bg);  
  92.             pointer = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_pointer);  
  93.               
  94.             this.init_min = init_min;  
  95.             this.interval = interval;  
  96.         }  
  97.   
  98.         @Override  
  99.         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  100.               
  101.         }  
  102.   
  103.         @Override  
  104.         public void surfaceCreated(SurfaceHolder holder) {  
  105.             new Thread(this).start();  
  106.         }  
  107.   
  108.         @Override  
  109.         public void surfaceDestroyed(SurfaceHolder holder) {  
  110.               
  111.         }  
  112.           
  113.         @Override  
  114.         public void run() {  
  115.             draw(0);  
  116.         }  
  117.         //每次X轴移动的像素  
  118.         private static final int MOVE = 10;  
  119.         //游标在最左边时X轴的位置  
  120.         private static final int INIT_POINTER_LEFT = 20;  
  121.         //游标在最右边时X轴的位置  
  122.         private static final int INIT_POINTER_RIGHT = 270;  
  123.         //游标顶端Y轴的位置  
  124.         private static final int INIT_POINTER_TOP = 36;  
  125.         //底下刻度数字最左边的X轴位置  
  126.         private static final int INIT_NUM_X = 18;  
  127.         //结果的X轴位置  
  128.         private static final int RESULT_X = 36;  
  129.         //结果的Y轴位置  
  130.         private static final int RESULT_Y = 25;  
  131.         //结果的字体大小  
  132.         private static final int RESULT_SIZE = 24;  
  133.         //游标X轴的位置  
  134.         private int POINTER_X = INIT_POINTER_LEFT;  
  135.         //底下刻度数字X轴位置  
  136.         private int NUM_X = INIT_NUM_X;  
  137.         //底下刻度数字的Y轴位置  
  138.         private int NUM_Y = 85;  
  139.         //结果  
  140.         private float result = 0;  
  141.   
  142.         /** 
  143.          * @param direction 方向,-1向左,1向右,0不动 
  144.          */  
  145.         public void draw(int direction){  
  146.             //获取画布  
  147.             canvas = mSurfaceHolder.lockCanvas();  
  148.             if (mSurfaceHolder == null || canvas == null) {    
  149.                 return;    
  150.             }  
  151.             canvas.drawColor(Color.WHITE);  
  152.             Paint paint = new Paint();    
  153.             paint.setAntiAlias(true);    
  154.             paint.setColor(Color.GRAY);  
  155.             canvas.drawBitmap(background, new Matrix(), paint);  
  156.               
  157.             switch(direction){  
  158.                 case -1:  
  159.                     POINTER_X -= MOVE;  
  160.                     result -= interval;  
  161.                     if(result <= 0){  
  162.                         result  = init_min;  
  163.                         POINTER_X = INIT_POINTER_LEFT;  
  164.                     }else{  
  165.                         if(POINTER_X < INIT_POINTER_LEFT){  
  166.                             POINTER_X = INIT_POINTER_RIGHT;  
  167.                             result = init_min;  
  168.                             init_min -= KEDU_COUNT * interval;  
  169.                         }  
  170.                     }  
  171.                     break;  
  172.                 case 1:  
  173.                     POINTER_X += MOVE;  
  174.                     result += interval;  
  175.                     if(POINTER_X > INIT_POINTER_RIGHT){  
  176.                         POINTER_X = INIT_POINTER_LEFT;  
  177.                         init_min += KEDU_COUNT * interval;  
  178.                         result = init_min;  
  179.                     }  
  180.                     break;  
  181.             }  
  182.             canvas.drawBitmap(pointer, POINTER_X, INIT_POINTER_TOP, paint);  
  183.               
  184.             for(int i=0; i<6; i++){  
  185.                 if(i == 0){  
  186.                     NUM_X = INIT_NUM_X;  
  187.                 }  
  188.                 canvas.drawText(Float.toString(i * 5f * interval + init_min), NUM_X, NUM_Y, paint);  
  189.                 NUM_X += 50;  
  190.             }  
  191.               
  192.             paint.setColor(Color.BLACK);  
  193.             paint.setTextSize(RESULT_SIZE);  
  194.             canvas.drawText(Float.toString(result), RESULT_X, RESULT_Y, paint);  
  195.             //解锁画布,提交画好的图像    
  196.             mSurfaceHolder.unlockCanvasAndPost(canvas);    
  197.         }  
  198.     }  
  199.   
  200.     class StaffView extends SurfaceView implements SurfaceHolder.Callback, Runnable{  
  201.   
  202.         private SurfaceHolder mSurfaceHolder = null;    
  203.         private Canvas canvas;  
  204.         private Paint paint;  
  205.         //画布背景  
  206.         private Bitmap background;  
  207.         //刻度  
  208.         private Bitmap staff;  
  209.         //刻度游标  
  210.         private Bitmap pointer;  
  211.         //初始值  
  212.         private float initValue;  
  213.         //刻度单位最小值  
  214.         private float interval;  
  215.         //单位  
  216.         private String unit;  
  217.         //是否初始  
  218.         private boolean isInit = true;  
  219.           
  220.         public StaffView(Context context, float initValue, float interval, String unit) {  
  221.             super(context);  
  222.             mSurfaceHolder = this.getHolder();    
  223.             mSurfaceHolder.addCallback(this);    
  224.               
  225.             paint = new Paint();  
  226.               
  227.             this.setFocusable(true);  
  228.             background = BitmapFactory.decodeResource(getResources(), R.drawable.staff_bg);  
  229.             staff = BitmapFactory.decodeResource(getResources(), R.drawable.staff0);  
  230.             pointer = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_pointer);  
  231.     
  232.             this.initValue = initValue;  
  233.             this.interval = interval;  
  234.             this.unit = unit;  
  235.         }  
  236.   
  237.         @Override  
  238.         public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  239.               
  240.         }  
  241.   
  242.         @Override  
  243.         public void surfaceCreated(SurfaceHolder holder) {  
  244.             new Thread(this).start();  
  245.         }  
  246.   
  247.         @Override  
  248.         public void surfaceDestroyed(SurfaceHolder holder) {  
  249.               
  250.         }  
  251.   
  252.         @Override  
  253.         public void run() {  
  254.             draw(0);  
  255.         }  
  256.           
  257.         private int move = 10;  //每次移动的距离  
  258.         private int initBx = 77;    //图片上X坐标  
  259.         private int by = 0//图片上Y坐标  
  260.         private int bw = 258;   //图片宽度  
  261.         private int bh = 31;    //图片高度  
  262.         private int sx = 18;    //画布X坐标  
  263.         private int sy = 36;    //画布Y坐标  
  264.         private int jiange = 51//大刻度之间距离  
  265.         private int num_left = 33;  //最左边数字到左边的距离  
  266.         private int RESULT_X = 36;  //结果的X轴位置  
  267.         private int RESULT_Y = 25;  //结果的Y轴位置  
  268.         private int RESULT_SIZE = 24;   //结果的字体大小  
  269.           
  270.         private float result = 0;  
  271.         /** 
  272.          * @param direction 方向,-1向左,1向右,0不动 
  273.          */  
  274.         public void draw(int direction){  
  275.             //获取画布  
  276.             canvas = mSurfaceHolder.lockCanvas();  
  277.             if (mSurfaceHolder == null || canvas == null) {    
  278.                 return;    
  279.             }  
  280.             canvas.drawColor(Color.WHITE);  
  281.               
  282.             paint.setAntiAlias(true);    
  283.             paint.setColor(Color.GRAY);  
  284.               
  285.             canvas.drawBitmap(background, new Matrix(), paint);  
  286.               
  287.             if(isInit){  
  288.                 result = initValue;  
  289.             }else{  
  290.                 switch(direction){  
  291.                     case 1:  
  292.                         result = Arithmetic.add(result, interval);  
  293.                         break;  
  294.                     case -1:  
  295.                         result = Arithmetic.sub(result, interval);  
  296.                         if(result < 0){  
  297.                             result = 0;  
  298.                         }  
  299.                         break;  
  300.                 }  
  301.             }  
  302.             initStaff();  
  303.   
  304.             canvas.drawBitmap(pointer, 14336, paint);  
  305.   
  306.             Paint reslutPaint = new Paint();  
  307.             reslutPaint.setColor(Color.BLACK);  
  308.             reslutPaint.setTextSize(RESULT_SIZE);  
  309.             canvas.drawText(Float.toString(result) + " " + unit, RESULT_X, RESULT_Y, reslutPaint);  
  310.             //解锁画布,提交画好的图像    
  311.             mSurfaceHolder.unlockCanvasAndPost(canvas);    
  312.         }  
  313.           
  314.         private void initStaff(){  
  315.             int bx = initBx;  
  316.             int num_x = num_left;  
  317.             int mod = 0;  
  318.             int midd = 2;  
  319.             if(result != 0){  
  320.                 mod = (int)(Arithmetic.div(result, interval, 1) % 5);  
  321.                 bx += mod * move;  
  322.             }  
  323.             if(mod >= 3){  
  324.                 midd = 1;  
  325.                 num_x += (5 - mod) * move;  
  326.             }else{  
  327.                 num_x -= mod * move;  
  328.             }  
  329.             float text = 0;  
  330.             for(int i=0; i<5; i++){  
  331.                 if(i < midd){  
  332.                     text = result - mod * interval - (midd - i) * 5 * interval;  
  333.                 }else if(i == midd){  
  334.                     text = result - mod * interval;  
  335.                 }else{  
  336.                     text += 5 * interval;  
  337.                 }  
  338.                 text = Arithmetic.round(text, 1);  
  339.                 if(text >= 0){  
  340.                     canvas.drawText(Float.toString(text), num_x, 85, paint);  
  341.                 }  
  342.                 num_x += jiange;  
  343.             }  
  344.   
  345.             //要绘制的图片矩形区域设置  
  346.             Rect src = new Rect();  
  347.             src.left = bx;  
  348.             src.top = by;  
  349.             src.right = bx + bw;  
  350.             src.bottom = bh;  
  351.               
  352.             //要绘制的画布矩形区域设置  
  353.             Rect dst = new Rect();  
  354.             dst.left = sx;  
  355.             dst.top = sy;  
  356.             dst.right = sx + bw;  
  357.             dst.bottom = sy + bh;  
  358.             canvas.drawBitmap(staff, src, dst, paint);  
  359.         }  
  360.           
  361.         private float initx = 0;  
  362.         @Override  
  363.         public boolean onTouchEvent(MotionEvent event) {  
  364.             switch(event.getAction()){  
  365.                 case MotionEvent.ACTION_DOWN:  
  366.                     initx = event.getX();  
  367.                     break;  
  368.                 case MotionEvent.ACTION_MOVE:  
  369.                     float lastx = event.getX();  
  370.                     if(lastx > initx + 5){  
  371.                         isInit = false;  
  372.                         draw(-1);  
  373.                         initx = lastx;  
  374.                     }else if(lastx < initx -5){  
  375.                         isInit = false;  
  376.                         draw(1);  
  377.                         initx = lastx;  
  378.                     }  
  379.                     break;  
  380.             }  
  381.                 return true;  
  382.         }  
  383.           
  384.         public float getResult(){  
  385.             return result;  
  386.         }  
  387.     }  
  388.       
  389.       
  390.     @Override  
  391.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  392.         if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){  
  393.             staff.isInit = false;  
  394.             staff.draw(-1);  
  395.             return true;  
  396.         }if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){  
  397.             staff.isInit = false;  
  398.             staff.draw(1);  
  399.             return true;  
  400.         }  
  401.         return super.onKeyDown(keyCode, event);  
  402.     }  
  403. }  

 布局文件:

Xml代码   收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:orientation="vertical"  
  5.   android:layout_width="fill_parent"  
  6.   android:layout_height="fill_parent"  
  7.   android:gravity="center"  
  8.   android:background="#fff">  
  9.     <LinearLayout   
  10.         android:id="@+id/kedu_linear"   
  11.         android:layout_width="294dp"   
  12.         android:layout_height="101dp"/>  
  13.     <ImageView   
  14.         android:layout_height="wrap_content"    
  15.         android:layout_width="wrap_content"  
  16.         android:id="@+id/kedu_tiao"   
  17.         android:src="@drawable/kedu_wheel_01"  
  18.         android:layout_margin="20dp"/>  
  19.     <LinearLayout   
  20.         android:id="@+id/staff_linear"   
  21.         android:layout_width="294dp"   
  22.         android:layout_height="101dp"/>  
  23.       
  24. </LinearLayout>  

 附件是运行效果截图。




Arithmetic类的源码如下:

Java代码   收藏代码
  1. package com.hyx.suiyipaint;  
  2.   
  3. import java.math.BigDecimal;  
  4.   
  5.   
  6. public class Arithmetic {  
  7.   
  8.     /** 
  9.      * 提供精确的加法运算。 
  10.      * @param v1 被加数 
  11.      * @param v2 加数 
  12.      * @return 两个参数的和 
  13.      */   
  14.     public static float add(float v1, float v2){  
  15.         BigDecimal b1 = new BigDecimal(Float.toString(v1));  
  16.         BigDecimal b2 = new BigDecimal(Float.toString(v2));  
  17.         return b1.add(b2).floatValue();   
  18.     }  
  19.       
  20.     /** 
  21.      * 提供精确的减法运算。 
  22.      * @param v1 被减数 
  23.      * @param v2 减数 
  24.      * @return 两个参数的差 
  25.      */   
  26.     public static float sub(float v1, float v2){  
  27.         BigDecimal b1 = new BigDecimal(Float.toString(v1));  
  28.         BigDecimal b2 = new BigDecimal(Float.toString(v2));  
  29.         return b1.subtract(b2).floatValue();  
  30.     }  
  31.       
  32.     /** 
  33.      * 提供精确的乘法运算。 
  34.      * @param v1 被乘数 
  35.      * @param v2 乘数 
  36.      * @return 两个参数的积 
  37.      */  
  38.   
  39.     public static float mul(float v1, float v2){  
  40.         BigDecimal b1 = new BigDecimal(Float.toString(v1));  
  41.         BigDecimal b2 = new BigDecimal(Float.toString(v2));  
  42.         return b1.multiply(b2).floatValue();  
  43.     }   
  44.       
  45.     /** 
  46.      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 
  47.      * 定精度,以后的数字四舍五入。 
  48.      * @param v1 被除数 
  49.      * @param v2 除数 
  50.      * @param scale 表示表示需要精确到小数点以后几位。 
  51.      * @return 两个参数的商 
  52.      */  
  53.   
  54.     public static float div(float v1, float v2, int scale){  
  55.         if(scale<0){  
  56.             scale = 0;  
  57.         }  
  58.         BigDecimal b1 = new BigDecimal(Float.toString(v1));  
  59.         BigDecimal b2 = new BigDecimal(Float.toString(v2));  
  60.         return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).floatValue();  
  61.   
  62.     }  
  63.       
  64.     /** 
  65.      * 提供精确的小数位四舍五入处理。 
  66.      * @param v 需要四舍五入的数字 
  67.      * @param scale 小数点后保留几位 
  68.      * @return 四舍五入后的结果 
  69.      */  
  70.     public static float round(float v, int scale){  
  71.         if(scale<0){  
  72.             scale = 0;  
  73.         }  
  74.         BigDecimal b = new BigDecimal(Float.toString(v));  
  75.         BigDecimal one = new BigDecimal("1");  
  76.         return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).floatValue();  
  77.   
  78.     }  
  79.   
  80. }  

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值