论坛首页 移动开发技术论坛

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

浏览 10082 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-08-24   最后修改:2011-08-29

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

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

package com.hyx.suiyipaint;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class KeduActivity extends Activity {
	
	private ImageView kedu_tiao;
	private LinearLayout kedu_linear;
	private LinearLayout staff_linear;
	
	private KeduView kedu;
	private StaffView staff;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.kedu);
		
		kedu_linear = (LinearLayout)findViewById(R.id.kedu_linear);
		kedu = new KeduView(this, 0f, 0.1f);
		kedu_linear.addView(kedu);
		staff_linear = (LinearLayout)findViewById(R.id.staff_linear);
		staff = new StaffView(this, 7.5f, 0.5f, "cm");
		staff_linear.addView(staff);
		
		kedu_tiao = (ImageView)findViewById(R.id.kedu_tiao);
		kedu_tiao.setOnTouchListener(keduListener);
		
	}
	
	private ImageView.OnTouchListener keduListener = new ImageView.OnTouchListener(){
		private float initx = 0;
		@Override
		public boolean onTouch(View v, MotionEvent event) {
			switch(event.getAction()){
				case MotionEvent.ACTION_DOWN:
					initx = event.getX();
					break;
				case MotionEvent.ACTION_MOVE:
					float lastx = event.getX();
					if(lastx > initx + 5){
						kedu.draw(1);
						initx = lastx;
					}else if(lastx < initx -5){
						kedu.draw(-1);
						initx = lastx;
					}
					break;
			}
			return true;
		}
	};
	
	class KeduView extends SurfaceView implements SurfaceHolder.Callback, Runnable{
		
		private SurfaceHolder mSurfaceHolder = null;  
		private Canvas canvas;
		//画布背景
		private Bitmap background;
		//刻度游标
		private Bitmap pointer;

		//总刻度数
		private static final int KEDU_COUNT = 25;
		//刻度最小值
		private float init_min;
		//每个刻度的单位值
		private float interval;

		public KeduView(Context context, float init_min, float interval) {
			super(context);
			mSurfaceHolder = this.getHolder();  
			mSurfaceHolder.addCallback(this);  
			this.setFocusable(true);
			background = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_bg);
			pointer = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_pointer);
			
			this.init_min = init_min;
			this.interval = interval;
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			
		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			new Thread(this).start();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			
		}
		
		@Override
		public void run() {
			draw(0);
		}
		//每次X轴移动的像素
		private static final int MOVE = 10;
		//游标在最左边时X轴的位置
		private static final int INIT_POINTER_LEFT = 20;
		//游标在最右边时X轴的位置
		private static final int INIT_POINTER_RIGHT = 270;
		//游标顶端Y轴的位置
		private static final int INIT_POINTER_TOP = 36;
		//底下刻度数字最左边的X轴位置
		private static final int INIT_NUM_X = 18;
		//结果的X轴位置
		private static final int RESULT_X = 36;
		//结果的Y轴位置
		private static final int RESULT_Y = 25;
		//结果的字体大小
		private static final int RESULT_SIZE = 24;
		//游标X轴的位置
		private int POINTER_X = INIT_POINTER_LEFT;
		//底下刻度数字X轴位置
		private int NUM_X = INIT_NUM_X;
		//底下刻度数字的Y轴位置
		private int NUM_Y = 85;
		//结果
		private float result = 0;

		/**
		 * @param direction 方向,-1向左,1向右,0不动
		 */
		public void draw(int direction){
			//获取画布
			canvas = mSurfaceHolder.lockCanvas();
			if (mSurfaceHolder == null || canvas == null) {  
				return;  
			}
			canvas.drawColor(Color.WHITE);
			Paint paint = new Paint();  
			paint.setAntiAlias(true);  
			paint.setColor(Color.GRAY);
			canvas.drawBitmap(background, new Matrix(), paint);
			
			switch(direction){
				case -1:
					POINTER_X -= MOVE;
					result -= interval;
					if(result <= 0){
						result  = init_min;
						POINTER_X = INIT_POINTER_LEFT;
					}else{
						if(POINTER_X < INIT_POINTER_LEFT){
							POINTER_X = INIT_POINTER_RIGHT;
							result = init_min;
							init_min -= KEDU_COUNT * interval;
						}
					}
					break;
				case 1:
					POINTER_X += MOVE;
					result += interval;
					if(POINTER_X > INIT_POINTER_RIGHT){
						POINTER_X = INIT_POINTER_LEFT;
						init_min += KEDU_COUNT * interval;
						result = init_min;
					}
					break;
			}
			canvas.drawBitmap(pointer, POINTER_X, INIT_POINTER_TOP, paint);
			
			for(int i=0; i<6; i++){
				if(i == 0){
					NUM_X = INIT_NUM_X;
				}
				canvas.drawText(Float.toString(i * 5f * interval + init_min), NUM_X, NUM_Y, paint);
				NUM_X += 50;
			}
			
			paint.setColor(Color.BLACK);
			paint.setTextSize(RESULT_SIZE);
			canvas.drawText(Float.toString(result), RESULT_X, RESULT_Y, paint);
			//解锁画布,提交画好的图像  
			mSurfaceHolder.unlockCanvasAndPost(canvas);  
		}
	}

	class StaffView extends SurfaceView implements SurfaceHolder.Callback, Runnable{

		private SurfaceHolder mSurfaceHolder = null;  
		private Canvas canvas;
		private Paint paint;
		//画布背景
		private Bitmap background;
		//刻度
		private Bitmap staff;
		//刻度游标
		private Bitmap pointer;
		//初始值
		private float initValue;
		//刻度单位最小值
		private float interval;
		//单位
		private String unit;
		//是否初始
		private boolean isInit = true;
		
		public StaffView(Context context, float initValue, float interval, String unit) {
			super(context);
			mSurfaceHolder = this.getHolder();  
			mSurfaceHolder.addCallback(this);  
			
			paint = new Paint();
			
			this.setFocusable(true);
			background = BitmapFactory.decodeResource(getResources(), R.drawable.staff_bg);
			staff = BitmapFactory.decodeResource(getResources(), R.drawable.staff0);
			pointer = BitmapFactory.decodeResource(getResources(), R.drawable.kedu_pointer);
  
			this.initValue = initValue;
			this.interval = interval;
			this.unit = unit;
		}

		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
			
		}

		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			new Thread(this).start();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			
		}

		@Override
		public void run() {
			draw(0);
		}
		
		private int move = 10;	//每次移动的距离
		private int initBx = 77;	//图片上X坐标
		private int by = 0;	//图片上Y坐标
		private int bw = 258;	//图片宽度
		private int bh = 31;	//图片高度
		private int sx = 18;	//画布X坐标
		private int sy = 36;	//画布Y坐标
		private int jiange = 51; //大刻度之间距离
		private int num_left = 33;	//最左边数字到左边的距离
		private int RESULT_X = 36;	//结果的X轴位置
		private int RESULT_Y = 25;	//结果的Y轴位置
		private int RESULT_SIZE = 24;	//结果的字体大小
		
		private float result = 0;
		/**
		 * @param direction 方向,-1向左,1向右,0不动
		 */
		public void draw(int direction){
			//获取画布
			canvas = mSurfaceHolder.lockCanvas();
			if (mSurfaceHolder == null || canvas == null) {  
				return;  
			}
			canvas.drawColor(Color.WHITE);
			
			paint.setAntiAlias(true);  
			paint.setColor(Color.GRAY);
			
			canvas.drawBitmap(background, new Matrix(), paint);
			
			if(isInit){
				result = initValue;
			}else{
				switch(direction){
					case 1:
						result = Arithmetic.add(result, interval);
						break;
					case -1:
						result = Arithmetic.sub(result, interval);
						if(result < 0){
							result = 0;
						}
						break;
				}
			}
			initStaff();

			canvas.drawBitmap(pointer, 143, 36, paint);

			Paint reslutPaint = new Paint();
			reslutPaint.setColor(Color.BLACK);
			reslutPaint.setTextSize(RESULT_SIZE);
			canvas.drawText(Float.toString(result) + " " + unit, RESULT_X, RESULT_Y, reslutPaint);
			//解锁画布,提交画好的图像  
			mSurfaceHolder.unlockCanvasAndPost(canvas);  
		}
		
		private void initStaff(){
			int bx = initBx;
			int num_x = num_left;
			int mod = 0;
			int midd = 2;
			if(result != 0){
				mod = (int)(Arithmetic.div(result, interval, 1) % 5);
				bx += mod * move;
			}
			if(mod >= 3){
				midd = 1;
				num_x += (5 - mod) * move;
			}else{
				num_x -= mod * move;
			}
			float text = 0;
			for(int i=0; i<5; i++){
				if(i < midd){
					text = result - mod * interval - (midd - i) * 5 * interval;
				}else if(i == midd){
					text = result - mod * interval;
				}else{
					text += 5 * interval;
				}
				text = Arithmetic.round(text, 1);
				if(text >= 0){
					canvas.drawText(Float.toString(text), num_x, 85, paint);
				}
				num_x += jiange;
			}

			//要绘制的图片矩形区域设置
			Rect src = new Rect();
			src.left = bx;
			src.top = by;
			src.right = bx + bw;
			src.bottom = bh;
			
			//要绘制的画布矩形区域设置
			Rect dst = new Rect();
			dst.left = sx;
			dst.top = sy;
			dst.right = sx + bw;
			dst.bottom = sy + bh;
			canvas.drawBitmap(staff, src, dst, paint);
		}
		
		private float initx = 0;
		@Override
		public boolean onTouchEvent(MotionEvent event) {
			switch(event.getAction()){
				case MotionEvent.ACTION_DOWN:
					initx = event.getX();
					break;
				case MotionEvent.ACTION_MOVE:
					float lastx = event.getX();
					if(lastx > initx + 5){
						isInit = false;
						draw(-1);
						initx = lastx;
					}else if(lastx < initx -5){
						isInit = false;
						draw(1);
						initx = lastx;
					}
					break;
			}
				return true;
		}
		
		public float getResult(){
			return result;
		}
	}
	
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){
			staff.isInit = false;
			staff.draw(-1);
			return true;
		}if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){
			staff.isInit = false;
			staff.draw(1);
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
}

 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:gravity="center"
  android:background="#fff">
    <LinearLayout 
    	android:id="@+id/kedu_linear" 
    	android:layout_width="294dp" 
    	android:layout_height="101dp"/>
    <ImageView 
    	android:layout_height="wrap_content"  
    	android:layout_width="wrap_content"
    	android:id="@+id/kedu_tiao" 
    	android:src="@drawable/kedu_wheel_01"
    	android:layout_margin="20dp"/>
    <LinearLayout 
    	android:id="@+id/staff_linear" 
    	android:layout_width="294dp" 
    	android:layout_height="101dp"/>
    
</LinearLayout>

 附件是运行效果截图。


  • 大小: 14 KB
   发表时间:2011-08-25  
求源码。。。。
0 请登录后投票
   发表时间:2011-08-25  
zhaoxuyang6 写道
求源码。。。。

源码已经全部贴出来了啊。
0 请登录后投票
   发表时间:2011-08-25   最后修改:2011-08-25
zhaoxuyang6 写道
求源码。。。。

   Arithmetic类的源码如下:

package com.hyx.suiyipaint;

import java.math.BigDecimal;


public class Arithmetic {

	/**
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */ 
	public static float add(float v1, float v2){
		BigDecimal b1 = new BigDecimal(Float.toString(v1));
		BigDecimal b2 = new BigDecimal(Float.toString(v2));
		return b1.add(b2).floatValue(); 
	}
	
	/**
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */ 
	public static float sub(float v1, float v2){
		BigDecimal b1 = new BigDecimal(Float.toString(v1));
		BigDecimal b2 = new BigDecimal(Float.toString(v2));
		return b1.subtract(b2).floatValue();
	}
	
	/**
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */

    public static float mul(float v1, float v2){
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.multiply(b2).floatValue();
    } 
    
    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */

    public static float div(float v1, float v2, int scale){
        if(scale<0){
        	scale = 0;
        }
        BigDecimal b1 = new BigDecimal(Float.toString(v1));
        BigDecimal b2 = new BigDecimal(Float.toString(v2));
        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).floatValue();

    }
    
    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static float round(float v, int scale){
        if(scale<0){
        	scale = 0;
        }
        BigDecimal b = new BigDecimal(Float.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).floatValue();

    }

}
0 请登录后投票
   发表时间:2011-08-25   最后修改:2011-08-25
zhaoxuyang6 写道
求源码。。。。


你个没骨气的家伙,好好跟哥学学!

哥最看不起求源码的人了!

看不起!

看不起!


LZ,求工程。。。。
0 请登录后投票
   发表时间:2011-08-25  
楼主给出项目图片就行了
0 请登录后投票
   发表时间:2011-08-26  

其实代码很简单,写不难懂,我把用到的图片给大家附上哈。

 

 

  • 大小: 5.4 KB
  • 大小: 7.7 KB
  • 大小: 2.9 KB
  • 大小: 5.3 KB
  • 大小: 84 Bytes
0 请登录后投票
   发表时间:2011-09-20  
楼主只需要写出大致的思路就行了,没有必要贴源码,看的人也累。
0 请登录后投票
   发表时间:2012-01-14  
仍然不怕死的求完整包,刚学几天,新手也需要学习封装类的思想
0 请登录后投票
   发表时间:2012-06-07  
哈哈求图片
0 请登录后投票
论坛首页 移动开发技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics