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

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


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

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

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

布局文件:

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. </LinearLayout>

附件是运行效果截图。




Arithmetic类的源码如下:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值