/**
*@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. 剑指Offer 6. 旋转数组的最小数字 (数组)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...

  2. CentOS 7 命令行安装TeamViewer

    由于要通过要远程登录到内网的电脑(一台笔记本),用于在紧急情况下处理服务器故障.刚开始准备使用ssh端口转发,无奈vps转发速度太慢. 后面考虑使用TeamViewer远程控制Windows桌面,但是 ...

  3. WEBBASE篇: 第九篇, JavaScript知识4

    JavaScript 4 练习1 <!doctype html> <html lang="en"> <head> <meta charse ...

  4. 软间隔分类——SVM

    引入:1. 数据线性不可分:2. 映射到高维依然不是线性可分3. 出现噪声.如图: 对原始问题变形得到#2: 进行拉格朗日转换: 其中α和r是拉格朗日因子,均有不小于0的约束.按照之前的对偶问题的推导 ...

  5. linu下未编译的mysql安装包

    wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.21.tar.gz

  6. java-IO流-字节流-概述及分类、FileInputStream、FileOutputStream、available()方法、定义小数组、BufferedInputStream、BufferedOutputStream、flush和close方法的区别、流的标准处理异常代码

    1.IO流概述及其分类 * 1.概念      * IO流用来处理设备之间的数据传输      * Java对数据的操作是通过流的方式      * Java用于操作流的类都在IO包中      *  ...

  7. some working learning总结学习(二)

    2. 读取excel上的测试用例和结果,成json格式,最终存到access数据库 结果如下: { : { 'Req_ID': 'Fqqqqq/qqqqq', 'Case_ID': 'ATC_LvPw ...

  8. python------SocketServer (0809)

    socket(一对一) 与socketserver 一.socketserver 1. 正式定义:The socketserver module simplifies the task of writ ...

  9. [转] Linux运维常见故障排查和处理的技巧汇总

    作为linux运维,多多少少会碰见这样那样的问题或故障,从中总结经验,查找问题,汇总并分析故障的原因,这是一个Linux运维工程师良好的习惯.每一次技术的突破,都经历着苦闷,伴随着快乐,可我们还是执着 ...

  10. [Java] 方法 -- 繼承關係

    public class test { void show() { System.out.println("父類別"); } } public class test2 extend ...