/**
*@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. Jsp 国际化访问首页选择展示不同字体小例子

    要求:创建一个首页,默然显示英文信息,但可以让用户选择使用英文,繁体中文或简体中文. 1.编写hello_en_US.txt,内容如下: cc.openhome.welcome=welcomecc.o ...

  2. web工程启动时,在一个类中延迟加载Bean,因为该Bean类可能还没被JVM加载

     问题描述: (1)javaWeb项目启动中,还没启动完成,在下面这个类加载另一个Bean类, (2)通过getBean方法获取到该Bean,可以获取到,不为null (3)但是,调用该Bean的方法 ...

  3. Linux性能监控分析命令(一)—vmstat命令详解

    一.vmstat介绍 语法格式: vmstat [-V] [-n] [-S unit] [delay [count]] -V prints version. -n causes the headers ...

  4. Spring boot JPA 用自定义主键策略 生成自定义主键ID

    最近学习Spring boot JPA 学习过程解决的一些问题写成随笔,大家一起成长.这次遇到自定义主键的问题 package javax.persistence; public enum Gener ...

  5. openssl查看apk的证书信息

    查看apk的证书信息: openssl pkcs7 -inform DER -in CERT.RSA -noout -print_certs -text

  6. C#程序优化的50种方案

    一.用属性代替可访问的字段 1..NET数据绑定只支持数据绑定,使用属性可以获得数据绑定的好处: 2.在属性的get和set访问器重可使用lock添加多线程的支持. 二.readonly(运行时常量) ...

  7. day04元组

    元组 1.元祖书写规范 users=[11,22,33,"老男孩"]#列表(可变) users=(11,22,33,"老纳海")#元祖(不可变) 1.公共方法( ...

  8. Apache ZooKeeper 服务启动源码解释

    转载:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper-code/ 本文首先讲解了 Apache ZooKeeper 服 ...

  9. Appium介绍及工作原理

    一.Appium介绍 Appium是一个开源.跨平台的测试框架,可以用来测试原生及混合的移动端应用.Appium支持IOS.Android及FirefoxOS平台.Appium使用WebDriver的 ...

  10. PythonStudy——字符串、列表、元组、字典、集合 (str、list、tuple、dict、set)常用方法总结

    字符串: # 字符串类型的一些操作(str)st1='hello world 'print(st1[0]) # 根据字符串索引来取字符h 找不到直接崩print(st1[-1]) # 根据索引倒取st ...