由于项目需要,所以用SurfaceView写了一个自定义View,根据晓风飞雨的温度计源码做了一部分修改而来,效果是双汞柱 不废话了 先上源码
package view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import com.example.sc.bloodpressuremeter.R;
import java.text.DecimalFormat;
/**
* TODO: document your custom view class.
*/
public class Thermometer extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mHolder;
private Canvas mCanvas;
//定义左侧范围
int left_temperatureRange = 15;
//定义右侧范围
int right_temperatureRange = 20;
//定义一个盘快的范围
private RectF mRange = new RectF();
//定义温度计的宽度和中心宽度
int mWith;
int mHeight;
int centerWith;
int centerHeight;
//定义温度计刻度总长度
int temperatureAllLong;
//定义一下水银的宽度
int MercuryWith;
//十的倍数的线长度
int MaxLineLong;
//五的倍数的线的长度
int MidLineLong;
//其他刻度线的长度
int MinLineLong;
//左侧刻度间隔
float left_scaleLong;
//右侧刻度间隔
float right_scaleLong;
//定义温度计距离画布的上宽度
float abHeight;
//绘制线条的画笔
private Paint LinePaint;
//绘制文本的画笔
private Paint TextPaint1;
//绘制单位的画笔
private Paint TextPaint;
//设置温度上升的速度
private volatile float mSpeed = 0;
//kpa上升的速度
private volatile float mSpeed_kpa = 0;
//设置背景图
private Bitmap mBitmap;
/**
* 定义初始温度,当前显示正在变化也就是显示的温度,还有目标温度
* 其中,初始温度不变,
* 当前温度是有程序根据不同的速度和目标温度计算出来的,
* 目标温度则是由仪器传送过来的数据
*/
private float BeginTenperature = (float) 0;
private int left_EndTenperature = 300;
private int right_EndTenperature = 40;
private volatile float CurrentTemperature = (float) 0;
private volatile float CurrentLow_hight = (float) 0;
float TargetTemperature = 0;
float Targetlow_hight = 0;
/**
* 定义每一秒绘制的次数
*/
int everySecondTime = 100;
//设置文字的大小
private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT, 25, getResources().getDisplayMetrics());
private float mTextSize_ten = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT, 10, getResources().getDisplayMetrics());
private float mSymbolTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT, 35, getResources().getDisplayMetrics());
private float mShowSymbolTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SHIFT, 45, getResources().getDisplayMetrics());
/**
* 用户绘制的线程
*/
private Thread mThread;
/**
* 根据目标温度改变要显示的当前温度的线程
*/
private Thread mChangeTemperatureThread;
/**
* 设置一个标志位,用于线程的开启还是关闭的标志
*
* @param context
*/
private Boolean isRunning, isRunning_kpa;
private DecimalFormat fomat;//格式化float
public Thermometer(Context context) {
this(context, null);
}
public Thermometer(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
protected void onMeasure(int with, int height) {
super.onMeasure(with, height);
this.mWith = getMeasuredWidth() / 2;
this.mHeight = getMeasuredHeight();
//这里先把中心设置在屏幕的中心
this.centerWith = mWith / 2 + 100;
this.centerHeight = mHeight / 2;
//设置水银的宽度
MercuryWith = mWith / 6;
MinLineLong = MercuryWith;
MidLineLong = MinLineLong * 8 / 6;
MaxLineLong = MidLineLong * 3 / 2;
//temperatureAllLong表示温度刻度总长度
temperatureAllLong = mHeight * 9 / 10;
//设置左侧刻度间隔,包含了刻度线的长度
left_scaleLong = temperatureAllLong / left_temperatureRange / 10.0f;//表示一个温度十个刻度
//设置右侧刻度间隔,包含了刻度线的长度
right_scaleLong = temperatureAllLong / right_temperatureRange / 5.0f;//表示一个温度5个刻度
abHeight = mHeight / 30.0f;
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//初始化画笔
LinePaint = new Paint();
//去锯齿
LinePaint.setAntiAlias(true);
LinePaint.setColor(Color.WHITE);
LinePaint.setStyle(Paint.Style.STROKE);
LinePaint.setStrokeWidth(1);
//初始化画笔
TextPaint1 = new Paint();
TextPaint1.setColor(Color.WHITE);
TextPaint1.setTextSize(mTextSize);
TextPaint1.setShader(null);
//初始化画笔
TextPaint = new Paint();
TextPaint.setColor(Color.WHITE);
TextPaint.setTextSize(mTextSize_ten);
TextPaint.setShader(null);
//初始化温度计的范围
mRange = new RectF(0, 0, mWith, mHeight);
isRunning = true;
isRunning_kpa = true;
mThread = new Thread(this);
mThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
isRunning = false;
isRunning_kpa = false;
}
@Override
public void run() {
//不断进行绘制
while (isRunning) {
long start = System.currentTimeMillis();
draw();
long end = System.currentTimeMillis();
if (end - start < everySecondTime) {
//这里控制一下,一秒绘制二十次。也就是五十秒绘制一次
try {
Thread.sleep(everySecondTime - (end - start));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void draw() {
try {
mCanvas = mHolder.lockCanvas();
//这里要判断是不是为空,之因为在用户点击了home以后,可能已经执行到这里
if (mCanvas != null) {
//这里是开始绘制自己要的东西
//先绘制背景,
drawBg();
//绘制水银的高度还有,显示体温
drawShowHeightAndShow();
}
} catch (Exception e) {
// e.printStackTrace();这里的异常不处理,
} finally {
if (mCanvas != null) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
private void drawShowHeightAndShow() {
float kpa = Targetlow_hight;
float CurrentKpa = CurrentLow_hight;
//这里控制水银的上升速度
float difference = Math.abs(TargetTemperature - CurrentTemperature);
float difference_kpa = Math.abs(kpa - CurrentKpa);
/**
* //这里定义一个boolean来控制是使用加法还是减法,其中true表示当前温度小于
* 目标温度,要使用加法,false表示当前温度大于目标温度,要使用减法。
*/
boolean addORsub = CurrentTemperature >= TargetTemperature ? false : true;
boolean addOrsub_kpa = CurrentKpa >= kpa ? false : true;
if (difference == 0 || difference <= 0.005) {
mSpeed = 0;
CurrentTemperature = TargetTemperature;
} else {
if (difference > 20) {
mSpeed = (float) 0.5;
} else {
if (difference > 10) {
mSpeed = (float) 0.15;
} else {
mSpeed = (float) 0.05;
}
}
}
if (difference_kpa == 0 || difference_kpa <= 0.005) {
mSpeed_kpa = 0;
CurrentKpa = kpa;
} else {
if (difference_kpa > 2) {
mSpeed_kpa = (float) 0.6;
} else {
if (difference_kpa > 1) {
mSpeed_kpa = (float) 0.5;
} else {
mSpeed_kpa = (float) 0.1;
}
}
}
if (addORsub) {
CurrentTemperature += 20 * mSpeed;
} else {
CurrentTemperature -= 20 * mSpeed;
}
if (addOrsub_kpa) {
CurrentKpa += 2 * mSpeed_kpa;
} else {
CurrentKpa -= 2 * mSpeed_kpa;
}
//
Paint RightRectPaint = new Paint();
RightRectPaint.setColor(Color.WHITE);
RightRectPaint.setStyle(Paint.Style.FILL);
Paint LeftRectPaint = new Paint();
LeftRectPaint.setColor(Color.WHITE);
LeftRectPaint.setStyle(Paint.Style.FILL);
//这里主要是对温度的显示,画矩形的过程中,唯一改变的就是Top这一个值了
//左侧水银柱
if (Math.abs(CurrentTemperature - TargetTemperature) > 10) {
float left = (temperatureAllLong / (left_temperatureRange * 1.0f)) * (int) (CurrentTemperature / 20) + (CurrentTemperature % 20) / 2 * (left_scaleLong);
mCanvas.drawRect(centerWith - MercuryWith / 2, temperatureAllLong + abHeight * 2 - left, centerWith, temperatureAllLong + abHeight * 2, LeftRectPaint);
// float right = (temperatureAllLong / (right_temperatureRange * 1.0f)) * (int) (CurrentKpa / 2) + (CurrentKpa % 2) / 2 * 4 * (right_scaleLong);
float right = (temperatureAllLong / (left_temperatureRange * 1.0f)) * (int) (CurrentKpa / 20) + (CurrentKpa % 20) / 2 * (left_scaleLong);
mCanvas.drawRect(centerWith + MercuryWith / 8, temperatureAllLong + abHeight * 2 - right, centerWith + MercuryWith / 2, temperatureAllLong + abHeight * 2, RightRectPaint);
isRunning = true;
} else {
float left = (temperatureAllLong / (left_temperatureRange * 1.0f)) * (int) (TargetTemperature / 20) + (TargetTemperature % 20) / 2 * (left_scaleLong);
mCanvas.drawRect(centerWith - MercuryWith / 2, temperatureAllLong + abHeight * 2 - left, centerWith, temperatureAllLong + abHeight * 2, LeftRectPaint);
// float right = (temperatureAllLong / (right_temperatureRange * 1.0f)) * (int) (kpa / 2) + (kpa % 2) / 2 * 4 * (right_scaleLong);
float right = (temperatureAllLong / (left_temperatureRange * 1.0f)) * (int) (kpa / 20) + (kpa % 20) / 2 * (left_scaleLong);
mCanvas.drawRect(centerWith + MercuryWith / 8, temperatureAllLong + abHeight * 2 - right, centerWith + MercuryWith / 2, temperatureAllLong + abHeight * 2, RightRectPaint);
isRunning = false;
}
}
private void drawBg() {
mCanvas.drawColor(getResources().getColor(R.color.class_blue));
//画右边的刻度
//定义每一个长刻度的高度
float left_everyTemparaturHeight = temperatureAllLong / (left_temperatureRange * 1.0f);
float right_everyTemparaturHeight = temperatureAllLong / (right_temperatureRange * 1.0f);
mCanvas.drawLine(centerWith + MercuryWith / 2, abHeight * 2, centerWith + MercuryWith / 2, right_everyTemparaturHeight * 20 + abHeight * 2, LinePaint);
for (int i = 0; i < right_temperatureRange; i++) {
mCanvas.drawLine(centerWith + MercuryWith / 2, right_everyTemparaturHeight * i + abHeight * 2, centerWith + MercuryWith / 2 + MaxLineLong, right_everyTemparaturHeight * i + abHeight * 2, LinePaint);
if (i == 0) {
mCanvas.drawText(right_EndTenperature - i * 2 + "", centerWith + MercuryWith / 2 + MaxLineLong + MinLineLong / 3, right_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
mCanvas.drawText("Kpa", centerWith + MercuryWith / 2 + MaxLineLong + MinLineLong / 3 + 5, right_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2 + 15, TextPaint);
} else {
mCanvas.drawText(right_EndTenperature - i * 2 + "", centerWith + MercuryWith / 2 + MaxLineLong + MinLineLong / 3, right_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
}
for (int j = 1; j < 5; j++) {
mCanvas.drawLine(centerWith + MercuryWith / 2, right_everyTemparaturHeight * i + j * (right_scaleLong) + abHeight * 2, centerWith + MercuryWith / 2 + MinLineLong, right_everyTemparaturHeight * i + j * (right_scaleLong) + abHeight * 2, LinePaint);
}
//画最后一个刻度
if (i == right_temperatureRange - 1) {
mCanvas.drawLine(centerWith + MercuryWith / 2,
right_everyTemparaturHeight * (i + 1) + abHeight * 2,//这里加上两倍的上距离
centerWith + MercuryWith / 2 + MaxLineLong,
right_everyTemparaturHeight * (i + 1) + abHeight * 2, LinePaint);
mCanvas.drawText(right_EndTenperature - (i + 1) * 2 + "", centerWith + MercuryWith / 2 + MaxLineLong + MinLineLong / 3,
right_everyTemparaturHeight * (i + 1) + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
}
}
//画左边的刻度
mCanvas.drawLine(centerWith - MercuryWith / 2, abHeight * 2, centerWith - MercuryWith / 2, left_everyTemparaturHeight * left_temperatureRange + abHeight * 2, LinePaint);
for (int i = 0; i < left_temperatureRange; i++) {
mCanvas.drawLine(centerWith - MercuryWith / 2, left_everyTemparaturHeight * i + abHeight * 2, centerWith - MercuryWith / 2 - MaxLineLong, left_everyTemparaturHeight * i + abHeight * 2, LinePaint);
if (i == 0) {
mCanvas.drawText(left_EndTenperature - i * 20 + "", centerWith - (MercuryWith / 2 + MaxLineLong + MinLineLong) - TextPaint1.getTextSize(), left_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
mCanvas.drawText("mmHg", centerWith - (MercuryWith / 2 + MaxLineLong + MinLineLong) - TextPaint1.getTextSize() + 5, left_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2 + 20, TextPaint);
} else {
mCanvas.drawText(left_EndTenperature - i * 20 + "", centerWith - (MercuryWith / 2 + MaxLineLong + MinLineLong) - TextPaint1.getTextSize(), left_everyTemparaturHeight * i + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
}
for (int j = 1; j <= 9; j++) {
if (j == 5) {
mCanvas.drawLine(centerWith - MercuryWith / 2, left_everyTemparaturHeight * i + j * (left_scaleLong) + abHeight * 2, centerWith - MercuryWith / 2 - MidLineLong, left_everyTemparaturHeight * i + j * (left_scaleLong) + abHeight * 2, LinePaint);
} else {
mCanvas.drawLine(centerWith - MercuryWith / 2, left_everyTemparaturHeight * i + j * (left_scaleLong) + abHeight * 2, centerWith - MercuryWith / 2 - MinLineLong, left_everyTemparaturHeight * i + j * (left_scaleLong) + abHeight * 2, LinePaint);
}
}
//画最后一个刻度
if (i == left_temperatureRange - 1) {
mCanvas.drawLine(centerWith - MercuryWith / 2, left_everyTemparaturHeight * (i + 1) + abHeight * 2, centerWith - MercuryWith / 2 - MaxLineLong, left_everyTemparaturHeight * (i + 1) + abHeight * 2, LinePaint);
mCanvas.drawText(left_EndTenperature - (i + 1) * 20 + "", centerWith - (MercuryWith / 2 + MaxLineLong + MinLineLong / 3) - TextPaint1.getTextSize(), left_everyTemparaturHeight * (i + 1) + TextPaint1.getTextSize() / 2 + abHeight * 2, TextPaint1);
}
}
}
private float trueTemperature = 0;
public void setTargetTemperature(float targetTemperature, float low_hight) {
trueTemperature = targetTemperature;
if (targetTemperature < 0) {
targetTemperature = 0;
}
if (targetTemperature > left_EndTenperature) {
targetTemperature = left_EndTenperature;
}
if (low_hight > left_EndTenperature) {
low_hight = left_EndTenperature;
}
if (low_hight - targetTemperature > 10 && false) {
TargetTemperature = targetTemperature;
Targetlow_hight = targetTemperature + 10;
} else {
TargetTemperature = targetTemperature;
Targetlow_hight = low_hight;
}
isRunning = true;
draw();
}
public void setTargetTemperatureToZero() {
TargetTemperature = 0;
Targetlow_hight = 0;
isRunning = true;
run();
}
}
用法:
<view.Thermometer
android:id = "@+id/thermometer"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" />
thermometer = (Thermometer) view.findViewById(R.id.thermometer);
thermometer.setZOrderOnTop(true); // 这句不能少
thermometer.setZOrderMediaOverlay(true);
thermometer.getHolder().setFormat(PixelFormat.TRANSPARENT);
将控件放置顶部 如果不写这个,Fragment上面放置控件的时候 切换屏幕可能会导致控件不隐藏
常用方法:
//将汞柱归零
thermometer.setTargetTemperatureToZero();
这是单独开启的一个线程,会从当前温度降至最低点
//输入数值 汞柱升高至对应数值 temp为左侧汞柱 temp_low_hight为右侧汞柱
thermometer.setTargetTemperature(temp, temp_low_hight);
效果这个样子:
作者:jyww03 发表于2016/10/20 11:39:37 原文链接
阅读:15 评论:0 查看评论