Android写的类似刻度尺的东西


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

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

  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>  

运行效果截图。

 

相关内容