Android自定义View:监测液化天然气罐液位与压力
March 8, 2022
这个是我在学习android自定义View时完成的一个作业:
android自定义View:监测液化天然气罐液位与压力
package com.xiaoyifei.howmoney;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;
import androidx.annotation.Nullable;
public class Hydraulic extends View {
private String mLeftText;
private String mRightText;
private int mMaxLevel;
private float mMaxPressure;
final public static String TAG="MYTEST";
private float mLiquidLevel=200;
private float mLiquidPressure;
private Runnable mRunnable;
private boolean mSwitch=false;
public Hydraulic(Context context) {
this(context,null);
}
public Hydraulic(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,R.attr.liquidDefStyle);
}
public Hydraulic(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.attrs_liquid,defStyleAttr,R.style.liquidDefStyle);
int count=array.getIndexCount();
for(int i=0;i<count;i++){
int attr=array.getIndex(i);
switch (attr){
case R.styleable.attrs_liquid_leftText:
mLeftText=array.getString(attr);
break;
case R.styleable.attrs_liquid_rightText:
mRightText=array.getString(attr);
break;
case R.styleable.attrs_liquid_maxLiquidLevel:
mMaxLevel=array.getInteger(attr,500);
break;
case R.styleable.attrs_liquid_maxLiquidPressure:
mMaxPressure=array.getFloat(attr,2000.0f);
break;
default:
break;
}
}
/*post(mRunnable=new Runnable() {
@Override
public void run() {
mLiquidLevel=mLiquidLevel-1;
if(mLiquidLevel<0){
removeCallbacks(mRunnable);
return;
}
postInvalidate();
postDelayed(this,1000);
}
});*/
setOnClickListener(new OnClickListener() {//点击就增加液体
@Override
public void onClick(View v) {
if(!mSwitch){
mSwitch=true;
post(mRunnable=new Runnable() {
@Override
public void run() {
mLiquidLevel=mLiquidLevel+1;
if(mLiquidLevel>mMaxLevel){
removeCallbacks(mRunnable);
return;
}
postInvalidate();
postDelayed(this,1000);
}
});
}else {
removeCallbacks(mRunnable);
mSwitch=false;
}
}
});
Log.i(TAG,mLeftText+" "+mRightText+" "+mMaxLevel+" "+mMaxPressure);
}
@Override
protected void onDraw(Canvas canvas) {
int width=getMeasuredWidth();
int height=getMeasuredHeight();
int centerX=width/2;
int centerY=height/2;
int leftCenterX=centerX/2;
mLiquidPressure=mLiquidLevel*4;
int rightCenterX=centerX+centerX/2;
String leftText=mLeftText+String.format("%.2f",mLiquidLevel)+"分米";
String rightText=mRightText+String.format("%.2f",mLiquidPressure);
canvas.drawColor(Color.parseColor("#e0f2f1"));
Paint paint=new Paint();
paint.setColor(Color.parseColor("#ff94c2"));
canvas.drawLine(centerX,0,centerX,height,paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
//罐子
int rectWidth=(width/2)*60/100;
int rectHeight=height*65/100;
canvas.drawRoundRect(leftCenterX-rectWidth/2+30,centerY-rectHeight/2,leftCenterX+rectWidth/2+30,centerY+rectHeight/2,30,20,paint);
//管子
Path path=new Path();
path.moveTo(leftCenterX+rectWidth/4,centerY+rectHeight/2-10);
path.rLineTo(0,-rectHeight-10);
path.rLineTo(-20,0);
path.rLineTo(0,-30);
path.rLineTo(70,0);
path.rLineTo(0,30);
path.rLineTo(-20,0);
path.rLineTo(0,rectHeight+10);
canvas.drawPath(path,paint);
//液体
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#29b6f6"));
int levelRectHeight= (int) (rectHeight*mLiquidLevel/mMaxLevel);
canvas.drawRoundRect(leftCenterX-rectWidth/2+30,centerY+rectHeight/2-levelRectHeight,leftCenterX+rectWidth/2+30,centerY+rectHeight/2,30,20,paint);
if(levelRectHeight>20){
canvas.drawRect(leftCenterX-rectWidth/2+30,centerY+rectHeight/2-levelRectHeight,leftCenterX+rectWidth/2+30,centerY+rectHeight/2-levelRectHeight+20,paint);
}
//刻度
paint.setColor(Color.parseColor("#ff94c2"));
int scaleLeft=leftCenterX-rectWidth/2+30;
int scalBottom=centerY+rectHeight/2;
int cent=rectHeight/20;
for(int i=1;i<20;i++){
if(i%5==0){
Rect bound=new Rect();
String scaleValue=String.valueOf((mMaxLevel/4)*(i/5));
paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,10,getResources().getDisplayMetrics()));
paint.getTextBounds(scaleValue,0,scaleValue.length(),bound);
canvas.drawText(scaleValue,scaleLeft-bound.width()-10,scalBottom-cent,paint);
canvas.drawLine(scaleLeft,scalBottom-cent,scaleLeft+30,scalBottom-cent,paint);
}else{
canvas.drawLine(scaleLeft,scalBottom-cent,scaleLeft+20,scalBottom-cent,paint);
}
scalBottom=scalBottom-cent;
}
//压力
int pressureWidth=(width/2)*60/100;
int pressureHeight=height*60/100;
int startAngle=135;
int sweepAngle=270;
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(20);
canvas.drawArc(rightCenterX-pressureWidth/2,centerY-pressureHeight/2,rightCenterX+pressureWidth/2,centerY+pressureHeight/2,startAngle,sweepAngle/2-1,false,paint);
paint.setColor(Color.YELLOW);
canvas.drawArc(rightCenterX-pressureWidth/2,centerY-pressureHeight/2,rightCenterX+pressureWidth/2,centerY+pressureHeight/2,startAngle+sweepAngle/2,sweepAngle/4-1,false,paint);
paint.setColor(Color.RED);
canvas.drawArc(rightCenterX-pressureWidth/2,centerY-pressureHeight/2,rightCenterX+pressureWidth/2,centerY+pressureHeight/2,startAngle+sweepAngle/2+sweepAngle/4,sweepAngle/4,false,paint);
//压力刻度
paint.setColor(Color.parseColor("#ff94c2"));
paint.setStrokeWidth(1);
int cx,cy;
int radius=pressureWidth/2;
for(int i=0;i<=4;i++) {
String scaleText=String.format("%.1f",(mMaxPressure/4)*i);
cx = (int) (Math.cos(Math.toRadians(startAngle+67.5*i)) * radius);
cy = (int) (Math.sin(Math.toRadians(startAngle+67.5*i)) * radius);
Rect bound=new Rect();
paint.getTextBounds(scaleText,0,scaleText.length(),bound);
if(cx<0) {
canvas.drawText(scaleText, rightCenterX + cx - bound.width() - 25, centerY + cy + bound.height()/2, paint);
}
if(cx==0) {
canvas.drawText(scaleText, rightCenterX + cx - bound.width()/2, centerY + cy - bound.height(), paint);
}
if(cx>0) {
canvas.drawText(scaleText, rightCenterX + cx + 25, centerY + cy + bound.height()/2, paint);
}
if(i==0){
String kpa="KPa";
paint.getTextBounds(kpa,0,kpa.length(),bound);
canvas.drawText("KPa",rightCenterX-bound.width()/2,centerY+cy,paint);
}
Log.i(TAG,"cx="+cx+ " "+"cy="+cy);
}
//压力指针
int littleCircleRadius=20;
int handRadius=radius-25;
paint.setStyle(Paint.Style.FILL);
float pressureAngle=startAngle+270*mLiquidLevel/mMaxLevel;
canvas.drawCircle(rightCenterX,centerY,littleCircleRadius,paint);
int px= (int) (rightCenterX+ Math.cos(Math.toRadians(pressureAngle))*handRadius);
int py= (int) (centerY+Math.sin(Math.toRadians(pressureAngle))*handRadius);
int px1= (int) (rightCenterX+ Math.cos(Math.toRadians(pressureAngle+90))*littleCircleRadius);
int py1= (int) (centerY+Math.sin(Math.toRadians(pressureAngle+90))*littleCircleRadius);
int px2= (int) (rightCenterX+ Math.cos(Math.toRadians(pressureAngle-90))*littleCircleRadius);
int py2= (int) (centerY+Math.sin(Math.toRadians(pressureAngle-90))*littleCircleRadius);
Path path1=new Path();
path1.moveTo(px1,py1);
path1.lineTo(px,py);
path1.lineTo(px2,py2);
path1.close();
canvas.drawPath(path1,paint);
Paint textPaint=new Paint();
textPaint.setColor(Color.parseColor("#000000"));
textPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,15,getResources().getDisplayMetrics()));
Rect bound=new Rect();
textPaint.getTextBounds(leftText,0,leftText.length(),bound);
canvas.drawText(leftText,leftCenterX-bound.width()/2,height-bound.height()/2,textPaint);
textPaint.getTextBounds(rightText,0,rightText.length(),bound);
canvas.drawText(rightText,rightCenterX-bound.width()/2,height-bound.height()/2,textPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = 0,height = 0;
int measureWidth=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int measureHeight=MeasureSpec.getSize(heightMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
switch (widthMode){
case MeasureSpec.AT_MOST:
width=defaultWidth();
break;
case MeasureSpec.EXACTLY:
width=measureWidth;
break;
case MeasureSpec.UNSPECIFIED:
width=Math.max(getSuggestedMinimumWidth(),measureWidth);
break;
default:break;
}
height=width/2;
/*
switch (heightMode){
case MeasureSpec.AT_MOST:
height=width/2;
Log.e(TAG,"高的模式是:AT_MOST"+" 高度是:"+measureHeight);
break;
case MeasureSpec.EXACTLY:
height=measureHeight;
Log.e(TAG,"高的模式是:EXACTLY"+" 高度是:"+measureHeight);
break;
case MeasureSpec.UNSPECIFIED:
height=Math.max(getSuggestedMinimumHeight(),measureHeight);
Log.e(TAG,"高的模式是:UNSPECIFIED"+" 高度是:"+measureHeight);
break;
default:break;
}
*/
setMeasuredDimension(width,height);
}
private int defaultWidth() {
WindowManager manager= (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics=new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.widthPixels;
}
public void setLiquidLevel(float liquidLevel){
this.mLiquidLevel=liquidLevel;
}
public void setLiquidPressure(float liquidPressure){
this.mLiquidPressure=liquidPressure;
}
}