基于android平台的模拟血压计实现(surfaceView的熟练使用)

这个是我根据上一篇文章的温度计改的血压计,因为客户对温度计还有血压计的需求是一样的,所以,我就选择了偷懒,直接用温度计的代码改了一概,就成了血压计的了

  1 package com.example.test;
  2 
  3 
  4 
  5 import android.content.Context;
  6 import android.graphics.Bitmap;
  7 import android.graphics.Canvas;
  8 import android.graphics.Color;
  9 import android.graphics.Paint;
 10 import android.graphics.RectF;
 11 import android.util.AttributeSet;
 12 import android.util.TypedValue;
 13 import android.view.SurfaceHolder;
 14 import android.view.SurfaceView;
 15 
 16 
 17 
 18 
 19 import java.text.DecimalFormat;
 20 
 21 /**
 22  * Created by yinxiaofei on 2016/1/13.
 23  */
 24 
 25 public class Sphygmomanometer extends SurfaceView implements SurfaceHolder.Callback ,Runnable{
 26 
 27     private SurfaceHolder mHolder;
 28     private Canvas mCanvas;
 29 
 30     //定义刻度的范围
 31     int temperatureRange=5;
 32     //定义一个盘快的范围
 33     private RectF mRange=new RectF();
 34     //定义温度计的宽度和中心宽度
 35     int mWith;
 36     int mHeight;
 37     int centerWith;
 38     int centerHeight;
 39     //定义总的宽度
 40 
 41     //定义温度计刻度总长度
 42     int temperatureAllLong;
 43 
 44     //定义一下水银的宽度
 45     int MercuryWith;
 46     //十的倍数的线长度
 47     int MaxLineLong;
 48     //五的倍数的线的长度
 49     int MidLineLong;
 50     //其他刻度线的长度
 51     int MinLineLong;
 52     //刻度间隔
 53     int scaleLong;
 54     //定义温度计距离画布的上宽度
 55     int abHeight;
 56 
 57     //绘制线条的画笔
 58     private Paint LinePaint;
 59     //绘制文本的画笔
 60     private Paint TextPaint;
 61 
 62     //设置温度上升的速度
 63     private volatile float mSpeed=0;
 64 
 65     //设置背景图
 66     private Bitmap mBitmap;
 67 
 68     /**
 69      * 定义初始温度,当前显示正在变化也就是显示的温度,还有目标温度
 70      * 其中,初始温度不变,
 71      * 当前温度是有程序根据不同的速度和目标温度计算出来的,
 72      * 目标温度则是由仪器传送过来的数据
 73      */
 74     private float BeginTenperature= (float) 0;
 75     private int EndTenperrature=300;
 76     private volatile float CurrentTemperature= (float) 60;
 77     float TargetTemperature=120;
 78 
 79     /**
 80      * 定义每一秒绘制的次数
 81      */
 82     int everySecondTime=50;
 83 
 84     //设置文字的大小
 85     private float mTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,25,getResources().getDisplayMetrics());
 86     private float mSymbolTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,35,getResources().getDisplayMetrics());
 87     private float mShowSymbolTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,45,getResources().getDisplayMetrics());
 88     /**
 89      * 用户绘制的线程
 90      */
 91     private Thread mThread;
 92     /**
 93      * 根据目标温度改变要显示的当前温度的线程
 94      */
 95     private Thread mChangeTemperatureThread;
 96 
 97     /**
 98      * 设置一个标志位,用于线程的开启还是关闭的标志
 99      * @param context
100      */
101     private Boolean isRunning;
102     private DecimalFormat fomat;//格式化float
103 
104     public Sphygmomanometer(Context context) {
105         this(context, null);
106     }
107 
108     public Sphygmomanometer(Context context, AttributeSet attrs) {
109         super(context,attrs);
110         mHolder=getHolder();
111         mHolder.addCallback(this);
112 
113     }
114     @Override
115     protected void onMeasure(int with,int height){
116         super.onMeasure(with, height);
117         this.mWith=getMeasuredWidth()/2;
118         this.mHeight=getMeasuredHeight();
119         //这里先把中心设置在屏幕的中心
120         this.centerWith=mWith/2;
121         this.centerHeight=mHeight/2;
122         //设置水银的宽度,暂时设置为总宽度的十五分之一
123         MercuryWith=mWith/15;
124         MinLineLong=MercuryWith;
125         MidLineLong=MinLineLong*8/5;
126         MaxLineLong=MidLineLong*3/2;
127         //temperatureAllLong表示温度刻度总长度
128         temperatureAllLong=mHeight*7/10;
129         //设置刻度间隔,包含了刻度线的长度
130         scaleLong=temperatureAllLong/temperatureRange/10;//表示一个温度十个刻度
131 
132 
133         abHeight=mHeight/10;
134     }
135     @Override
136     public void surfaceCreated(SurfaceHolder surfaceHolder) {
137         //初始化画笔
138         LinePaint=new Paint();
139         //去锯齿
140         LinePaint.setAntiAlias(true);
141         LinePaint.setColor(Color.BLACK);
142         LinePaint.setStyle(Paint.Style.STROKE);
143         LinePaint.setStrokeWidth(1);
144         //初始化画笔
145         TextPaint=new Paint();
146         TextPaint.setColor(Color.BLACK);
147         TextPaint.setTextSize(mTextSize);
148         TextPaint.setShader(null);
149         //初始化温度计的范围
150         mRange=new RectF(0,0,mWith,mHeight);
151         isRunning=true;
152         mThread =new Thread(this);
153         mThread.start();
154 
155     }
156 
157     @Override
158     public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
159 
160     }
161 
162     @Override
163     public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
164 
165         isRunning=false;
166 
167     }
168 
169     @Override
170     public void run() {
171         //不断进行绘制
172         while(isRunning){
173             long start=System.currentTimeMillis();
174             draw();
175             long end=System.currentTimeMillis();
176             if(end-start<everySecondTime){
177                 //这里控制一下,一秒绘制二十次。也就是五十秒绘制一次
178                 try {
179                     Thread.sleep(everySecondTime-(end-start));
180                 } catch (InterruptedException e) {
181                     e.printStackTrace();
182                 }
183             }
184         }
185     }
186 
187     private void draw() {
188 
189         try {
190             mCanvas=mHolder.lockCanvas();
191             //这里要判断是不是为空,之因为在用户点击了home以后,可能已经执行到这里
192             if(mCanvas!=null)
193             {
194                 //这里是开始绘制自己要的东西
195                 //先绘制背景,
196                 drawBg();
197                 //绘制水银的高度还有,显示体温
198                 drawShowHeightAndShow();
199             }
200         } catch (Exception e) {
201            // e.printStackTrace();这里的异常不处理,
202         } finally {
203             if(mCanvas!=null){
204                 mHolder.unlockCanvasAndPost(mCanvas);
205             }
206         }
207 
208     }
209 
210     private void drawShowHeightAndShow() {
211 
212         //这里控制水银的上升速度
213         //这里要除以20,是因为血压计的刻度值,到温度计的刻度值,是二十倍的换算,主要是偷懒
214         float difference=Math.abs(TargetTemperature-CurrentTemperature)/60;
215         /**
216          * //这里定义一个boolean来控制是使用加法还是减法,其中true表示当前温度小于
217          * 目标温度,要使用加法,false表示当前温度大于目标温度,要使用减法。
218          */
219         boolean addORsub=CurrentTemperature>=TargetTemperature?false:true;
220         if(difference==0||difference<=0.005){
221             mSpeed=0;
222             CurrentTemperature=TargetTemperature;
223         }else{
224             if (difference>2){
225                 mSpeed= (float) 0.03;
226             }else{
227                 if(difference>1){
228                     mSpeed= (float) 0.025;
229                 }else{
230                     if(difference>0.5){
231                         mSpeed= (float) 0.015;
232                     }else{
233                         if(difference>0.3){
234                             mSpeed= (float) 0.012;
235                         }else{
236                             if(difference>0.2){
237                                 mSpeed= (float) 0.009;
238                             }else{
239                                 mSpeed= (float) 0.008;
240                             }
241 
242                         }
243                     }
244                 }
245             }
246         }
247         if(addORsub){
248             CurrentTemperature+=mSpeed*100;
249         }else{
250             CurrentTemperature-=mSpeed*100;
251         }
252 
253         //
254 
255         Paint RectPaint=new Paint();
256         RectPaint.setStyle(Paint.Style.FILL);
257 //        RectPaint.setColor(getResources().getColor(R.color.theme_color));
258 //        这里主要是对温度的显示,画矩形的过程中,唯一改变的就是Top这一个值了
259         //这里(CurrentTemperature-BeginTenperature)/20表示的是刻度值的换算,从温度计过度到血压计的刻度值
260         if(Math.abs(CurrentTemperature-TargetTemperature)>0.8)
261         mCanvas.drawRect(centerWith-MercuryWith/2,
262                 (scaleLong)*10*(temperatureRange)+abHeight*2-
263                         (CurrentTemperature-BeginTenperature)/60*10*scaleLong,
264                 centerWith+MercuryWith/2,
265                 (scaleLong)*10*(temperatureRange)+abHeight*2,
266                 RectPaint);
267         else{
268             mCanvas.drawRect(centerWith-MercuryWith/2,
269                     (scaleLong)*10*(temperatureRange)+abHeight*2-
270                             (TargetTemperature-BeginTenperature)/60*10*scaleLong,
271                     centerWith+MercuryWith/2,
272                     (scaleLong)*10*(temperatureRange)+abHeight*2,
273                     RectPaint);
274         }
275 
276         //这里开始画显示的数字
277         Paint ShowNumberTextPaint=new Paint();
278         ShowNumberTextPaint.setColor(Color.BLACK);
279         ShowNumberTextPaint.setTextSize(mShowSymbolTextSize);
280         ShowNumberTextPaint.setShader(null);
281         fomat = new DecimalFormat("##0.0");
282         float display = Float.parseFloat(fomat.format(trueTemperature));
283         mCanvas.drawText(display + " kpa",
284                 mWith * 3 / 2 - ShowNumberTextPaint.getTextSize() * 2,
285                 temperatureAllLong / 2 - ShowNumberTextPaint.getTextSize(),
286                 ShowNumberTextPaint
287         );
288 
289 
290         mCanvas.drawText(display + " kpa",
291                 mWith*3/2- ShowNumberTextPaint.getTextSize() * 2,
292                 temperatureAllLong/2+ShowNumberTextPaint.getTextSize(),
293                 ShowNumberTextPaint
294         );
295 
296     }
297 
298     private void drawBg() {
299         mCanvas.drawColor(Color.WHITE);
300 //        mCanvas.drawLine(0, 0, mWith, mHeight, LinePaint);
301         //画右边的刻度
302         //定义每一个长刻度的高度
303         float everyTemparaturHeight=(scaleLong)*10;
304         for(int i=0;i<temperatureRange;i++){
305             mCanvas.drawLine(centerWith + MercuryWith / 2,
306                     everyTemparaturHeight * i + abHeight * 2,//这里加上两倍的上距离
307                     centerWith + MercuryWith / 2 + MidLineLong,
308                     everyTemparaturHeight * i + abHeight * 2, LinePaint);
309             for(int j=1;j<=9;j++){
310                 if(j==5){
311                     mCanvas.drawLine(centerWith+MercuryWith/2,
312                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
313                             centerWith+MercuryWith/2+MaxLineLong,
314                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
315                     mCanvas.drawText(EndTenperrature-30 - i * 60 + "", centerWith + MercuryWith / 2 + MaxLineLong + MinLineLong / 3,
316                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2 + TextPaint.getTextSize() / 2 , TextPaint);
317                 }else{
318                     mCanvas.drawLine(centerWith+MercuryWith/2,
319                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
320                             centerWith+MercuryWith/2+MinLineLong,
321                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
322                 }
323 
324             }
325 
326         }
327         //画左边的刻度
328         for(int i=0;i<temperatureRange;i++){
329             mCanvas.drawLine(centerWith-MercuryWith/2,
330                     everyTemparaturHeight*i+abHeight*2,
331                     centerWith-MercuryWith/2-MaxLineLong,
332                     everyTemparaturHeight*i+abHeight*2,LinePaint);
333             if(EndTenperrature-i*60>99)
334             mCanvas.drawText(EndTenperrature-i*60+"", centerWith - (MercuryWith/2+MaxLineLong+MinLineLong/3)-TextPaint.getTextSize()*3/2,
335                     everyTemparaturHeight * i + TextPaint.getTextSize() / 2+abHeight*2, TextPaint);
336             else if(EndTenperrature-i*60>9)
337                 mCanvas.drawText(EndTenperrature-i*60+"", centerWith - (MercuryWith/2+MaxLineLong+MinLineLong/3)-TextPaint.getTextSize(),
338                         everyTemparaturHeight * i + TextPaint.getTextSize() / 2+abHeight*2, TextPaint);
339             else if(EndTenperrature-i*60>=0)
340                 mCanvas.drawText(EndTenperrature-i*60+"", centerWith - (MercuryWith/2+MaxLineLong+MinLineLong/3)-TextPaint.getTextSize()/100,
341                         everyTemparaturHeight * i + TextPaint.getTextSize() / 2+abHeight*2, TextPaint);
342             
343             for(int j=1;j<=9;j++){
344                 if(j==5){
345                     mCanvas.drawLine(centerWith-MercuryWith/2,
346                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
347                             centerWith-MercuryWith/2-MidLineLong,
348                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
349                 }else{
350                     mCanvas.drawLine(centerWith-MercuryWith/2,
351                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
352                             centerWith-MercuryWith/2-MinLineLong,
353                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
354                 }
355 
356             }
357             //画最后一个刻度
358             if(i==temperatureRange-1){
359                 mCanvas.drawLine(centerWith-MercuryWith/2,
360                         everyTemparaturHeight*(i+1)+abHeight*2,
361                         centerWith-MercuryWith/2-MaxLineLong,
362                         everyTemparaturHeight*(i+1)+abHeight*2,LinePaint);
363                 mCanvas.drawText(EndTenperrature-(i+1)*60+"", centerWith - (MercuryWith/2+MaxLineLong+MinLineLong/3)-TextPaint.getTextSize(),
364                         everyTemparaturHeight * (i+1) + TextPaint.getTextSize() / 2+abHeight*2, TextPaint);
365             }
366         }
367         //画红色的园
368         Paint CirclePaint=new Paint();
369         CirclePaint.setStyle(Paint.Style.FILL);
370  //       CirclePaint.setColor(getResources().getColor(R.color.theme_color));
371         mCanvas.drawCircle(centerWith,
372                 everyTemparaturHeight*(temperatureRange)+abHeight*2+MercuryWith,
373                 MercuryWith*3/2,CirclePaint);
374         //画摄氏度的符号
375         Paint symbolTextPaint=new Paint();
376         symbolTextPaint.setColor(Color.BLACK);
377         symbolTextPaint.setTextSize(mSymbolTextSize);
378         symbolTextPaint.setShader(null);
379         mCanvas.drawText("BP",
380                 centerWith - MaxLineLong / 2 - MercuryWith / 2 - symbolTextPaint.getTextSize() / 2,
381                 abHeight * 2 - symbolTextPaint.getTextSize(),
382                 symbolTextPaint
383         );
384         mCanvas.drawText("BP",
385                 centerWith + MaxLineLong / 2 + MercuryWith / 2 - symbolTextPaint.getTextSize() / 2,
386                 abHeight * 2 - symbolTextPaint.getTextSize(),
387                 symbolTextPaint
388         );
389 
390         //绘制显示数字的符号和虚线
391         Paint ShowsymbolTextPaint=new Paint();
392         ShowsymbolTextPaint.setColor(Color.BLACK);
393         ShowsymbolTextPaint.setTextSize(mShowSymbolTextSize);
394         ShowsymbolTextPaint.setShader(null);
395 
396         mCanvas.drawText("- - - - - - - -",
397                 mWith * 3 / 2 - ShowsymbolTextPaint.getTextSize() * 2,
398                 temperatureAllLong/2,
399                 ShowsymbolTextPaint
400         );
401 
402     }
403 
404     private float trueTemperature = 0;
405 
406     public void setTargetTemperature(float targetTemperature) {
407         trueTemperature = targetTemperature;
408         if(targetTemperature<0){
409             targetTemperature = 0;
410         }
411         if(targetTemperature>EndTenperrature){
412             targetTemperature = EndTenperrature;
413         }
414         TargetTemperature = targetTemperature;
415     }
416 }

至于xml的布局文件,请参考上一篇文章,其实也和简单

posted @ 2016-06-08 23:55  晓风飞雨  阅读(1261)  评论(0编辑  收藏  举报