车载系统20201225

1.名称:

2.所用软件环境:
Androidstudio3.2.win10.grade4.6.
3.用到的技术:
服务端:stm32,ESP8266 WIFI 模块。
客户端:APP。
4.客户端编写概要:
客户端编写主要分为两部分,一部分是XML页面编写,主要作用是人机交互。另一部分是Java代码编写,主要作用是前段页面的数据刷新、显示、链接服务器。
(1)XML界面:定义了一个按钮,用来连接服务器。定义了四个button,分别显示温度数据、灯的状态、继电器状态、车的状态。定义了两个仪表盘控件,一个用来显示油量,一个用来显示车速。还定义了一个进度条,用来表征温度的可视化。布局使用了相对布局。
(2)Java后台:当点击连接服务器之后,我们会获取代码中已经定义好的IP和端口,String IP=“192.168.4.1”;String PORT=“8086”;,新建一个socket进行连接。连接成功之后,获取输入流,接收数据,接收到的数据存储在数组中,然后分别显示到XML界面各自的位置。
5.使用的通信协议是TCP协议。
代码是:
mainActivity:
package com.xw.example.dashboardviewdemo;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends Activity {
//666
EditText editTextIPAddress,editTextPort;//输入IP地址,端口号
Button buttonConnect;//连接按钮
TextView youwei;
TextView chesu;
Button chedeng;
Button jidianqi;
Button chezhuangtai;
Button wendu;
TextView tVRecData;
Socket socket;
InputStream inputStream;//输入流
byte[] RevBuff = new byte[999999];//缓存数据
OutputStream outputStream;//输出流
MyHandler myHandler;//使用Handler更新控件
String IP=“192.168.4.1”;
String PORT=“8086”;
//666
DashboardView dashboardView2;
DashboardView dashboardView4;
DashboardView dashboardView5;
int cc,dd;
private ProgressBar ProBar;//进度条

int i = 0;
String a1 = null; //wendu
String a2 = null;//chesu
String a3 = null;//youliang
String a4 = null;//chedeng
String a5 = null;//jidianqi
String a6 = null;//chezhuangtai
String a7 = null;//null
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //设置无标题
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    //设置全屏
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_main);
    //强制横屏显示
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    //666
    myHandler = new MyHandler();
    buttonConnect = (Button) findViewById(R.id.buttonConnect);
    buttonConnect.setText("连接");


    //666

   // Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
   // setSupportActionBar(toolbar);

  //  dashboardView2 = (DashboardView) findViewById(R.id.default_dashboard_view);
    dashboardView5 = (DashboardView) findViewById(R.id.dashboard_view_5);
    chedeng = (Button)findViewById(R.id.chedeng);
    jidianqi =(Button) findViewById(R.id.jidianqi);
    chezhuangtai =(Button) findViewById(R.id.chezhuangtai);
    wendu =(Button)findViewById(R.id.wendu);
   // DashboardView dashboardView3 = (DashboardView) findViewById(R.id.dashboard_view_3);
    dashboardView4 = (DashboardView) findViewById(R.id.dashboard_view_4);
   ProBar=findViewById(R.id.progress_bar_h);
    /*dashboardView1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            dashboardView1.setRealTimeValue(150.f, true, 100);
        }
    });*/

    List<HighlightCR> highlight1 = new ArrayList<>();
    highlight1.add(new HighlightCR(210, 60, Color.parseColor("#03A9F4")));
    highlight1.add(new HighlightCR(270, 60, Color.parseColor("#FFA000")));
   // dashboardView1.setStripeHighlightColorAndRange(highlight1);

    List<HighlightCR> highlight2 = new ArrayList<>();
    highlight2.add(new HighlightCR(170, 140, Color.parseColor("#607D8B")));
    highlight2.add(new HighlightCR(310, 60, Color.parseColor("#795548")));
    //dashboardView3.setStripeHighlightColorAndRange(highlight2);

    dashboardView4.setRadius(110);
    dashboardView4.setArcColor(getResources().getColor(android.R.color.black));
    dashboardView4.setTextColor(Color.parseColor("#212121"));
    dashboardView4.setBgColor(getResources().getColor(android.R.color.holo_purple));
    dashboardView4.setStartAngle(150);
    dashboardView4.setPointerRadius(80);
    dashboardView4.setCircleRadius(8);
    dashboardView4.setSweepAngle(240);
    dashboardView4.setBigSliceCount(12);
    dashboardView4.setMaxValue(240);
    //dashboardView4.setRealTimeValue(80);
    dashboardView4.setMeasureTextSize(16);
    dashboardView4.setHeaderRadius(50);
    dashboardView4.setHeaderTitle("km/h");
    dashboardView4.setHeaderTextSize(22);
    dashboardView4.setStripeWidth(20);
    dashboardView4.setStripeMode(DashboardView.StripeMode.OUTER);



    dashboardView5.setRadius(110);
    dashboardView5.setArcColor(getResources().getColor(android.R.color.black));
    dashboardView5.setTextColor(Color.parseColor("#212121"));
    dashboardView5.setBgColor(getResources().getColor(android.R.color.holo_purple));
    dashboardView5.setStartAngle(150);
    dashboardView5.setPointerRadius(80);
    dashboardView5.setCircleRadius(8);
    dashboardView5.setSweepAngle(240);
    dashboardView5.setBigSliceCount(10);
    dashboardView5.setMaxValue(100);
    //dashboardView4.setRealTimeValue(80);
    dashboardView5.setMeasureTextSize(16);
    dashboardView5.setHeaderRadius(50);
    dashboardView5.setHeaderTitle("L");
    dashboardView5.setHeaderTextSize(22);
    dashboardView5.setStripeWidth(20);
    dashboardView5.setStripeMode(DashboardView.StripeMode.OUTER);

    List<HighlightCR> highlight3 = new ArrayList<>();
    highlight3.add(new HighlightCR(150, 100, Color.parseColor("#4CAF50")));
    highlight3.add(new HighlightCR(250, 80, Color.parseColor("#FFEB3B")));
    highlight3.add(new HighlightCR(330, 60, Color.parseColor("#F44336")));

    dashboardView4.setStripeHighlightColorAndRange(highlight3);
    dashboardView5.setBgColor(getResources().getColor(android.R.color.holo_purple));

//666

    buttonConnect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (buttonConnect.getText()=="连接"){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                        try{
                            // socket = new Socket(editTextIPAddress.getText().toString(),Integer.valueOf(editTextPort.getText().toString()));
                            socket = new Socket(IP, Integer.parseInt(PORT));
                            if(socket.isConnected()){
                                msg.what = 1;//设置消息变量的 what 变量值 为1
                                inputStream = socket.getInputStream();//获取数据流通道
                               outputStream = socket.getOutputStream();//获取输出流
                                //设置车速和油量的位置开始

// dashboardView4.setRealTimeValue(20);
//设置车速和油量的位置结束
Recv();//调用接收函数
// dashboardView2.setRealTimeValue(33);
//dashboardView4.setRealTimeValue(33);
System.out.println(“666666666666333333333333333333333333333333333333333666666666666666666666666”);
}
}catch (Exception e){
msg.what = 0;//设置消息变量的 what 变量值 为0
}
myHandler.sendMessage(msg);//插入消息队列
}
}).start();
}
else{
try{ socket.close(); }catch (Exception e){} //关闭连接
try{ inputStream.close(); }catch (Exception e){}
buttonConnect.setText(“连接”);//按钮显示连接
}
}
});

}


public void Recv(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            while (socket!= null && socket.isConnected()) try {

                String Len = String.valueOf(inputStream.read(RevBuff));//获取数据

                if (Len != "-1") {
                    System.out.println("66666666666666666644444444444444444444444444446666666666666666666666666");
                    Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                    msg.what = 3;//设置消息变量的 what 变量值 为3
                    msg.arg1 = Integer.parseInt(Len);//接收的数据个数
                    msg.obj = RevBuff;//传递数据
                    myHandler.sendMessage(msg);//插入消息队列



                } else {//连接异常断开
                    Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                    msg.what = 0;//设置消息变量的 what 变量值 为0
                    myHandler.sendMessage(msg);//插入消息队列
                    break;
                }
            } catch (Exception e) {//连接异常断开
                Message msg = myHandler.obtainMessage();//从消息队列拉取个消息变量
                msg.what = 0;//设置消息变量的 what 变量值 为0
                myHandler.sendMessage(msg);//插入消息队列
                break;
            }
        }
    }).start();
}

//Handler
class MyHandler extends Handler {
    @SuppressLint("ResourceType")
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        switch (msg.what) {
            case 0:
                Toast.makeText(MainActivity.this, "连接出错", Toast.LENGTH_SHORT).show();
                buttonConnect.setText("连接");//按钮显示连接
                break;
            case 1:
                buttonConnect.setText("断开");//按钮显示断开
                break;
            case 3:
                byte[] Buffer1 = new byte[msg.arg1];//创建一个数组 arg1为接收数据的个数

                System.arraycopy((byte[]) msg.obj, 0, Buffer1, 0, msg.arg1);//拷贝数据

                String aa = new String(Buffer1);

                System.out.println("666666666666666666666666665555555555555555555555566666666666666666666666666666");
                String[] arr = aa.split("\\s+");

                for (i = 0; i < 7; i++) {
                    if (i == 0) a1 = arr[0];
                    if (i == 1) a2 = arr[1];
                    if (i == 2) a3 = arr[2];
                    if (i == 3) a4 = arr[3];
                    if (i == 4) a5 = arr[4];
                    if (i == 5) a6 = arr[5];
                    if (i == 6) a7 = arr[6];
                }
                System.out.println("66666666666666666666666666"+a4+"5555555555555555555555566666666666666666666666666666");
                //youwei.setText(a1);

                if (a5.equals("ON"))
                {
                    chedeng.setText("车灯开");
                    chedeng.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_light));
                    chedeng.setTextColor(getResources().getColor(android.R.color.black));
                }else if (a5.equals("OFF"))
                {
                    chedeng.setText("车灯关");
                    chedeng.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
                    chedeng.setTextColor(getResources().getColor(android.R.color.black));
                }

                if (a6.equals("ON"))
                {
                    jidianqi.setText("继电器开");
                    jidianqi.setBackgroundColor(getResources().getColor(android.R.color.holo_red_dark));
                    jidianqi.setTextColor(getResources().getColor(android.R.color.black));
                }else if (a6.equals("OFF"))
                {
                    jidianqi.setText("继电器关");
                    jidianqi.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
                    jidianqi.setTextColor(getResources().getColor(android.R.color.black));
                }

                if (a7.equals("1"))
                {
                    chezhuangtai.setText("加速");
                    chezhuangtai.setBackgroundColor(getResources().getColor(android.R.color.holo_orange_light));
                    chezhuangtai.setTextColor(getResources().getColor(android.R.color.black));
                }else if (a7.equals("2"))
                {
                    chezhuangtai.setText("减速");
                    chezhuangtai.setBackgroundColor(getResources().getColor(android.R.color.holo_purple));
                    chezhuangtai.setTextColor(getResources().getColor(android.R.color.black));
                }else if (a7.equals("3"))
                {
                    chezhuangtai.setText("停止");
                    chezhuangtai.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
                    chezhuangtai.setTextColor(getResources().getColor(android.R.color.black));
                }



                wendu.setText("温度:" + a2 + "℃");
                //chedeng.setText("车灯:"+a5);
               // jidianqi.setText("继电器:"+a6);
                //chezhuangtai.setText("车状态:"+a7);
                final int abc = Integer.parseInt(a4);//chesu
                float abcd=Float.parseFloat(a2);
                int abcde=(int)abcd;
               //int abcd = Integer.parseInt(a2);//youliang
                int abd = Integer.parseInt(a3);
                dashboardView4.setRealTimeValue(abd);
                dashboardView5.setRealTimeValue(abc);
                ProBar.setProgress(abcde);
                wendu.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
                wendu.setTextColor(getResources().getColor(android.R.color.black));
               /* chedeng.setTextColor(getResources().getColor(android.R.color.holo_purple));
                jidianqi.setTextColor(getResources().getColor(android.R.color.holo_purple));
                chezhuangtai.setTextColor(getResources().getColor(android.R.color.holo_purple));*/
                /*dashboardView2.setRealTimeValue(66);
                dashboardView4.setRealTimeValue(33);
                byte[] Buffer1 = new byte[msg.arg1];//创建一个数组 arg1为接收数据的个数
                System.arraycopy((byte[]) msg.obj, 0, Buffer1, 0, msg.arg1);//拷贝数据
                String aa = new String(Buffer1);
                String[] arr = aa.split("\\s+");
                int i = 0;
                String a1 = null;
                String a2 = null;
                String a3 = null;
                String a4 = null;
                String a5 = null;
                String a6 = null;
                for (i = 0; i < 6; i++) {
                    if (i == 0) a1 = arr[0];
                    if (i == 1) a2 = arr[1];
                    if (i == 2) a3 = arr[2];
                    if (i == 3) a4 = arr[3];
                    if (i == 4) a5 = arr[4];
                    if (i == 5) a6 = arr[5];
                }*/
               /* tVRecData.setText(a1);
                youwei.setText(a2);
                chesu.setText(a3);
                zhaomingdeng.setText(a4);
                jidianqi.setText(a5);
                chezhuangtai.setText(a6);*/

                //延时函数
              /*  Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        int abc = 0;//chesu
                        int abd =0;
                        dashboardView4.setRealTimeValue(abd);
                        dashboardView5.setRealTimeValue(abc);
                         //要执行的操作
                       // youwei.setText("");
                        wendu.setText("");
                        //chesu.setText("");
                        chedeng.setText("");
                        jidianqi.setText("");
                        chezhuangtai.setText("");
                    }
                }, 1990);//3秒后执行Runnable中的run方法*/
               /* tVRecData.setTextColor(getResources().getColor(R.drawable.red));
                youwei.setTextColor(getResources().getColor(R.drawable.red));
                chezhuangtai.setTextColor(getResources().getColor(R.drawable.red));
                chesu.setTextColor(getResources().getColor(R.drawable.red));
                jidianqi.setTextColor(getResources().getColor(R.drawable.red));
                zhaomingdeng.setTextColor(getResources().getColor(R.drawable.red));*/

        }
    }
    //666




}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

}

HighlightCR:
package com.xw.example.dashboardviewdemo;

/**

  • HighlightColorAndRange

  • 高亮效果的范围和颜色对象

  • Created by woxingxiao on 2015/11/3.
    */
    public class HighlightCR {

    private int mStartAngle;
    private int mSweepAngle;
    private int mColor;

    public HighlightCR() {

    }

    public HighlightCR(int startAngle, int sweepAngle, int color) {
    this.mStartAngle = startAngle;
    this.mSweepAngle = sweepAngle;
    this.mColor = color;
    }

    public int getStartAngle() {
    return mStartAngle;
    }

    public void setStartAngle(int startAngle) {
    mStartAngle = startAngle;
    }

    public int getSweepAngle() {
    return mSweepAngle;
    }

    public void setSweepAngle(int sweepAngle) {
    mSweepAngle = sweepAngle;
    }

    public int getColor() {
    return mColor;
    }

    public void setColor(int color) {
    this.mColor = color;
    }
    }

DashboardView:

package com.xw.example.dashboardviewdemo;

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.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import java.util.List;

public class DashboardView extends View {

private int mRadius; // 圆弧半径
private int mStartAngle; // 起始角度
private int mSweepAngle; // 绘制角度
private int mBigSliceCount; // 大份数
private int mSliceCountInOneBigSlice; // 划分一大份长的小份数
private int mArcColor; // 弧度颜色
private int mMeasureTextSize; // 刻度字体大小
private int mTextColor; // 字体颜色
private String mHeaderTitle = ""; // 表头
private int mHeaderTextSize; // 表头字体大小
private int mHeaderRadius; // 表头半径
private int mPointerRadius; // 指针半径
private int mCircleRadius; // 中心圆半径
private int mMinValue; // 最小值
private int mMaxValue; // 最大值
public float mRealTimeValue; // 实时值
private int mStripeWidth; // 色条宽度
private StripeMode mStripeMode = StripeMode.NORMAL;
private int mBigSliceRadius; // 较长刻度半径
private int mSmallSliceRadius; // 较短刻度半径
private int mNumMeaRadius; // 数字刻度半径
private int mModeType;
private List<HighlightCR> mStripeHighlight; // 高亮范围颜色对象的集合
private int mBgColor; // 背景色

private int mViewWidth; // 控件宽度
private int mViewHeight; // 控件高度
private float mCenterX;
private float mCenterY;

private Paint mPaintArc;
private Paint mPaintText;
private Paint mPaintPointer;
private Paint mPaintValue;
private Paint mPaintStripe;

private RectF mRectArc;
private RectF mRectStripe;
private Rect mRectMeasures;
private Rect mRectHeader;
private Rect mRectRealText;
private Path path;

private int mSmallSliceCount; // 短刻度个数
private float mBigSliceAngle; // 大刻度等分角度
private float mSmallSliceAngle; // 小刻度等分角度

private String[] mGraduations; // 等分的刻度值
private float initAngle;
private boolean textColorFlag = true; // 若不单独设置文字颜色,则文字和圆弧同色
private boolean mAnimEnable; // 是否播放动画
private MyHandler mHandler;
private long duration = 500; // 动画默认时长

public DashboardView(Context context) {
    this(context, null);
}

public DashboardView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DashboardView, defStyleAttr, 0);

    mRadius = a.getDimensionPixelSize(R.styleable.DashboardView_radius, dpToPx(80));
    mStartAngle = a.getInteger(R.styleable.DashboardView_startAngle, 180);
    mSweepAngle = a.getInteger(R.styleable.DashboardView_sweepAngle, 180);
    mBigSliceCount = a.getInteger(R.styleable.DashboardView_bigSliceCount, 10);
    mSliceCountInOneBigSlice = a.getInteger(R.styleable.DashboardView_sliceCountInOneBigSlice, 5);
    mArcColor = a.getColor(R.styleable.DashboardView_arcColor, Color.WHITE);
    mMeasureTextSize = a.getDimensionPixelSize(R.styleable.DashboardView_measureTextSize, spToPx(12));
    mTextColor = a.getColor(R.styleable.DashboardView_textColor, mArcColor);
    mHeaderTitle = a.getString(R.styleable.DashboardView_headerTitle);
    if (mHeaderTitle == null) mHeaderTitle = "";
    mHeaderTextSize = a.getDimensionPixelSize(R.styleable.DashboardView_headerTextSize, spToPx(14));
    mHeaderRadius = a.getDimensionPixelSize(R.styleable.DashboardView_headerRadius, mRadius / 3);
    mPointerRadius = a.getDimensionPixelSize(R.styleable.DashboardView_pointerRadius, mRadius / 3 * 2);
    mCircleRadius = a.getDimensionPixelSize(R.styleable.DashboardView_circleRadius, mRadius / 17);
    mMinValue = a.getInteger(R.styleable.DashboardView_minValue, 0);
    mMaxValue = a.getInteger(R.styleable.DashboardView_maxValue, 100);
    mRealTimeValue = a.getFloat(R.styleable.DashboardView_realTimeValue, 0.0f);
    mStripeWidth = a.getDimensionPixelSize(R.styleable.DashboardView_stripeWidth, 0);
    mModeType = a.getInt(R.styleable.DashboardView_stripeMode, 0);
    mBgColor = a.getColor(R.styleable.DashboardView_bgColor, 0);

    a.recycle();

    initObjects();
    initSizes();
}

private String[] getMeasureNumbers() {
    String[] strings = new String[mBigSliceCount + 1];
    for (int i = 0; i <= mBigSliceCount; i++) {
        if (i == 0) {
            strings[i] = String.valueOf(mMinValue);
        } else if (i == mBigSliceCount) {
            strings[i] = String.valueOf(mMaxValue);
        } else {
            strings[i] = String.valueOf(((mMaxValue - mMinValue) / mBigSliceCount) * i);
        }
    }

    return strings;
}

private void initObjects() {
    mPaintArc = new Paint();
    mPaintArc.setAntiAlias(true);
    mPaintArc.setColor(mArcColor);
    mPaintArc.setStyle(Paint.Style.STROKE);
    mPaintArc.setStrokeCap(Paint.Cap.ROUND);

    mPaintText = new Paint();
    mPaintText.setAntiAlias(true);
    mPaintText.setColor(mTextColor);
    mPaintText.setStyle(Paint.Style.STROKE);

    mPaintPointer = new Paint();
    mPaintPointer.setAntiAlias(true);

    mPaintStripe = new Paint();
    mPaintStripe.setAntiAlias(true);
    mPaintStripe.setStyle(Paint.Style.STROKE);
    mPaintStripe.setStrokeWidth(mStripeWidth);

    mRectMeasures = new Rect();
    mRectHeader = new Rect();
    mRectRealText = new Rect();
    path = new Path();

    mPaintValue = new Paint();
    mPaintValue.setAntiAlias(true);
    mPaintValue.setColor(mTextColor);
    mPaintValue.setStyle(Paint.Style.STROKE);
    mPaintValue.setTextAlign(Paint.Align.CENTER);
    mPaintValue.setTextSize(Math.max(mHeaderTextSize, mMeasureTextSize));
    mPaintValue.getTextBounds(trimFloat(mRealTimeValue), 0, trimFloat(mRealTimeValue).length(), mRectRealText);

    mHandler = new MyHandler();
}

private void initSizes() {
    if (mSweepAngle > 360)
        throw new IllegalArgumentException("sweepAngle must less than 360 degree");

    mSmallSliceRadius = mRadius - dpToPx(8);
    mBigSliceRadius = mSmallSliceRadius - dpToPx(4);
    mNumMeaRadius = mBigSliceRadius - dpToPx(3);

    mSmallSliceCount = mBigSliceCount * mSliceCountInOneBigSlice;
    mBigSliceAngle = mSweepAngle / (float) mBigSliceCount;
    mSmallSliceAngle = mBigSliceAngle / (float) mSliceCountInOneBigSlice;
    mGraduations = getMeasureNumbers();

    switch (mModeType) {
        case 0:
            mStripeMode = StripeMode.NORMAL;
            break;
        case 1:
            mStripeMode = StripeMode.INNER;
            break;
        case 2:
            mStripeMode = StripeMode.OUTER;
            break;
    }

    int totalRadius;
    if (mStripeMode == StripeMode.OUTER) {
        totalRadius = mRadius + mStripeWidth;
    } else {
        totalRadius = mRadius;
    }

    mCenterX = mCenterY = 0.0f;
    if (mStartAngle <= 180 && mStartAngle + mSweepAngle >= 180) {
        mViewWidth = totalRadius * 2 + getPaddingLeft() + getPaddingRight() + dpToPx(2) * 2;
    } else {
        float[] point1 = getCoordinatePoint(totalRadius, mStartAngle);
        float[] point2 = getCoordinatePoint(totalRadius, mStartAngle + mSweepAngle);
        float max = Math.max(Math.abs(point1[0]), Math.abs(point2[0]));
        mViewWidth = (int) (max * 2 + getPaddingLeft() + getPaddingRight() + dpToPx(2) * 2);
    }
    if ((mStartAngle <= 90 && mStartAngle + mSweepAngle >= 90) ||
            (mStartAngle <= 270 && mStartAngle + mSweepAngle >= 270)) {
        mViewHeight = totalRadius * 2 + getPaddingTop() + getPaddingBottom() + dpToPx(2) * 2;
    } else {
        float[] point1 = getCoordinatePoint(totalRadius, mStartAngle);
        float[] point2 = getCoordinatePoint(totalRadius, mStartAngle + mSweepAngle);
        float max = Math.max(Math.abs(point1[1]), Math.abs(point2[1]));
        mViewHeight = (int) (max * 2 + getPaddingTop() + getPaddingBottom() + dpToPx(2) * 2);
    }

    mCenterX = mViewWidth / 2.0f;
    mCenterY = mViewHeight / 2.0f;

    mRectArc = new RectF(mCenterX - mRadius, mCenterY - mRadius, mCenterX + mRadius, mCenterY + mRadius);
    int r = 0;
    if (mStripeWidth > 0) {
        if (mStripeMode == StripeMode.OUTER) {
            r = mRadius + dpToPx(1) + mStripeWidth / 2;
        } else if (mStripeMode == StripeMode.INNER) {
            r = mRadius + dpToPx(1) - mStripeWidth / 2;
        }
        mRectStripe = new RectF(mCenterX - r, mCenterY - r, mCenterX + r, mCenterY + r);
    }

    initAngle = getAngleFromResult(mRealTimeValue);
}


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    if (widthMode == MeasureSpec.EXACTLY) {
        mViewWidth = widthSize;
    } else {
        if (widthMode == MeasureSpec.AT_MOST)
            mViewWidth = Math.min(mViewWidth, widthSize);
    }
    if (heightMode == MeasureSpec.EXACTLY) {
        mViewHeight = heightSize;
    } else {
        int totalRadius;
        if (mStripeMode == StripeMode.OUTER) {
            totalRadius = mRadius + mStripeWidth;
        } else {
            totalRadius = mRadius;
        }
        if (mStartAngle >= 180 && mStartAngle + mSweepAngle <= 360) {
            mViewHeight = totalRadius + mCircleRadius + dpToPx(2) + dpToPx(25) +
                    getPaddingTop() + getPaddingBottom() + mRectRealText.height();
        } else {
            float[] point1 = getCoordinatePoint(totalRadius, mStartAngle);
            float[] point2 = getCoordinatePoint(totalRadius, mStartAngle + mSweepAngle);
            float maxY = Math.max(Math.abs(point1[1]) - mCenterY, Math.abs(point2[1]) - mCenterY);
            float f = mCircleRadius + dpToPx(2) + dpToPx(25) + mRectRealText.height();
            float max = Math.max(maxY, f);
            mViewHeight = (int) (max + totalRadius + getPaddingTop() + getPaddingBottom() + dpToPx(2) * 2);
        }
        if (widthMode == MeasureSpec.AT_MOST)
            mViewHeight = Math.min(mViewHeight, widthSize);
    }

    setMeasuredDimension(mViewWidth, mViewHeight);
}


@Override
protected void onDraw(Canvas canvas) {
    if (mBgColor != 0) canvas.drawColor(mBgColor);

    drawStripe(canvas);
    drawMeasures(canvas);
    drawArc(canvas);
    drawCircleAndReadingText(canvas);
    drawPointer(canvas);
}

/**
 * 绘制色带
 */
private void drawStripe(Canvas canvas) {
    if (mStripeMode != StripeMode.NORMAL && mStripeHighlight != null) {
        for (int i = 0; i < mStripeHighlight.size(); i++) {
            HighlightCR highlightCR = mStripeHighlight.get(i);
            if (highlightCR.getColor() == 0 || highlightCR.getSweepAngle() == 0)
                continue;

            mPaintStripe.setColor(highlightCR.getColor());
            if (highlightCR.getStartAngle() + highlightCR.getSweepAngle() <= mStartAngle + mSweepAngle) {
                canvas.drawArc(mRectStripe, highlightCR.getStartAngle(),
                        highlightCR.getSweepAngle(), false, mPaintStripe);
            } else {
                canvas.drawArc(mRectStripe, highlightCR.getStartAngle(),
                        mStartAngle + mSweepAngle - highlightCR.getStartAngle(), false, mPaintStripe);
                break;
            }
        }
    }
}

/**
 * 绘制刻度盘
 */
private void drawMeasures(Canvas canvas) {
    mPaintArc.setStrokeWidth(dpToPx(2));
    for (int i = 0; i <= mBigSliceCount; i++) {
        //绘制大刻度
        float angle = i * mBigSliceAngle + mStartAngle;
        float[] point1 = getCoordinatePoint(mRadius, angle);
        float[] point2 = getCoordinatePoint(mBigSliceRadius, angle);

        if (mStripeMode == StripeMode.NORMAL && mStripeHighlight != null) {
            for (int j = 0; j < mStripeHighlight.size(); j++) {
                HighlightCR highlightCR = mStripeHighlight.get(j);
                if (highlightCR.getColor() == 0 || highlightCR.getSweepAngle() == 0)
                    continue;

                if (angle <= highlightCR.getStartAngle() + highlightCR.getSweepAngle()) {
                    mPaintArc.setColor(highlightCR.getColor());
                    break;
                } else {
                    mPaintArc.setColor(mArcColor);
                }
            }
        } else {
            mPaintArc.setColor(mArcColor);
        }
        canvas.drawLine(point1[0], point1[1], point2[0], point2[1], mPaintArc);

        //绘制圆盘上的数字
        mPaintText.setTextSize(mMeasureTextSize);
        String number = mGraduations[i];
        mPaintText.getTextBounds(number, 0, number.length(), mRectMeasures);
        if (angle % 360 > 135 && angle % 360 < 225) {
            mPaintText.setTextAlign(Paint.Align.LEFT);
        } else if ((angle % 360 >= 0 && angle % 360 < 45) || (angle % 360 > 315 && angle % 360 <= 360)) {
            mPaintText.setTextAlign(Paint.Align.RIGHT);
        } else {
            mPaintText.setTextAlign(Paint.Align.CENTER);
        }
        float[] numberPoint = getCoordinatePoint(mNumMeaRadius, angle);
        if (i == 0 || i == mBigSliceCount) {
            canvas.drawText(number, numberPoint[0], numberPoint[1] + (mRectMeasures.height() / 2), mPaintText);
        } else {
            canvas.drawText(number, numberPoint[0], numberPoint[1] + mRectMeasures.height(), mPaintText);
        }
    }

    //绘制小的子刻度
    mPaintArc.setStrokeWidth(dpToPx(1));
    for (int i = 0; i < mSmallSliceCount; i++) {
        if (i % mSliceCountInOneBigSlice != 0) {
            float angle = i * mSmallSliceAngle + mStartAngle;
            float[] point1 = getCoordinatePoint(mRadius, angle);
            float[] point2 = getCoordinatePoint(mSmallSliceRadius, angle);

            if (mStripeMode == StripeMode.NORMAL && mStripeHighlight != null) {
                for (int j = 0; j < mStripeHighlight.size(); j++) {
                    HighlightCR highlightCR = mStripeHighlight.get(j);
                    if (highlightCR.getColor() == 0 || highlightCR.getSweepAngle() == 0)
                        continue;

                    if (angle <= highlightCR.getStartAngle() + highlightCR.getSweepAngle()) {
                        mPaintArc.setColor(highlightCR.getColor());
                        break;
                    } else {
                        mPaintArc.setColor(mArcColor);
                    }
                }
            } else {
                mPaintArc.setColor(mArcColor);
            }
            mPaintArc.setStrokeWidth(dpToPx(1));
            canvas.drawLine(point1[0], point1[1], point2[0], point2[1], mPaintArc);
        }
    }

}

/**
 * 绘制刻度盘的弧形
 */
private void drawArc(Canvas canvas) {
    mPaintArc.setStrokeWidth(dpToPx(2));
    if (mStripeMode == StripeMode.NORMAL) {
        if (mStripeHighlight != null) {
            for (int i = 0; i < mStripeHighlight.size(); i++) {
                HighlightCR highlightCR = mStripeHighlight.get(i);
                if (highlightCR.getColor() == 0 || highlightCR.getSweepAngle() == 0)
                    continue;

                mPaintArc.setColor(highlightCR.getColor());
                if (highlightCR.getStartAngle() + highlightCR.getSweepAngle() <= mStartAngle + mSweepAngle) {
                    canvas.drawArc(mRectArc, highlightCR.getStartAngle(),
                            highlightCR.getSweepAngle(), false, mPaintArc);
                } else {
                    canvas.drawArc(mRectArc, highlightCR.getStartAngle(),
                            mStartAngle + mSweepAngle - highlightCR.getStartAngle(), false, mPaintArc);
                    break;
                }
            }
        } else {
            mPaintArc.setColor(mArcColor);
            canvas.drawArc(mRectArc, mStartAngle, mSweepAngle, false, mPaintArc);
        }
    } else if (mStripeMode == StripeMode.OUTER) {
        mPaintArc.setColor(mArcColor);
        canvas.drawArc(mRectArc, mStartAngle, mSweepAngle, false, mPaintArc);
    }
}

/**
 * 绘制圆和文字读数
 */
private void drawCircleAndReadingText(Canvas canvas) {
    //表头
    mPaintText.setTextSize(mHeaderTextSize);
    mPaintText.setTextAlign(Paint.Align.CENTER);
    mPaintText.getTextBounds(mHeaderTitle, 0, mHeaderTitle.length(), mRectHeader);
    canvas.drawText(mHeaderTitle, mCenterX, mCenterY - mHeaderRadius + mRectHeader.height(), mPaintText);

    //绘制中心点的圆
    mPaintPointer.setStyle(Paint.Style.FILL);
    mPaintPointer.setColor(Color.parseColor("#e4e9e9"));
    canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mPaintPointer);

    mPaintPointer.setStyle(Paint.Style.STROKE);
    mPaintPointer.setStrokeWidth(dpToPx(4));
    mPaintPointer.setColor(mArcColor);
    canvas.drawCircle(mCenterX, mCenterY, mCircleRadius + dpToPx(2), mPaintPointer);

    // 绘制读数
    canvas.drawText(trimFloat(mRealTimeValue), mCenterX,
            mCenterY + mCircleRadius + dpToPx(2) + dpToPx(25), mPaintValue);
}

/**
 * 绘制指针
 */
private void drawPointer(Canvas canvas) {
    mPaintPointer.setStyle(Paint.Style.FILL);
    mPaintPointer.setColor(mTextColor);
    path.reset();
    float[] point1 = getCoordinatePoint(mCircleRadius / 2, initAngle + 90);
    path.moveTo(point1[0], point1[1]);
    float[] point2 = getCoordinatePoint(mCircleRadius / 2, initAngle - 90);
    path.lineTo(point2[0], point2[1]);
    float[] point3 = getCoordinatePoint(mPointerRadius, initAngle);
    path.lineTo(point3[0], point3[1]);
    path.close();
    canvas.drawPath(path, mPaintPointer);
    // 绘制三角形指针底部的圆弧效果
    canvas.drawCircle((point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2,
            mCircleRadius / 2, mPaintPointer);
}

/**
 * 依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
 */
public float[] getCoordinatePoint(int radius, float cirAngle) {
    float[] point = new float[2];

    double arcAngle = Math.toRadians(cirAngle); //将角度转换为弧度
    if (cirAngle < 90) {
        point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
        point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
    } else if (cirAngle == 90) {
        point[0] = mCenterX;
        point[1] = mCenterY + radius;
    } else if (cirAngle > 90 && cirAngle < 180) {
        arcAngle = Math.PI * (180 - cirAngle) / 180.0;
        point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
        point[1] = (float) (mCenterY + Math.sin(arcAngle) * radius);
    } else if (cirAngle == 180) {
        point[0] = mCenterX - radius;
        point[1] = mCenterY;
    } else if (cirAngle > 180 && cirAngle < 270) {
        arcAngle = Math.PI * (cirAngle - 180) / 180.0;
        point[0] = (float) (mCenterX - Math.cos(arcAngle) * radius);
        point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
    } else if (cirAngle == 270) {
        point[0] = mCenterX;
        point[1] = mCenterY - radius;
    } else {
        arcAngle = Math.PI * (360 - cirAngle) / 180.0;
        point[0] = (float) (mCenterX + Math.cos(arcAngle) * radius);
        point[1] = (float) (mCenterY - Math.sin(arcAngle) * radius);
    }

    return point;
}

/**
 * 通过数值得到角度位置
 */
private float getAngleFromResult(float result) {
    if (result > mMaxValue)
        return mMaxValue;
    return mSweepAngle * (result - mMinValue) / (mMaxValue - mMinValue) + mStartAngle;
}

/**
 * float类型如果小数点后为零则显示整数否则保留
 */
public static String trimFloat(float value) {
    if (Math.round(value) - value == 0) {
        return String.valueOf((long) value);
    }
    return String.valueOf(value);
}

public int getRadius() {
    return mRadius;
}

public void setRadius(int radius) {
    mRadius = dpToPx(radius);
    initSizes();
    invalidate();
}

public int getStartAngle() {
    return mStartAngle;
}

public void setStartAngle(int startAngle) {
    mStartAngle = startAngle;
    initSizes();
    invalidate();
}

public int getSweepAngle() {
    return mSweepAngle;
}

public void setSweepAngle(int sweepAngle) {
    mSweepAngle = sweepAngle;
    initSizes();
    invalidate();
}

public int getBigSliceCount() {
    return mBigSliceCount;
}

public void setBigSliceCount(int bigSliceCount) {
    mBigSliceCount = bigSliceCount;
    initSizes();
    invalidate();
}

public int getSliceCountInOneBigSlice() {
    return mSliceCountInOneBigSlice;
}

public void setSliceCountInOneBigSlice(int sliceCountInOneBigSlice) {
    mSliceCountInOneBigSlice = sliceCountInOneBigSlice;
    initSizes();
    invalidate();
}

public int getArcColor() {
    return mArcColor;
}

public void setArcColor(int arcColor) {
    mArcColor = arcColor;
    mPaintArc.setColor(arcColor);
    if (textColorFlag) {
        mTextColor = mArcColor;
        mPaintText.setColor(arcColor);
    }
    invalidate();
}

public int getMeasureTextSize() {
    return mMeasureTextSize;
}

public void setMeasureTextSize(int measureTextSize) {
    mMeasureTextSize = spToPx(measureTextSize);
    initSizes();
    invalidate();
}

public int getTextColor() {
    return mTextColor;
}

public void setTextColor(int textColor) {
    mTextColor = textColor;
    textColorFlag = false;
    mPaintText.setColor(textColor);
    invalidate();
}

public String getHeaderTitle() {
    return mHeaderTitle;
}

public void setHeaderTitle(String headerTitle) {
    mHeaderTitle = headerTitle;
    invalidate();
}

public int getHeaderTextSize() {
    return mHeaderTextSize;
}

public void setHeaderTextSize(int headerTextSize) {
    mHeaderTextSize = spToPx(headerTextSize);
    initSizes();
    invalidate();
}

public int getHeaderRadius() {
    return mHeaderRadius;
}

public void setHeaderRadius(int headerRadius) {
    mHeaderRadius = dpToPx(headerRadius);
    initSizes();
    invalidate();
}

public int getPointerRadius() {
    return mPointerRadius;
}

public void setPointerRadius(int pointerRadius) {
    mPointerRadius = dpToPx(pointerRadius);
    initSizes();
    invalidate();
}

public int getCircleRadius() {
    return mCircleRadius;
}

public void setCircleRadius(int circleRadius) {
    mCircleRadius = dpToPx(circleRadius);
    initSizes();
    invalidate();
}

public int getMinValue() {
    return mMinValue;
}

public void setMinValue(int minValue) {
    mMinValue = minValue;
    initSizes();
    invalidate();
}

public int getMaxValue() {
    return mMaxValue;
}

public void setMaxValue(int maxValue) {
    mMaxValue = maxValue;
    initSizes();
    invalidate();
}

public float getRealTimeValue() {
    return mRealTimeValue;
}

public void setRealTimeValue(int realTimeValue) {
    mRealTimeValue = realTimeValue;
    initSizes();
    if (!mAnimEnable)
        invalidate();
}

public void setRealTimeValue(float realTimeValue, boolean animEnable) {
    mHandler.preValue = mRealTimeValue;
    mAnimEnable = animEnable;
    initSizes();
    if (!mAnimEnable) {
        invalidate();
    } else {
        mRealTimeValue = realTimeValue;
        mHandler.endValue = realTimeValue;
        mHandler.deltaValue = Math.abs(mHandler.endValue - mHandler.preValue);
        mHandler.sendEmptyMessage(0);
    }
}

public void setRealTimeValue(float realTimeValue, boolean animEnable, long duration) {
    mHandler.preValue = mRealTimeValue;
    mAnimEnable = animEnable;
    initSizes();
    if (!mAnimEnable) {
        invalidate();
    } else {
        this.duration = duration;
        mRealTimeValue = realTimeValue;
        mHandler.endValue = realTimeValue;
        mHandler.deltaValue = Math.abs(mHandler.endValue - mHandler.preValue);
        mHandler.sendEmptyMessage(0);
    }
}

public int getStripeWidth() {
    return mStripeWidth;
}

public void setStripeWidth(int stripeWidth) {
    mStripeWidth = dpToPx(stripeWidth);
    initSizes();
    invalidate();
}

public StripeMode getStripeMode() {
    return mStripeMode;
}

public void setStripeMode(StripeMode mStripeMode) {
    this.mStripeMode = mStripeMode;
    switch (mStripeMode) {
        case NORMAL:
            mModeType = 0;
            break;
        case INNER:
            mModeType = 1;
            break;
        case OUTER:
            mModeType = 2;
            break;
    }
    initSizes();
    invalidate();
}

public int getBigSliceRadius() {
    return mBigSliceRadius;
}

public void setBigSliceRadius(int bigSliceRadius) {
    mBigSliceRadius = dpToPx(bigSliceRadius);
    initSizes();
    invalidate();
}

public int getSmallSliceRadius() {
    return mSmallSliceRadius;
}

public void setSmallSliceRadius(int smallSliceRadius) {
    mSmallSliceRadius = dpToPx(smallSliceRadius);
    initSizes();
    invalidate();
}

public int getNumMeaRadius() {
    return mNumMeaRadius;
}

public void setNumMeaRadius(int numMeaRadius) {
    mNumMeaRadius = dpToPx(numMeaRadius);
    initSizes();
    invalidate();
}

public void setStripeHighlightColorAndRange(List<HighlightCR> stripeHighlight) {
    mStripeHighlight = stripeHighlight;
    mPaintStripe.setStrokeWidth(mStripeWidth);
    invalidate();
}

public enum StripeMode {
    NORMAL,
    INNER,
    OUTER
}

public int getBgColor() {
    return mBgColor;
}

public void setBgColor(int mBgColor) {
    this.mBgColor = mBgColor;
    invalidate();
}

public boolean isAnimEnable() {
    return mAnimEnable;
}

public void setAnimEnable(boolean animEnable) {
    mAnimEnable = animEnable;
    if (mAnimEnable) {
        mHandler.endValue = mRealTimeValue;
        mHandler.sendEmptyMessage(0);
    }
}

private int dpToPx(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}

private int spToPx(int sp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}

private class MyHandler extends Handler {

    float preValue;
    float endValue;
    float deltaValue;

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        if (msg.what == 0) {
            if (preValue > endValue) {
                preValue -= 1;
            } else if (preValue < endValue) {
                preValue += 1;
            }
            if (Math.abs(preValue - endValue) > 1) {
                mRealTimeValue = preValue;
                long t = (long) (duration / deltaValue);
                sendEmptyMessageDelayed(0, t);
            } else {
                mRealTimeValue = endValue;
            }
            initAngle = getAngleFromResult(mRealTimeValue);
            invalidate();
        }
    }
}

}

activity-main:

<?xml version="1.0" encoding="utf-8"?>

<android.support.design.widget.CoordinatorLayout
xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:fitsSystemWindows=“true”
tools:context=“.MainActivity”>

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
  >
</android.support.design.widget.AppBarLayout>

<include layout="@layout/content_main"/>

</android.support.design.widget.CoordinatorLayout>

content_main:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">


    <Button
        android:id="@+id/buttonConnect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="287dp"
        android:layout_marginLeft="287dp"
        android:layout_marginTop="0dp"
        android:background="#265"
        android:text="连接"
        android:textSize="15dp" />
    <ProgressBar
        android:id="@+id/progress_bar_h"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="40dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:max="100"
        android:progressDrawable="@drawable/progress_vertical"
        android:layout_marginLeft="314dp"
        android:layout_marginTop="80dp"
        />

    <com.xw.example.dashboardviewdemo.DashboardView
        android:id="@+id/dashboard_view_5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:layout_alignParentBottom="true"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="68dp"
        app:startAngle="180"
        android:layout_marginTop="10dp"
        app:sweepAngle="180" />
    <com.xw.example.dashboardviewdemo.DashboardView
        android:id="@+id/dashboard_view_4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="380dp"
        android:layout_marginBottom="68dp"
        app:startAngle="180"
        android:layout_marginTop="10dp"
        app:sweepAngle="180" />


    <Button
        android:id="@+id/chezhuangtai"
        android:layout_width="101dp"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_marginStart="503dp"
        android:layout_marginLeft="557dp"
        android:layout_marginBottom="-41dp"
        android:background="#278"
        android:textSize="15dp"
        android:text="" />

    <Button
        android:id="@+id/wendu"
        android:textSize="15dp"
        android:background="#278"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_marginTop="0dp"
        android:layout_marginEnd="487dp"
        android:layout_marginLeft="167dp"
        android:text="" />

    <Button
        android:id="@+id/chedeng"
        android:background="#278"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="13dp"
        android:layout_marginLeft="13dp"
        android:layout_marginTop="0dp"
        android:textSize="15dp"
        android:text="" />

    <Button
        android:id="@+id/jidianqi"
        android:background="#278"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:textSize="15dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_marginStart="393dp"
        android:layout_marginLeft="393dp"
        android:layout_marginTop="0dp"
        android:text="" />


</RelativeLayout>

manifests:

<?xml version="1.0" encoding="utf-8"?>





<application
android:allowBackup=“true”
android:icon=“@mipmap/ic_launcher”
android:label=“@string/app_name”
android:supportsRtl=“true”
android:theme=“@style/AppTheme”

     >
    <activity
        android:name="com.xw.example.dashboardviewdemo.MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
progress_vertical.xml <?xml version="1.0" encoding="utf-8"?>
<item android:id="@android:id/progress">
    <clip
        android:clipOrientation="vertical"
        android:gravity = "bottom"
        >

        <shape>
            <corners android:radius="5dip" />
            <gradient
                android:startColor="#ffffd300"
                android:centerColor="#ffffb600"
                android:centerX="0.75"
                android:endColor="#ffffcb00"
                android:angle="90"
                />
        </shape>
    </clip>
</item>
attrs.xml <?xml version="1.0" encoding="utf-8"?> colors.xml <?xml version="1.0" encoding="utf-8"?> #3F51B5 #303F9F #FF4081 #80808FF0 #F8F8FF00 #FFFFFF #938192 #7cd12e #ff000000 #ff0000ff #ff00ffff #ff888888 #ff00ff00 #ffcccccc #ffff00ff #ffff0000 #00000000 #ffffff00

styles.xml
styles.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值