/**
*@content:实现计步的环形View
*@time:2018-7-30
*@build:
*/ public class CountStepsAnnularView extends View {
private final String TAG = "CountStepsAnnularView";
//文字组
private String mAimText;
private float mAimNum;//目标步数
private String mStepText;
private float mCurrentNum;//当前步数
//参数组
private float mPadding;//内边距
private float mOuterRaceWidth;//外环宽度
private float mInnerRaceWidth;//内环宽度
private Paint mPaint;
private Path mPath;
//颜色组
private int mAimTextColor;
private int mCurrenStepNumColor;
private int mStepTextColor;
private int[] mOuterRaceColors;
private float [] mOuterRaceColorPositions;
private int[] mInnerRaceColors;
private float [] mInnerRaceColorsPositions; //动画变量值
private int animation_innerRace;
private int animation_currentStep;
private boolean mStartAnimation; public CountStepsAnnularView(Context context) {
super(context);
init(); } public CountStepsAnnularView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(); } public CountStepsAnnularView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(); }
/**
* 添加数据的方法
* @param setAimText ”目标“的文字
* @param setStepText “步” 的文字
* @param setAimStepNum 目标步数
* @param setCurrenStepNum 当前步数
* @param aimTextColor 目标文字颜色
* @param currenStepNumColor 当前步数文字颜色
* @param stepTextColor 步的显示颜色
* @param startAnimation 是否启用动画
*/
public void setData(String setAimText,String setStepText,float setAimStepNum,float setCurrenStepNum,
int aimTextColor,int currenStepNumColor,int stepTextColor,boolean startAnimation){
this.mAimText = setAimText;//设置目标文字
this.mStepText = setStepText;//设置步文字animation_innerRace
this.mAimNum = setAimStepNum;//设置目标步数
this.mCurrentNum = setCurrenStepNum;//设置当前步数
animation_innerRace = 0;
animation_currentStep = 0 ;
if(aimTextColor != 0){
this.mAimTextColor = aimTextColor;
}else {
mAimTextColor = 0xF0111111;
}
if(currenStepNumColor != 0){
this.mCurrenStepNumColor = currenStepNumColor;
}else {
mCurrenStepNumColor = 0xF0111111;
}
if(stepTextColor != 0){
this.mStepTextColor = stepTextColor;
}else {
mStepTextColor = 0xF0111111;
}
this.mStartAnimation = startAnimation;
} /**
* 设置颜色的方法
* @param outerRaceColors 外环颜色组 例如: int [] colors = new int[]{0xff56F9D0,0xFF4194F9};
* @param outerRaceColorsPositions 外环颜色渐变点 例如: float [] floats = new float[]{0,0.5f};
* @param innerRaceColors 内环颜色组
* @param innerRaceColorspPositions 内环颜色渐变点
* @ps 颜色组和渐变点组 数量需要一致
*/
public void setGradientColors(int [] outerRaceColors,float [] outerRaceColorsPositions,
int [] innerRaceColors,float[] innerRaceColorspPositions){
this.mOuterRaceColors = outerRaceColors;
this.mOuterRaceColorPositions = outerRaceColorsPositions;
this.mInnerRaceColors = innerRaceColors;
this.mInnerRaceColorsPositions = innerRaceColorspPositions; } private void init(){
mPaint = new Paint();
mPath = new Path(); }
private void initData(){
mOuterRaceWidth = getWidth()/10;
mPadding = mOuterRaceWidth/2+5;
mInnerRaceWidth = mOuterRaceWidth - 3;
if(mOuterRaceColors == null){
mOuterRaceColors = new int[]{0xff56F9D0,0xFF4194F9};
mOuterRaceColorPositions = new float[]{0,0.5f};
}
if(mInnerRaceColors == null){
mInnerRaceColors = new int[]{0xFF8EF9BE,0xFF26FCB1};
mInnerRaceColorsPositions = new float[]{0,0.5f};
}
} //画外环
private void outerRace(Canvas canvas){
mPaint.reset();
mPath.reset();
//setLayerType(LAYER_TYPE_SOFTWARE,null);//关闭硬件加速
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mOuterRaceWidth);
mPaint.setStyle(Paint.Style.STROKE);
SweepGradient sg = new SweepGradient(getWidth()/2,getHeight()/2,mOuterRaceColors,mOuterRaceColorPositions);
Matrix matrix = new Matrix();
matrix.preRotate(135,getWidth(),getHeight());
sg.setLocalMatrix(matrix);
mPaint.setShader(sg);
RectF rectF = new RectF();
rectF.left = mPadding;
rectF.top = mPadding;
rectF.right = getWidth()-mPadding;
rectF.bottom = getHeight()-mPadding;
mPath.addArc(rectF,135,270);
canvas.drawPath(mPath,mPaint);
} //画内环
private void innerRace(Canvas canvas){
mPaint.reset();
mPath.reset();
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mInnerRaceWidth);
mPaint.setStyle(Paint.Style.STROKE);
SweepGradient sg = new SweepGradient(getWidth()/2,getHeight()/2,mInnerRaceColors,mInnerRaceColorsPositions);
Matrix matrix = new Matrix();
matrix.preRotate(135,getWidth(),getHeight());
sg.setLocalMatrix(matrix);
mPaint.setShader(sg);
RectF rectF = new RectF();
rectF.left = mPadding;
rectF.top = mPadding;
rectF.right = getWidth() - mPadding;
rectF.bottom = getHeight() - mPadding ;
float currentNum = (float) 270 * (mCurrentNum / mAimNum);
if(mStartAnimation) {
//270度是内环最大值,不可以超过270
if (mCurrentNum > mAimNum) {
if(animation_innerRace < 270){
animation_innerRace = animation_innerRace + 5;
}
mPath.addArc(rectF, 135, animation_innerRace);
} else { if (animation_innerRace < currentNum) {
animation_innerRace = animation_innerRace + 5;
}
mPath.addArc(rectF, 135, animation_innerRace);
}
}else {
//270度是内环最大值,不可以超过270
if (mCurrentNum > mAimNum) {
mPath.addArc(rectF, 135, 270);
} else {
mPath.addArc(rectF, 135, currentNum);
}
}
canvas.drawPath(mPath,mPaint);
} //目标文字
private void titleText(Canvas canvas){
mPath.reset();
mPaint.reset();
String aimNumText = Integer.toString((int)mAimNum);
int num = aimNumText.length()+mAimText.length()+mStepText.length()+1;
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(mAimTextColor);
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getWidth()/100);
if(num < 10){
mPaint.setTextSize(getWidth()/10);
}else {
mPaint.setTextSize(getWidth()/(num)+2);
}
float y = getHeight()/2 - mPadding ;
float x = getWidth()/2;
canvas.drawText(mAimText+" "+aimNumText+mStepText,x,y,mPaint); } //当前数字
private void currentNumText(Canvas canvas){
mPath.reset();
mPaint.reset();
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(mCurrenStepNumColor);
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getWidth()/100);
mPaint.setTextSize(getWidth()/5);
float y = getHeight()/2+getWidth()/10+mPadding;
float x = getWidth()/2;
if(mStartAnimation) {
if (animation_currentStep < mCurrentNum) {
if (mCurrentNum < 300) {
animation_currentStep++;
} else {
if (animation_currentStep < mCurrentNum - 500) {
animation_currentStep = animation_currentStep + 300;
}else if(animation_currentStep < mCurrentNum - 301){
animation_currentStep = animation_currentStep + 50;
}else if(animation_currentStep < mCurrentNum -51){
animation_currentStep = animation_currentStep + 20;
}else if (animation_currentStep < mCurrentNum -11){
animation_currentStep = animation_currentStep + 5;
}else if (animation_currentStep < mCurrentNum){
animation_currentStep = animation_currentStep + 1;
}
}
}
canvas.drawText(Integer.toString((int) animation_currentStep), x, y, mPaint);
}else {
canvas.drawText(Integer.toString((int) mCurrentNum), x, y, mPaint);
}
} //步文字
private void stepText(Canvas canvas){
mPath.reset();
mPaint.reset();
mPaint.setTextAlign(Paint.Align.CENTER);
mPaint.setColor(mStepTextColor);
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getWidth()/100);
mPaint.setTextSize(getWidth()/10);
float y = getHeight()/2+getWidth()/10+getWidth()/5+5;
float x = getWidth()/2;
canvas.drawText(mStepText,x,y,mPaint);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
initData();
outerRace(canvas);
innerRace(canvas);
titleText(canvas);
currentNumText(canvas);
stepText(canvas);
postInvalidateDelayed(1); }
}
 
/**
*@content:自定义柱状图View
*@time:2018-7-31
*@build:
*/ public class BarGraphView extends View {
private final String TAG = "BarGraphView";
private List<Item> mItemList = new ArrayList<>();;
private Paint mPaint;
private Paint mPaintTiemText;
private Paint mPaintCurrenNumText;
private Path mPath;
private Path mSrc;
private float mWPadding;//宽边距 X边距
private float mHPadding;//高边距 Y边距
private float mSpacing;// item之间的间距
private float mItemWidth; //item 的宽度
private float mItemHeight; //item 的高度
private float mItemNum; // item 的数量
private float mBottomLine; //底线上的Y坐标值
private float mMaxValue;
//颜色组
private int[] mItemColors ;
private float[] mItemColorsPosition;
private int mTiemTextColor;
private int mCurrenNumTextColor; public BarGraphView(Context context) {
super(context);
initPaint();
} public BarGraphView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
} public BarGraphView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
} /**
* 添加数据的方法
* @param item 例子:view.addData(new BarGraphView.Item("12-7",1651));
*/
public void addData(Item item){
mItemList.add(item);
//计算添加到List中的最大值,并且给最大值增加2000上限
mMaxValue = 0;
if(!mItemList.isEmpty()) {
for (int j = 0; j < mItemList.size(); j++) {
float numA = mItemList.get(j).currenNum;
if (mMaxValue < numA) {
mMaxValue = numA;
}
}
mMaxValue = mMaxValue + 2000;
}
} public List<Item> getData(){
return mItemList; } /**
* 设置颜色的方法
* @param mItemColors 圆柱体的颜色组
* @param mItemColorsPosition 圆柱体的颜色组渐变点
* @param mTiemTextColor 时间text的颜色
* @param mCurrenNumTextColor 步数text的颜色
*/
public void setColors(int[] mItemColors,float[] mItemColorsPosition,int mTiemTextColor,int mCurrenNumTextColor){
this.mItemColors = mItemColors;
this.mItemColorsPosition = mItemColorsPosition;
this.mTiemTextColor = mTiemTextColor;
this.mCurrenNumTextColor = mCurrenNumTextColor;
} private void initPaint(){
this.mPaint = new Paint();
this.mPaintTiemText = new Paint();
this.mPaintCurrenNumText = new Paint();
this.mPath = new Path();
this.mSrc = new Path();
}
private void initData(){
if(!mItemList.isEmpty()) {
mItemNum = mItemList.size();
}
if(mItemColors == null){
mItemColors = new int[]{0xFF2BF19E,0xFF1BE2FC};
}
if (mItemColorsPosition == null){
mItemColorsPosition = new float[]{0.2f,0.8f};
}
if (mTiemTextColor == 0){
mTiemTextColor = Color.BLACK;
}
if (mCurrenNumTextColor == 0){
mCurrenNumTextColor = Color.BLACK;
} mWPadding = getWidth()/20; //宽度内边距
mHPadding = getHeight()/10; //高度内边距
mItemWidth = getWidth()/(10+mItemNum); //圆柱体的宽度
mBottomLine = getHeight()-mHPadding*2; //底部横线坐标
if(mItemList.size() == 1){
//只有一个item时,处理圆柱间距
mSpacing = getWidth()/2 - mItemWidth;
}else if (mItemList.size() == 2) {
//只有二个item时,处理圆柱间距
mSpacing = getWidth() / 4;
}else if (mItemList.size() == 3){
//只有三个item时,处理圆柱间距
mSpacing = getWidth() / 6;
}else {
mSpacing = ((getWidth() - mWPadding*2 - mItemWidth*mItemNum)/mItemNum)/1.15f; //圆柱体之间的间距
} } /**
* 画底部横线
* @param canvas 画布
*/
private void drawXline(Canvas canvas){
mPaint.reset();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(2);
int [] colors = new int[]{0xFF7E42FF,0xFF2BB5FA};
float[] colorsPosition = new float[]{0.2f,0.6f};
RadialGradient rg = new RadialGradient(getWidth()/2,
getHeight()-mHPadding*2,
getWidth(),
colors,colorsPosition,Shader.TileMode.CLAMP);
mPaint.setShader(rg);
canvas.drawLine(mWPadding,getHeight()-mHPadding*2,getWidth()-mWPadding,getHeight()-mHPadding*2,mPaint); } /**
* 画圆柱 画日期 画数值
* @param canvas 画布
*/
private void drawItem(Canvas canvas){
mPaint.reset();
mPaintTiemText.reset();
mPaintCurrenNumText.reset();
mPath.reset();
//柱状图画笔
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.BLUE);
LinearGradient lg = new LinearGradient(0,getHeight(),getWidth(),0,mItemColors,mItemColorsPosition,Shader.TileMode.CLAMP);
mPaint.setShader(lg);
//日期画笔
mPaintTiemText.setAntiAlias(true);
mPaintTiemText.setStyle(Paint.Style.FILL);
mPaintTiemText.setStrokeWidth(5);
mPaintTiemText.setTextSize(getWidth()/35);
mPaintTiemText.setTextAlign(Paint.Align.LEFT);
mPaintTiemText.setColor(mTiemTextColor);
//数值画笔
mPaintCurrenNumText.setAntiAlias(true);
mPaintCurrenNumText.setStyle(Paint.Style.FILL);
mPaintCurrenNumText.setStrokeWidth(5);
mPaintCurrenNumText.setTextSize(getWidth()/35);
mPaintCurrenNumText.setTextAlign(Paint.Align.LEFT);
mPaintCurrenNumText.setColor(mCurrenNumTextColor);
mItemHeight = (getHeight() - mHPadding * 3) * (mItemList.get(0).currenNum / mMaxValue);
if(!mItemList.isEmpty()) {
//画第一个圆柱
RectF rect = new RectF();
rect.left = mWPadding + mSpacing;
rect.top = mBottomLine - mItemHeight;
rect.right = mWPadding + mSpacing + mItemWidth;
rect.bottom = mBottomLine;
mPath.addRect(rect, Path.Direction.CW);
//画日期
canvas.drawText(mItemList.get(0).time,
mWPadding + mSpacing,
mBottomLine + mHPadding,
mPaintTiemText);
//画数值
canvas.drawText(Integer.toString((int) (mItemList.get(0).currenNum)),
mWPadding + mSpacing,
mBottomLine - mItemHeight - 5,
mPaintCurrenNumText);
//画剩下的圆柱
for (int i = 1; i < mItemList.size(); i++) {
Item item = mItemList.get(i);
mItemHeight = (getHeight() - mHPadding * 3) * (item.currenNum / mMaxValue);
RectF rectF = new RectF();
rectF.left = mWPadding + mSpacing * (i + 1) + mItemWidth * i;
rectF.top = mBottomLine - mItemHeight;
rectF.right = mWPadding + mSpacing * (i + 1) + mItemWidth * (i + 1);
rectF.bottom = mBottomLine;
mSrc = new Path();//画单个圆柱
mSrc.addRect(rectF, Path.Direction.CW);
mPath.addPath(mSrc);//将单个圆柱添加到mPath中
canvas.drawText(item.time,
mWPadding + mSpacing * (i + 1) + mItemWidth * i,
mBottomLine + mHPadding,
mPaintTiemText);//画日期
canvas.drawText(Integer.toString((int) (item.currenNum)),
mWPadding + mSpacing * (i + 1) + mItemWidth * i,
mBottomLine - mItemHeight - 5,
mPaintCurrenNumText);//画步数
}
canvas.drawPath(mPath, mPaint);//一次性添加全部圆柱
}else {
mPaintTiemText.setTextSize(getWidth()/20);
canvas.drawText("无数据",getWidth()/2,getHeight()/2,mPaintTiemText);
}
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
initData();
drawXline(canvas);
drawItem(canvas);
} public static class Item {
public String time;
public float currenNum;
public Item (String time,float currenNum){
this.time = time;
this.currenNum = currenNum;
}
}
}
 

android 开发 View _16 自定义计步器View、自定义柱状图View的更多相关文章

  1. Android开发之仿微信显示更多文字的View

    最近开发需求中要模仿微信朋友圈文章的展开收起功能,网上找了找,发现都有问题,于是乎自己在前辈的基础上进行了一定量的修改,下边将源码贴出来供大家参考:1.主Activity布局文件就不粘贴了,很简单,就 ...

  2. Android开发学习之路--UI之自定义布局和控件

    新的一年已经开始了,今天已经是初二了,两天没有学习了,还是要来继续学习下.一般手机的title都是actionbar,就像iphone一样可以后退,可以编辑.这里自定义布局就来实现下这个功能,首先准备 ...

  3. Android开发:使用DialogFragment实现dialog自定义布局

    使用DialogFragment实现dialog的自定义布局最大的好处是可以更好控制dialog的生命周期. TestFragment的代码: public class TestFragment ex ...

  4. 【Android开发】控件外边框自定义

    1.在drawable里面新建自定义的资源文件shape <?xml version="1.0" encoding="utf-8"?> <sh ...

  5. Android开发之自定义组件和接口回调

    说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...

  6. 【转】Android开发笔记(序)写在前面的目录

    原文:http://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经 ...

  7. Android开发之漫漫长途 番外篇——自定义View的各种姿势1

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  8. Android开发之漫漫长途 番外篇——自定义View的各种姿势2

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  9. Android开发进阶——自定义View的使用及其原理探索

    在Android开发中,系统提供给我们的UI控件是有限的,当我们需要使用一些特殊的控件的时候,只靠系统提供的控件,可能无法达到我们想要的效果,这时,就需要我们自定义一些控件,来完成我们想要的效果了.下 ...

随机推荐

  1. weinre 远程调试 安装 配置

    1.第一种方法:安装:npm install -g weinre 2.第一种方法:开启本地监听服务器(修改端口,默认端口是8080):在cmd中运行: weinre --httpPort 8101 - ...

  2. angualr Material Icons

    首先需要项目引入 angualr meterial icons的资源库 图标资源链接 https://klarsys.github.io/angular-material-icons/ <md- ...

  3. Verilog HDL按位操作符与归约操作符的区别

    sdaPipe <= {`DEB_I2C_LEN{1'b1}}; {{}} 为一种赋值运算符,将一个表达式放入双重花括号中,而复制因子放在第一层花括号中,用来指定复制的次数. { }表示拼接,{ ...

  4. [Java复习] 复习知识点

    将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现. String 被设计成不可变(immutable)类, 所以它的所有对象都是不可变对象. 要被序列化的实例 ...

  5. ArcGIS统计栅格像元值并转换为矢量图层

    很多时候,我们需要得到矢量数据区域所对应栅格数据的像元统计值(求平均.求和等),然后将获得的统计值赋给矢量图层的属性表,在ArcGIS中操作如下:(PS:第一次写技术文章,望大家多多体谅与支持,么么哒 ...

  6. java mysql数据库链接与资源关闭

    /** * Created by Clear on 2018/8/11. * here provide the kind of connections from mysql database,and ...

  7. Gym - 100783G:Playing With Geometry (几何 离散化 )

    pro:给定规则的多边形,规则是指顶点都在整点上,而且是相互垂直的边的交点. 现在给定两个多边形A,B,问A,B缩小,旋转后是否可以变为同一个图形. sol:缩小的话,直接离散化即可,就可以去掉没用的 ...

  8. 如何将docker镜像文件上传至Docker Hub

    一.Docker Hub中新建存储库 注册,登录Docker Hub之后,点击右上角Create Repository,创建存储库,如下图所示: 取个名字,我这里取名为lihui_demo.并且可以选 ...

  9. 2分钟理解文件IO -我对文件IO的理解与实验对比

    本文介绍了不同的IO方式以及他们之间的效率比较 1.一次读取写入单个字节(读取400M的文件浪费了很久,等了很久没读取完成,证明其效率很差) public class CopyFileDemo { p ...

  10. 关于PostmanURL中不能传递中文的问题

    众所周知,中文乱码等问题在开发过程中让人厌烦,本人最近在使用Postman插件测试web的时候,在请求中添加了中文,结果请求错误 截图如下: 原因:不能直接处理中文,需要自行转化 解决: 1.新建一个 ...