android 开发 View _16 自定义计步器View、自定义柱状图View

时间:2021-04-01 19:44:03
/**
*@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;
}
}
}