基於android平台的模擬溫度計測量實時溫度的實現--(surfaceView的熟練使用)


上來老規矩,先上圖,這個溫度計是我為一個商用的app專門開發的,商業原因,其他的截圖還有代碼不可以公布,但是這個溫度計的源碼是可以公布的,這個代碼是我自己精心設計的,里面有不少的計算公式,感覺自己還是設計的很巧妙的模擬也很逼真,尤其是在測量溫度的時候,溫度計水銀的高度變化,這個是要用有一個速度來控制的,尤其是這個溫度的變化還是實時的,也是不可控的,所以我們要考慮到溫度的隨時變化,根據當前的目標溫度還有當前水銀柱的高度,老確定當前的水銀上升速度是多少。當然了這只是一個方面,還有其他的,比如字體的大小還有刻度的長度,這些全部都是要根據畫布的大小來變化的,這個在我的代碼中也有體現。下面這個類的代碼可以直接通過最后一個函數setTargetTemperature調用,設置實時的溫度,溫度計會顯示出來實時的變化。希望大家可以用到。

  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 import java.text.DecimalFormat;
 19 
 20 /**
 21  * Created by yinxiaofei on 2016/1/13.
 22  */
 23 
 24 public class Thermometer extends SurfaceView implements SurfaceHolder.Callback ,Runnable{
 25 
 26     private SurfaceHolder mHolder;
 27     private Canvas mCanvas;
 28 
 29     //定義溫度的范圍
 30     int temperatureRange=12;
 31     //定義一個盤快的范圍
 32     private RectF mRange=new RectF();
 33     //定義溫度計的寬度和中心寬度
 34     int mWith;
 35     int mHeight;
 36     int centerWith;
 37     int centerHeight;
 38     //定義總的寬度
 39 
 40     //定義溫度計刻度總長度
 41     int temperatureAllLong;
 42 
 43     //定義一下水銀的寬度
 44     int MercuryWith;
 45     //十的倍數的線長度
 46     int MaxLineLong;
 47     //五的倍數的線的長度
 48     int MidLineLong;
 49     //其他刻度線的長度
 50     int MinLineLong;
 51     //刻度間隔
 52     int scaleLong;
 53     //定義溫度計距離畫布的上寬度
 54     int abHeight;
 55 
 56     //繪制線條的畫筆
 57     private Paint LinePaint;
 58     //繪制文本的畫筆
 59     private Paint TextPaint;
 60 
 61     //設置溫度上升的速度
 62     private volatile float mSpeed=0;
 63 
 64     //設置背景圖
 65     private Bitmap mBitmap;
 66 
 67     /**
 68      * 定義初始溫度,當前顯示正在變化也就是顯示的溫度,還有目標溫度
 69      * 其中,初始溫度不變,
 70      * 當前溫度是有程序根據不同的速度和目標溫度計算出來的,
 71      * 目標溫度則是由儀器傳送過來的數據
 72      */
 73     private float BeginTenperature= (float) 30;
 74     private int EndTenperature=42;
 75     private volatile float CurrentTemperature= (float) 30;
 76 
 77 
 78 
 79     float TargetTemperature=39;
 80 
 81     /**
 82      * 定義每一秒繪制的次數
 83      */
 84     int everySecondTime=100;
 85 
 86     //設置文字的大小
 87     private float mTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,25,getResources().getDisplayMetrics());
 88     private float mSymbolTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,35,getResources().getDisplayMetrics());
 89     private float mShowSymbolTextSize= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT,45,getResources().getDisplayMetrics());
 90     /**
 91      * 用戶繪制的線程
 92      */
 93     private Thread mThread;
 94     /**
 95      * 根據目標溫度改變要顯示的當前溫度的線程
 96      */
 97     private Thread mChangeTemperatureThread;
 98 
 99     /**
100      * 設置一個標志位,用於線程的開啟還是關閉的標志
101      * @param context
102      */
103     private Boolean isRunning;
104 
105     private DecimalFormat fomat;//格式化float
106 
107     public Thermometer(Context context) {
108         this(context, null);
109     }
110 
111     public Thermometer(Context context, AttributeSet attrs) {
112         super(context,attrs);
113         mHolder=getHolder();
114         mHolder.addCallback(this);
115 
116     }
117     @Override
118     protected void onMeasure(int with,int height){
119         super.onMeasure(with, height);
120         this.mWith=getMeasuredWidth()/2;
121         this.mHeight=getMeasuredHeight();
122         //這里先把中心設置在屏幕的中心
123         this.centerWith=mWith/2;
124         this.centerHeight=mHeight/2;
125         //設置水銀的寬度,暫時設置為總寬度的十五分之一
126         MercuryWith=mWith/15;
127         MinLineLong=MercuryWith;
128         MidLineLong=MinLineLong*8/5;
129         MaxLineLong=MidLineLong*3/2;
130         //temperatureAllLong表示溫度刻度總長度
131         temperatureAllLong=mHeight*7/10;
132         //設置刻度間隔,包含了刻度線的長度
133         scaleLong=temperatureAllLong/temperatureRange/10;//表示一個溫度十個刻度
134 
135 
136         abHeight=mHeight/12;
137     }
138     @Override
139     public void surfaceCreated(SurfaceHolder surfaceHolder) {
140         //初始化畫筆
141         LinePaint=new Paint();
142         //去鋸齒
143         LinePaint.setAntiAlias(true);
144         LinePaint.setColor(Color.BLACK);
145         LinePaint.setStyle(Paint.Style.STROKE);
146         LinePaint.setStrokeWidth(1);
147         //初始化畫筆
148         TextPaint=new Paint();
149         TextPaint.setColor(Color.BLACK);
150         TextPaint.setTextSize(mTextSize);
151         TextPaint.setShader(null);
152         //初始化溫度計的范圍
153         mRange=new RectF(0,0,mWith,mHeight);
154         isRunning=true;
155         mThread =new Thread(this);
156         mThread.start();
157 
158     }
159 
160     @Override
161     public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
162 
163     }
164 
165     @Override
166     public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
167 
168         isRunning=false;
169 
170     }
171 
172     @Override
173     public void run() {
174         //不斷進行繪制
175         while(isRunning){
176             long start=System.currentTimeMillis();
177             draw();
178             long end=System.currentTimeMillis();
179             if(end-start<everySecondTime){
180                 //這里控制一下,一秒繪制二十次。也就是五十秒繪制一次
181                 try {
182                     Thread.sleep(everySecondTime-(end-start));
183                 } catch (InterruptedException e) {
184                     e.printStackTrace();
185                 }
186             }
187         }
188     }
189 
190     private void draw() {
191 
192         try {
193             mCanvas=mHolder.lockCanvas();
194             //這里要判斷是不是為空,之因為在用戶點擊了home以后,可能已經執行到這里
195             if(mCanvas!=null)
196             {
197                 //這里是開始繪制自己要的東西
198                 //先繪制背景,
199                 drawBg();
200                 //繪制水銀的高度還有,顯示體溫
201                 drawShowHeightAndShow();
202             }
203         } catch (Exception e) {
204            // e.printStackTrace();這里的異常不處理,
205         } finally {
206             if(mCanvas!=null){
207                 mHolder.unlockCanvasAndPost(mCanvas);
208             }
209         }
210 
211     }
212 
213     private void drawShowHeightAndShow() {
214 
215         //這里控制水銀的上升速度
216         float difference=Math.abs(TargetTemperature-CurrentTemperature);
217         /**
218          * //這里定義一個boolean來控制是使用加法還是減法,其中true表示當前溫度小於
219          * 目標溫度,要使用加法,false表示當前溫度大於目標溫度,要使用減法。
220          */
221         boolean addORsub=CurrentTemperature>=TargetTemperature?false:true;
222         if(difference==0||difference<=0.005){
223             mSpeed=0;
224             CurrentTemperature=TargetTemperature;
225         }else{
226             if (difference>2){
227                 mSpeed= (float) 0.03;
228             }else{
229                 if(difference>1){
230                     mSpeed= (float) 0.025;
231                 }else{
232                     if(difference>0.5){
233                         mSpeed= (float) 0.015;
234                     }else{
235                         if(difference>0.3){
236                             mSpeed= (float) 0.012;
237                         }else{
238                             if(difference>0.2){
239                                 mSpeed= (float) 0.009;
240                             }else{
241                                 mSpeed= (float) 0.008;
242                             }
243 
244                         }
245                     }
246                 }
247             }
248         }
249         if(addORsub){
250             CurrentTemperature+=20*mSpeed;
251         }else{
252             CurrentTemperature-=20*mSpeed;
253         }
254 
255         //
256 
257         Paint RectPaint=new Paint();
258         RectPaint.setStyle(Paint.Style.FILL);
259 //        RectPaint.setColor(getResources().getColor(R.color.theme_color));
260 //        這里主要是對溫度的顯示,畫矩形的過程中,唯一改變的就是Top這一個值了
261         if(Math.abs(CurrentTemperature-TargetTemperature)>0.32)
262         mCanvas.drawRect(centerWith-MercuryWith/2,
263                 (scaleLong)*10*(temperatureRange)+abHeight*2-
264                         (CurrentTemperature-BeginTenperature)*10*scaleLong,
265                 centerWith+MercuryWith/2,
266                 (scaleLong)*10*(temperatureRange)+abHeight*2,
267                 RectPaint);
268         else{
269             mCanvas.drawRect(centerWith-MercuryWith/2,
270                     (scaleLong)*10*(temperatureRange)+abHeight*2-
271                             (TargetTemperature-BeginTenperature)*10*scaleLong,
272                     centerWith+MercuryWith/2,
273                     (scaleLong)*10*(temperatureRange)+abHeight*2,
274                     RectPaint);
275         }
276 
277         //這里開始畫顯示的數字
278         Paint ShowNumberTextPaint=new Paint();
279         ShowNumberTextPaint.setColor(Color.BLACK);
280         ShowNumberTextPaint.setTextSize(mShowSymbolTextSize);
281         ShowNumberTextPaint.setShader(null);
282         fomat = new DecimalFormat("##0.0");
283         float display = Float.parseFloat(fomat.format(trueTemperature));
284         mCanvas.drawText(display + "",
285                 mWith * 3 / 2 - ShowNumberTextPaint.getTextSize() * 2,
286                 temperatureAllLong / 2 - ShowNumberTextPaint.getTextSize(),
287                 ShowNumberTextPaint
288         );
289         mCanvas.drawText(display + "",
290                 mWith*3/2- ShowNumberTextPaint.getTextSize() * 2,
291                 temperatureAllLong/2+ShowNumberTextPaint.getTextSize(),
292                 ShowNumberTextPaint
293         );
294 
295     }
296 
297     private void drawBg() {
298         mCanvas.drawColor(Color.WHITE);
299 //        mCanvas.drawLine(0, 0, mWith, mHeight, LinePaint);
300         //畫右邊的刻度
301         //定義每一個長刻度的高度
302         float everyTemparaturHeight=(scaleLong)*10;
303         for(int i=0;i<temperatureRange;i++){
304             mCanvas.drawLine(centerWith+MercuryWith/2,
305                     everyTemparaturHeight*i+abHeight*2,//這里加上兩倍的上距離
306                     centerWith+MercuryWith/2+MaxLineLong,
307                     everyTemparaturHeight*i+abHeight*2,LinePaint);
308             mCanvas.drawText(EndTenperature-i+"",centerWith+MercuryWith/2+MaxLineLong+MinLineLong/3,
309                     everyTemparaturHeight*i+TextPaint.getTextSize()/2+abHeight*2,TextPaint);
310             for(int j=1;j<=9;j++){
311                 if(j==5){
312                     mCanvas.drawLine(centerWith+MercuryWith/2,
313                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
314                             centerWith+MercuryWith/2+MidLineLong,
315                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
316                 }else{
317                     mCanvas.drawLine(centerWith+MercuryWith/2,
318                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,
319                             centerWith+MercuryWith/2+MinLineLong,
320                             everyTemparaturHeight*i+j*(scaleLong)+abHeight*2,LinePaint);
321                 }
322 
323             }
324             //畫最后一個刻度
325             if(i==temperatureRange-1){
326 
327                 mCanvas.drawLine(centerWith+MercuryWith/2,
328                         everyTemparaturHeight*(i+1)+abHeight*2,//這里加上兩倍的上距離
329                         centerWith+MercuryWith/2+MaxLineLong,
330                         everyTemparaturHeight*(i+1)+abHeight*2,LinePaint);
331                 mCanvas.drawText(EndTenperature-(i+1)+"",centerWith+MercuryWith/2+MaxLineLong+MinLineLong/3,
332                         everyTemparaturHeight*(i+1)+TextPaint.getTextSize()/2+abHeight*2,TextPaint);
333             }
334         }
335         //畫左邊的刻度
336         for(int i=0;i<temperatureRange;i++){
337             mCanvas.drawLine(centerWith-MercuryWith/2,
338                     everyTemparaturHeight*i+abHeight*2,
339                     centerWith-MercuryWith/2-MaxLineLong,
340                     everyTemparaturHeight*i+abHeight*2,LinePaint);
341             mCanvas.drawText(EndTenperature-i+"", centerWith - (MercuryWith/2+MaxLineLong+MinLineLong/3)-TextPaint.getTextSize(),
342                     everyTemparaturHeight * i + TextPaint.getTextSize() / 2+abHeight*2, TextPaint);
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(EndTenperature-(i+1)+"", 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("℃",
380                 centerWith - MaxLineLong / 2 - MercuryWith / 2 - symbolTextPaint.getTextSize() / 2,
381                 abHeight * 2 - symbolTextPaint.getTextSize(),
382                 symbolTextPaint
383         );
384         mCanvas.drawText("℃",
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         mCanvas.drawText("℃",
396                 mWith*3/2,
397                 temperatureAllLong/2-ShowsymbolTextPaint.getTextSize(),
398                 ShowsymbolTextPaint
399         );
400         mCanvas.drawText("- - - - - - - -",
401                 mWith+ShowsymbolTextPaint.getTextSize()*3,
402                 temperatureAllLong/2,
403                 ShowsymbolTextPaint
404         );
405         mCanvas.drawText("℃",
406                 mWith*3/2,
407                 temperatureAllLong/2+ShowsymbolTextPaint.getTextSize(),
408                 ShowsymbolTextPaint
409         );
410 
411     }
412 
413     private float trueTemperature  =0 ;
414 
415     public void setTargetTemperature(float targetTemperature) {
416         trueTemperature = targetTemperature;
417         if(targetTemperature<30){
418             targetTemperature = 30;
419         }
420         if(targetTemperature>EndTenperature){
421             targetTemperature = EndTenperature;
422         }
423         TargetTemperature = targetTemperature;
424     }
425 }

布局文件直接在你的xml當中添加以下語句就可以了

<com.example.test.Sphygmomanometer
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         />

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM