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"/>