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;
    }
}