本文实例为大家分享了android自定义圆角柱状图的具体代码,供大家参考,具体内容如下
需求:
画一个圆角柱状图,显示12个月的数据,y轴数据动态分割,如果是当前月,就画出当前月图片;点击柱状图变色,并显示虚线弹出当前月信息,滑动时弹框和虚线消失,柱状图刷新到最初。
1.histogramround
package com.broker.liming.widget;
import android.annotation.targetapi;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.dashpatheffect;
import android.graphics.paint;
import android.graphics.path;
import android.graphics.rect;
import android.os.build;
import android.support.annotation.nullable;
import android.support.v4.content.contextcompat;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
import android.view.viewconfiguration;
import com.broker.liming.r;
import com.broker.liming.bean.chartdata;
import com.broker.liming.utils.arithutil;
import com.broker.liming.utils.logutil2;
import java.text.decimalformat;
import java.util.arraylist;
import java.util.list;
/**
* @author chenhuirong
* @date 2018/12/10
* @description zhu
*/
public class histogramround extends chartydate {
private int[] rect_color;
private int rect_text_color;//矩形文字颜色
private int rect_big_text_color;//矩形最大文字颜色
private int rect_text_size;//矩形文字尺寸
private getnumberlistener listener;
private int selectindex = -1;
private int yheightselect=0;
private int leftselector=0;
private boolean isscrollow;//true 滑动 false点击
private list<integer> selectindexroles = new arraylist<>();
private list<object> objects=new arraylist<>();
public histogramround(context context) {
super(context);
}
public histogramround(context context, attributeset attrs, int defstyleattr) {
super(context, attrs, defstyleattr);
initstyle(context,attrs);
}
public histogramround(context context, attributeset attrs) {
super(context, attrs);
initstyle(context,attrs);
}
/*
* 初始化样式属性
*/
private void initstyle(context context,attributeset attrs) {
typedarray types = context.obtainstyledattributes(attrs, r.styleable.zqxchart_histogram);
coordinates_color = types.getcolor(r.styleable.zqxchart_histogram_hcoordinatescolor, color.red);
rect_text_color = types.getcolor(r.styleable.zqxchart_histogram_recttextcolor,color.black);
rect_big_text_color=getresources().getcolor(r.color.text_yellow);
rect_text_size = types.getinteger(r.styleable.zqxchart_histogram_recttextsize,28);
x_text_color = types.getcolor(r.styleable.zqxchart_histogram_hxtextcolor,color.black);
y_text_color = types.getcolor(r.styleable.zqxchart_histogram_hytextcolor,color.black);
x_text_size = types.getinteger(r.styleable.zqxchart_histogram_hxtextsize,30);
y_text_size = types.getinteger(r.styleable.zqxchart_histogram_hytextsize,28);
xpcount = types.getinteger(r.styleable.zqxchart_histogram_hxpointcount,12);
ypcount = types.getinteger(r.styleable.zqxchart_histogram_hypointcount,12);
rect_color = getresources().getintarray(r.array.histogram_color);
animtype = types.getinteger(r.styleable.zqxchart_histogram_hanimtype, anim.anim_none);
types.recycle();
}
@override
protected void ondraw(canvas canvas) {
super.ondraw(canvas);
if (xdata!=null&&ydata!=null){
drawhistogramround(canvas);
}
}
/*
* 画柱状图
*/
@targetapi(build.version_codes.lollipop)
private void drawhistogramround(canvas canvas) {
//如果没有设置x轴数据
if (xdata == null){
throw new nullpointerexception("x轴数据源不能为空!");
}
//如果没有设置y轴数据
if (ydata == null){
throw new nullpointerexception("y轴数据源不能为空!");
}
paint histogrampaint = new paint();
// histogrampaint.setantialias(true);
histogrampaint.setstyle(paint.style.fill);
histogrampaint.setstrokewidth((float) 4.0);
histogrampaint.setstrokecap(paint.cap.round);
//矩形上具体数据画笔
paint textpaint = new paint(paint.anti_alias_flag);
// tv_mudi.settextsize(typedvalue.complex_unit_px,getresources().getdimension(r.dimen.font_13));
// textpaint.settextsize(rect_text_size);
paint mpaintcircle = new paint(paint.anti_alias_flag);
// mpaintcircle.setstyle(paint.style.anti_alias_flag);
//
mpaintcircle.setstrokewidth(2);
mpaintcircle.setcolor(color.parsecolor("#ff5932"));
mpaintcircle.setpatheffect(new dashpatheffect(new float[]{4, 4}, 0));
mpaintcircle.setantialias(true);
textpaint.settextsize(getresources().getdimension(r.dimen.font_9));
decimalformat formater = new decimalformat("0.000");
for (int i=0; i<xpcount; i++){
try {
histogrampaint.setcolor(rect_color == null
? getresources().getcolor(r.color.colorprimary)
: rect_color[i]);
}catch (arrayindexoutofboundsexception e){
histogrampaint.setcolor(getresources().getcolor(r.color.colorprimary));
}
int alpha = anims[i].getalpha();
textpaint.setalpha(alpha);
histogrampaint.setalpha(alpha);
//计算执行动画当前y坐标
float top = anims[i].getcurrenty();
float left = ox+xcoordinates[i]-xspacing/5;
float right = ox+xcoordinates[i]+xspacing/3;
string a = formater.format(ydata[i]);
string ydata=a.substring(0,a.indexof("."));
int[] textsize = gettextsize(xdata[i],textpaint);
float texty = top - textsize[1]/2;
logutil2.log("ymax-------"+ymax+"--ydata--"+ydata);
if (float.valueof(ydata)>=ymax){
textpaint.setcolor(rect_big_text_color);
}else {
textpaint.setcolor(rect_text_color);
}
logutil2.log("ydata--------------->ydatay轴上的数据"+ydata);
//画矩形上文字
// canvas.drawtext(ydata,left+20,texty,textpaint);
//计算每条柱状图的宽度
// double tempbarwidth = (((int) mxinterval) >> 1) / mcategorylist.size();
// mbarpaint.setstrokewidth((float) tempbarwidth);
if (selectindex==i){
histogrampaint.setcolor(contextcompat.getcolor(getcontext(), r.color.name_ffa646));
//draw x 坐标
yheightselect= (int) top/*-getpaddingtop() */- getpaddingbottom()-xtextsurplus-x_text_size;
yheightselect= (int) (/*(oy+75)-(*/top/*+getpaddingtop()/)*/);
leftselector= (int) (left+(right-left)/2);
// canvas.drawline(ox,top, ox,top-yheight,mpaintcircle);
path path = new path();
path.moveto(ox, ox+xwidth+40);
path.lineto(ox, ox+xwidth+40);
// canvas.drawpath(path, mpaintcircle);
// canvas.drawline(ox,top,ox+xwidth+40,top,mpaintcircle);
if (!isscrollow){
listener.getnumber(i, (int) oy, leftselector,yheightselect, (int) ox);
}
logutil2.log("setselect--画:--getheight"+getheight()+"--left--"+left+"--height--"+yheightselect+"--top--"+top+"--oy--"+oy);
}else {
histogrampaint.setcolor(contextcompat.getcolor(getcontext(), r.color.color_1fa6fb));
}
//画每一个矩形
if(build.version.sdk_int >= build.version_codes.lollipop){
//画圆角柱只在5.0以上版本适用,以下版本会闪退
canvas.drawroundrect(left,top,right,oy,30,30,histogrampaint);
}else {
canvas.drawrect(left,top,right,oy,histogrampaint);
}
objects.add(histogrampaint);
}
}
public void setpublicrefresh(){
selectindex=-1;
invalidate();
for (int i=0;i<objects.size();i++){
paint paint= (paint) objects.get(i);
paint.setcolor(contextcompat.getcolor(getcontext(), r.color.color_1fa6fb));
logutil2.log("柱子--"+paint);
}
}
// public void isscrollow(boolean isscrollowt){
// this.isscrollow=isscrollowt;
// };
/*
* 设置数据
*/
@override
public void setchartydatedata(chartdata chartdata) {
super.setchartydatedata(chartdata);
histogramdata histogramdata = (histogramdata) chartdata;
this.rect_color = histogramdata.getrectcolor() != null ?
histogramdata.getrectcolor() : this.rect_color;
this.rect_text_size = getfinalvalue(this.rect_text_size,histogramdata.getrecttextsize());
this.rect_text_color = getfinalvalue(this.rect_text_color,histogramdata.getrecttextcolor());
}
@override
public void setonlongclicklistener(@nullable onlongclicklistener l) {
super.setonlongclicklistener(l);
logutil2.log("ondraw--getx---弹框的长按事件:" + isscrollow);
}
@override
protected void onoverscrolled(int scrollx, int scrolly, boolean clampedx, boolean clampedy) {
super.onoverscrolled(scrollx, scrolly, clampedx, clampedy);
logutil2.log("ondraw--getx---弹框的滑动事件:" + isscrollow);
}
@override
protected void onsizechanged(int w, int h, int oldw, int oldh) {
super.onsizechanged(w, h, oldw, oldh);
logutil2.log("ondraw--getx---弹框的滑动改变事件:" + isscrollow);
}
@override
public boolean ontouchevent(motionevent ev) {
int x =0;
int y =0;
int left = getpaddingleft()+ytextsurplus;
int top = 0;
int right = xwidth/ 12+getpaddingleft()+ytextsurplus;
int bottom = yheight;
// int right = getwidth()/ 12;
// int bottom = yheight;
switch (ev.getaction()) {
case motionevent.action_down:
x = (int) ev.getx();
y = (int) ev.gety();
logutil2.log("setselect--666down--x" + x + "--left--" + y + "ev--x" + ev.getx() + "ev--y" + ev.gety());
// if (isscrollow) {
/* for (int i = 0; i < 12; i++) {
rect rect = new rect(left, top, right, bottom);
left += xwidth / 12;
right += xwidth / 12;
if (rect.contains(x, y)) {
if (listener != null) {
logutil2.log("setselect--666down--x" + x + "--left--" + y + "ev--x" + ev.getx() + "ev--y" + ev.gety());
//抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
// if (math.abs(arithutil.sub(ev.getx(), x)) <= 20 && math.abs(arithutil.sub(ev.gety(), y)) <= 20) {
selectindex = i;
selectindexroles.clear();
selectindexroles.add(selectindex);
invalidate();
// }
}
}
}*/
// }
break;
case motionevent.action_move:
isscrollow=true;
logutil2.log("setselect--666move--x" + x + "--left--" + y + "ev--x" + ev.getx() + "ev--y" + ev.gety());
break;
case motionevent.action_up:
isscrollow=false;
x = (int) ev.getx();
y = (int) ev.gety();
logutil2.log("setselect--666up--x" + x + "--left--" + y + "ev--x" + ev.getx() + "ev--y" + ev.gety());
for (int i = 0; i < 12; i++) {
rect rect = new rect(left, top, right, bottom);
left += xwidth / 12;
right += xwidth / 12;
if (rect.contains(x, y)) {
if (listener != null) {
//抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
// if (math.abs(arithutil.sub(ev.getx(), x)) <= 20 && math.abs(arithutil.sub(ev.gety(), y)) <= 20) {
selectindex = i;
selectindexroles.clear();
selectindexroles.add(selectindex);
invalidate();
// }
}
}
}
break;
}
return true;
}
public void setlistener(getnumberlistener listener) {
this.listener = listener;
}
public interface getnumberlistener {
void getnumber(int number, int x, int y,int heightselect,int ox);
}
}
2.chartydate
package com.broker.liming.widget;
import android.content.context;
import android.graphics.bitmap;
import android.graphics.bitmapfactory;
import android.graphics.canvas;
import android.graphics.paint;
import android.graphics.rect;
import android.graphics.rectf;
import android.support.v4.content.contextcompat;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
import com.broker.liming.r;
import com.broker.liming.bean.chartdata;
import com.broker.liming.utils.densityutil;
import com.broker.liming.utils.doubleutils;
import com.broker.liming.utils.logutil2;
import java.math.bigdecimal;
import java.text.decimalformat;
import java.text.simpledateformat;
import java.util.arraylist;
import java.util.date;
import java.util.list;
/**
* @author chenhuirong
* @date 2018/12/10
* @description 统计图
*
* */
public class chartydate extends view {
protected final int xsurplus = 0;//x轴留余
protected final int ysurplus = 20;//y轴留余
protected final int xtextsurplus = 150;//x轴文字留余
protected final int ytextsurplus = 100;//y轴文字留余
protected float ox;//原点x
protected float oy;//原点y
protected int xwidth;//x轴宽度
protected int yheight;//y轴高度
protected int xspacing;//x轴坐标间距
protected int yspacing;//y轴坐标间距
protected int xpcount = 7;//x轴坐标点数
protected int ypcount = 7;//y轴坐标点数
protected int[] xcoordinates;//x轴坐标点
protected int[] ycoordinates;//y轴坐标点
protected float ymax = 0f;//y轴最大刻度值
protected string[] xdata;//x轴数据
protected float[] ydata;//y轴数据
protected int coordinates_color;//坐标系颜色
protected int x_text_size;//x轴文字尺寸
protected int y_text_size;//y轴文字尺寸
protected int x_text_color;//x轴文字颜色
protected int y_text_color;//y轴文字颜色
protected boolean isanim = true;
protected anim[] anims;//动画数组
protected long interval = 100;//动画执行间隔
protected int animtype = -2;//动画
private paint mtablevaluepaint;
// private getnumberlistener listener;
// private int selectindex = -1;
// private list<integer> selectindexroles = new arraylist<>();
public chartydate(context context) {
super(context);
}
public chartydate(context context, attributeset attrs, int defstyleattr) {
super(context, attrs, defstyleattr);
}
public chartydate(context context, attributeset attrs) {
super(context, attrs);
}
@override
protected void ondraw(canvas canvas) {
logutil2.log("ydata--------------->ondraw画布"+ypcount);
initchartydateprop();
initcoordinatesystem(canvas);
//开始动画
if (isanim){
initanims();
post(animator);
isanim = false;
}
}
/*
* 初始化统计图属性
*/
private void initchartydateprop() {
//x轴宽度
xwidth = getwidth() - getpaddingleft() - getpaddingright() - ytextsurplus;
//y轴宽度
yheight = getheight() - getpaddingtop() - getpaddingbottom() - xtextsurplus;
//x轴每个刻度的间距
xspacing = (xwidth-xsurplus-xwidth%xpcount)/xpcount;
//y轴每个刻度的间距
yspacing = (yheight-ysurplus-yheight%ypcount)/ypcount;
//坐标系原点x
ox = getpaddingleft()+ytextsurplus;
//坐标系原点y 减70为了画出当月图片
oy = getpaddingtop()+yheight+xtextsurplus/2-70;
//x轴各刻度点位置
xcoordinates = new int[xpcount];
//y轴各刻度点位置
ycoordinates = new int[ypcount];
//记录x轴刻度点位置 修改柱形图离坐标原点的距离
for (int i=0; i<xpcount; i++){
xcoordinates[i] = (i+1) * xspacing- 30;
}
logutil2.log("ydata--------------->ypcount记录y轴刻度点位置"+ypcount);
//记录y轴刻度点位置
for (int j=0; j<ypcount; j++){
ycoordinates[j] = (j+1) * yspacing;
logutil2.log("ydata--------------->henghe"+ycoordinates[j]);
}
logutil2.log("ydata--------------->ycoordinates记录y轴刻度点位置"+ycoordinates.length);
}
/*
* 初始化坐标系
*/
private void initcoordinatesystem(canvas canvas){
paint mainpaint = new paint();
mainpaint.setcolor(coordinates_color);
mainpaint.setantialias(true);
//draw x 坐标
// canvas.drawline(ox,oy, ox,oy-yheight,mainpaint);
//draw y 坐标
// canvas.drawline(ox,oy,ox+xwidth+40,oy,mainpaint);
//刻度值画笔
paint textpaint = new paint(paint.anti_alias_flag);
textpaint.setcolor(getresources().getcolor(r.color.transparent));
mtablevaluepaint = new paint();
mtablevaluepaint.setstrokewidth(densityutil.dip2px(getcontext(), 0.04f));
mtablevaluepaint.setstyle(paint.style.fill);
mtablevaluepaint.setcolor(contextcompat.getcolor(getcontext(), r.color.text_666666));
mtablevaluepaint.setantialias(true);
mtablevaluepaint.settextsize(densityutil.dip2px(getcontext(), 13));
//draw x 刻度
for (int i=0; i<xcoordinates.length; i++){
//更改文字大小
// textpaint.settextsize(x_text_size);
textpaint.settextsize(getresources().getdimension(r.dimen.font_9));
//更改文字颜色
textpaint.setcolor(x_text_color);
//x轴刻度线
// canvas.drawline(ox+xcoordinates[i],oy,ox+xcoordinates[i],oy-5,mainpaint);
//获取x轴文字宽高
if (xdata!=null&&xdata.length>0){
int[] textsize = gettextsize(xdata[i],textpaint);
//计算x轴文字x,y坐标偏移量
int textx = textsize[0]/2;
int texty = xtextsurplus/2 - textsize[1]/2;
//画x轴文字
canvas.drawtext(xdata[i],ox+xcoordinates[i]-textx,oy+texty,textpaint);
string[] strnow = new simpledateformat("yyyy-mm-dd").format(new date()).tostring().split("-");
integer year = integer.parseint(strnow[0]);
integer month = integer.parseint(strnow[1]);
//画当前月图片 + densityutil.dip2px(mcontext, 6)
if (month == integer.parseint(xdata[i])) {
bitmap arrow = bitmapfactory.decoderesource(getresources(), r.mipmap.current_month);
rectf rectf = new rectf((float) (ox+xcoordinates[i]-textx - densityutil.dip2px(getcontext(), 10)),
(float) (oy+texty+60 - densityutil.dip2px(getcontext(), 15)),
(float) (ox+xcoordinates[i]-textx + densityutil.dip2px(getcontext(), 20)),
(float) (oy+texty+70 - densityutil.dip2px(getcontext(), 3)));
canvas.drawbitmap(arrow, null, rectf, textpaint);
}
}
}
if(ymax == 0f){
ymax = getymax();
}
if(getymax()==0){
ymax=1.0f;
}
//draw y 刻度
for (int j=0; j<ypcount; j++){
//更改文字大小
textpaint.settextsize(y_text_size);
//y轴刻度线
// canvas.drawline(ox,oy-ycoordinates[j],ox+5,oy-ycoordinates[j],mainpaint);
//y轴刻度值
int iymax = (int)ymax;
string datay;
if (ymax - iymax == 0){
datay = (int)(ymax/ypcount*(j+1))+"";
}else {
datay = new decimalformat("0.000").format(ymax/ypcount*(j+1));
}
//平均分成4份
// double mmaxdiv = doubleutils.getlargerinterger(ymax, 7);
// datay= string.valueof((new bigdecimal((j + 1) * mmaxdiv).setscale(2, bigdecimal.round_half_up).doublevalue()));
int att=(int) math.floor(ymax);
string mbigst=string.valueof(att);
// string mbigst=string.valueof(ymax).substring(0, string.valueof(ymax).indexof("."));
int maxlength=mbigst.length();
int basemax= att+1;
if (maxlength>=2){
basemax= integer.valueof(mbigst.substring(0, 2))+1;
}
boolean isbreak=false;
int margcount=0;
string ii="";//画y轴最大值
string aa="";//间隔
for (int i=basemax;i<basemax+100;i++){
for (int a=100;a>0;a--){
if (i%a==0&&i/a<=6&&i/a>=4){
margcount=i/a;
ii= string.valueof(i);
aa=string .valueof(a);
isbreak=true;
break;
}
}
if (isbreak)
break;
}
for (int y=0;y<maxlength-2;y++){
aa=aa+"0";
ii=ii+"0";
}
// double mm=formattosepara2(double.valueof(aa));
// int mm+=integer.parseint(aa)*j;
//string.valueof(integer.parseint(aa)*(j+1))
datay= formattosepara2(double.valueof(integer.parseint(aa)*(j+1)));
//
logutil2.log("ydate---+++"+datay+"---"+ii);
//获取文字宽高
int[] textsize = gettextsize(datay,textpaint);
//计算画文字的坐标偏移量
int textx = ytextsurplus/2 + textsize[0]/2;
int texty = textsize[1]/2;
//画y轴文字
textpaint.setcolor(y_text_color);
if (j==0){
canvas.drawtext("0",ox-textx,oy,textpaint);
}
canvas.drawtext(datay,ox-textx,oy-ycoordinates[j]+texty,textpaint);
}
logutil2.log("ydate---+++"+ydata.tostring());
}
public string formattosepara2(double data) {
int length = string.valueof(data).split("\\.")[0].length();
if (length < 4) {
return string.format("%.2f", data);
}
decimalformat df = new decimalformat("##,###");
return df.format(data);
}
/*
* 准备动画
*/
private void initanims() {
anims = new anim[xpcount];
// switch (animtype){
// case anim.anim_translate:
// for (int i=0;i<xpcount;i++){
// float datax = ox+xcoordinates[i];
// float datay = oy-ydata[i]/ymax*ycoordinates[ycoordinates.length-1];
// anim anim = new anim(datax,datay,datax,oy);
// anim.setanimation(new translateanim());
// anim.setvelocity(interval*2);
// anims[i] = anim;
// }
// break;
// case anim.anim_alpha:
// for (int i=0;i<xpcount;i++){
// float datax = ox+xcoordinates[i];
// float datay = oy-ydata[i]/ymax*ycoordinates[ycoordinates.length-1];
// anim anim = new anim(datax,datay,datax,datay);
// anim.setanimation(new alphaanim());
// anim.setalpha(0);
// anim.setvelocity(interval * 3/2);
// anims[i] = anim;
// }
// break;
// default:
// for (int i=0;i<xpcount;i++){
// float datax = ox+xcoordinates[i];
// float datay = oy-ydata[i]/ymax*ycoordinates[ycoordinates.length-1];
// anim anim = new anim(datax,datay,datax,datay);
// anim.setanimation(new translateanim());
// anim.setvelocity(interval);
// anims[i] = anim;
// }
for (int i=0;i<xpcount;i++){
float datax = ox+xcoordinates[i];
logutil2.log("ydata----------datax"+ox+xcoordinates[i]);
logutil2.log("ydata----------ydata"+ydata.length);
logutil2.log("ydata----------xpcount"+xpcount);
logutil2.log("ydata----------ycoordinates"+ycoordinates.length);
//平均分成4份
double mmaxdi = doubleutils.getlargerinterger(ymax, 7);
//设置y轴分值
float total=0;
// float total= (float) new bigdecimal((7) * mmaxdi).setscale(2, bigdecimal.round_half_up).doublevalue();
logutil2.log("最大值--"+ymax);
int att=(int) math.floor(ymax);
string mbigst=string.valueof(att);
// string mbigst=string.valueof((int) math.floor(ymax));
logutil2.log("最大值--"+ymax+"---"+mbigst);
// string mbigst=string.valueof(ymax).substring(0, string.valueof(ymax).indexof("."));
int maxlength=mbigst.length();
int basemax= att+1;
if (maxlength>=2){
basemax= integer.valueof(mbigst.substring(0, 2))+1;
}
boolean isbreak=false;
string aa="";//间隔值
string ii="";//y轴最大
int margcount=0;//分多少份,动态设置
for (int j=basemax;j<basemax+100;j++){
for (int a=100;a>0;a--){
if (j%a==0&&j/a<=6&&j/a>=4){
margcount=j/a;
aa=string.valueof(a);
ii=string.valueof(j);
isbreak=true;
break;
}
}
if (isbreak)
break;
}
for (int y=0;y<maxlength-2;y++){
aa=aa+"0";
ii=ii+"0";
// total= float.parsefloat(string.valueof(basemax)+"0");
}
logutil2.log("total"+total);
total= float.parsefloat(ii);
logutil2.log("aa--"+aa+"--total"+total);
float datay = oy-ydata[i]/total*ycoordinates[ycoordinates.length-1];
logutil2.log("ydata----------datay"+datay);
anim anim = new anim(datax,datay,datax,datay);
anim.setanimation(new translateanim());
anim.setvelocity(interval);
anims[i] = anim;
logutil2.log("ydata----------anims"+anims);
}
// break;
// }
}
/*
* 获取y轴最大值
*/
protected float getymax(){
if (ydata == null || ydata.length == 0){
ydata = new float[ypcount];
}
float max =0;
for (int i=0; i<ydata.length; i++){
if (max < ydata[i]){
max = ydata[i];
}
}
return max;
}
/*
* 获取文字宽高
*/
protected int[] gettextsize(string str,paint paint){
//计算文字所在矩形,可以得到宽高
rect rect = new rect();
paint.gettextbounds(str, 0, str.length(), rect);
int w = rect.width();
int h = rect.height();
return new int[]{w,h};
}
/*
* 设置统计图属性
*/
public void setchartydatedata(chartdata chartdata) {
if (chartdata == null){
throw new nullpointerexception("折线图数据不能为空!");
}
this.xdata = chartdata.getxdata();
this.ydata = chartdata.getydata();
this.xpcount = getfinalvalue(this.xpcount,chartdata.getxpcount());
this.ypcount = getfinalvalue(this.ypcount,chartdata.getypcount());
this.coordinates_color = getfinalvalue(this.coordinates_color,chartdata.getcoordinatescolor());
this.x_text_size = getfinalvalue(this.x_text_size,chartdata.getxtextsize());
this.y_text_size = getfinalvalue(this.y_text_size,chartdata.getytextsize());
this.x_text_color = getfinalvalue(this.x_text_color,chartdata.getxtextcolor());
this.y_text_color = getfinalvalue(this.y_text_color,chartdata.getytextcolor());
this.interval = getfinalvalue((int) this.interval,chartdata.getinterval());
// this.animtype = chartdata.getanimtype() != -2 ? chartdata.getanimtype()
// : this.animtype;
this.ymax = chartdata.getymax() != 0f ? chartdata.getymax() : this.ymax;
}
/*
* 设置正确属性值
*/
protected int getfinalvalue(int old,int news){
old = news != 0 ? news : old;
return old;
}
/*
* 执行动画runnable
*/
private runnable animator = new runnable() {
@override
public void run() {
logutil2.log("ydata----------anims循环"+anims);
logutil2.log("ydata----------anims长多"+anims.length);
for(anim a : anims){
logutil2.log("ydata----------anims循环2"+a.isover());
if(!a.isover()){
a.refresh();
postdelayed(this, interval);
invalidate();
return;
}
}
}
};
/*
* 更新数据并重绘
*/
public void update(chartdata chartdata){
ymax = 0;
setchartydatedata(chartdata);
isanim = true;
invalidate();
}
/* @override
public boolean ontouchevent(motionevent ev) {
int x = (int) ev.getx();
int y = (int) ev.gety();
int left = 0;
int top = 0;
int right = xwidth/ 12;
int bottom = yheight;
switch (ev.getaction()) {
case motionevent.action_down:
for (int i = 0; i < 12; i++) {
rect rect = new rect(left, top, right, bottom);
left += xwidth / 12;
right += xwidth / 12;
if (rect.contains(x, y)) {
if (listener != null) {
listener.getnumber(i, x, y);
// isselect=true;
// number = i;
selectindex = i;
selectindexroles.clear();
selectindexroles.add(selectindex);
invalidate();
}
}
}
break;
case motionevent.action_up:
break;
}
return true;
}
public void setlistener(getnumberlistener listener) {
this.listener = listener;
}
public interface getnumberlistener {
void getnumber(int number, int x, int y);
}*/
}
3.布局 activity_family_status嵌套在scrollowview中
<android.support.v4.widget.nestedscrollview android:id="@+id/scrollowview" android:layout_width="match_parent" android:layout_height="wrap_content" android:fillviewport="true" android:layout_marginbottom="@dimen/lay_10" > <linearlayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <com.broker.liming.widget.histogramround android:id="@+id/histogramchart" android:layout_width="@dimen/lay_320" android:layout_height="220dp" android:layout_marginleft="@dimen/lay_12" chart:hcoordinatescolor="@color/text_999999" chart:hxtextcolor="@color/color_6a6a6a" chart:hytextcolor="@color/color_1fa6fb" /> <linearlayout/> <android.support.v4.widget.nestedscrollview/>
4.运用familystatusactivity
package com.broker.liming.activity;
import android.content.context;
import android.content.intent;
import android.support.annotation.requiresapi;
import android.support.v4.widget.nestedscrollview;
import android.support.v7.widget.linearlayoutmanager;
import com.broker.liming.utils.arithutil;
import com.broker.liming.utils.barutils;
import com.broker.liming.utils.gsonutils;
import com.broker.liming.utils.logutil2;
import com.broker.liming.utils.uihelper;
import com.broker.liming.widget.histogramdata;
import com.broker.liming.widget.histogramround;
import com.broker.liming.widget.titlebar;
import org.json.jsonexception;
import java.text.decimalformat;
import java.text.simpledateformat;
import java.util.arraylist;
import java.util.arrays;
import java.util.date;
import java.util.list;
import butterknife.bindview;
import static com.sobot.chat.utils.screenutils.dip2px;
import static com.sobot.chat.utils.screenutils.px2dip;
/**
* @descpription:家庭现状
* @date: 2019/7/17.
* @author:chenhuirong
*/
public class familystatusactivity extends baseactivity{
@bindview(r.id.histogramchart)
histogramround histogramchart;
@bindview(r.id.scrollowview)
nestedscrollview scrollowview;
private familystatusadapter adapter;
private familystatusrateadapter rateadapter;
private histogramdata histogramdata;
//柱状图
// @bindview(r.id.my_single_chart_view)
// singleview mmysinglechartview;
@bindview(r.id.rl_single)
relativelayout rlsingle;
private list<float> singlelist;
private linearlayout llsingle;
private double mmax = 44;
private list<familypremiumarraybean> listdata = new arraylist<>();
private string monthback;
float[] ydata = new float[12];
private string[] xdata= new string[12] ;
private string[] xdatashow= new string[12] ;//仅为显示
private boolean isscrollow=true;
private boolean isfresh=false;
int margcount=0;//共分多少份
private linearlayout line;
private string name;
public static void actionstart(context context, string familyuuid,string names) {
intent intent = new intent(context, familystatusactivity.class);
intent.putextra("familyuuid", familyuuid);
intent.putextra("name",names);
context.startactivity(intent);
}
@override
protected void inittitlebar() {
titlebar titlebar = (titlebar) findviewbyid(r.id.title_bar);
assert titlebar != null;
/*titlebar.setleftbackground(r.mipmap.back);*/
titlebar.setleftbackground(r.mipmap.order_back);
titlebar.settitle(name+"的家庭数据分析");
titlebar.settitlecolor(r.color.text_000000);
titlebar.settitlebarbg(getresources().getcolor(r.color.white));
titlebar.setleftclicklistener(new view.onclicklistener() {
@override
public void onclick(view v) {
finish();
}
});
}
@override
protected int getcontentview() {
return r.layout.activity_family_status;
}
@override
protected boolean initbundle(bundle bundle) {
}
@override
public void initdata() {
super.initdata();
}
@override
protected void onresume() {
super.onresume();
getpiedate(familyuuid);
}
public void gethomedata() {
try {
userbean query = userbeandao.query();
requestserverpostform(false, 100, httpparams.getfamilystatus(query, familyuuid));
} catch (jsonexception e) {
e.printstacktrace();
}
}
@override
public void initview() {
xdata=new string[]{"1","2","3","4","5","6","7","8","9","10","11","12"};
xdatashow=new string[]{"01","02","03","04","05","06","07","08","09","10","11","12"};
initsingle();
scrollowview.setontouchlistener(new view.ontouchlistener() {
@override
public boolean ontouch(view v, motionevent event) {
logutil2.log("ondraw--getx---isscrollow" +isscrollow);
float x=0;
float y=0;
switch (event.getaction()) {
case motionevent.action_down:
x = event.getx();
y = event.gety();
logutil2.log("ondraw--getx---down" + event.getx() + "---" + y);
break;
case motionevent.action_move:
logutil2.log("ondraw--getx---move:" + event.getx() + "---");
// isfresh=true;
//在此刷新柱状图,防止多次刷新,多次重绘
if (isscrollow){
rlsingle.removeview(llsingle);
rlsingle.removeview(line);
histogramchart.setpublicrefresh();
// histogramchart.isscrollow(isfresh);
isscrollow=false;
}
break;
case motionevent.action_cancel:
case motionevent.action_up:
//
//允许scrollview截断点击事件,scrollview可滑动
logutil2.log("ondraw--getx---up" + event.getx() + "mlastwowny:" + event.gety()+"x差值:"+math.abs(arithutil.sub(event.getx(), x))+"--y差值:"+ math.abs(arithutil.sub(event.gety(), y)) );
//抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
/* if (math.abs(arithutil.sub(event.getx(), x)) <= 20 && math.abs(arithutil.sub(event.gety(), y)) <= 20) {
// isscrollow=false;
ischeck=true;
}else {
// isscrollow=true;
ischeck=false;
histogramchart.isscrollow(false);
rlsingle.removeview(llsingle);
rlsingle.removeview(line);
if (isscrollow){
histogramchart.setpublicrefresh();
isscrollow=false;
}
}*/
break;
}
return false;
}
});
changestatusbartextcolor(true);
barutils.setcolornotranslucent(this, getresources().getcolor(r.color.white));
}
/**
* 弹出弹框
*/
private void initsingle(){
rlsingle = (relativelayout) findviewbyid(r.id.rl_single);
singlelist = new arraylist<>();
rlsingle.removeview(llsingle);
rlsingle.removeview(line);
histogramchart.setonlongclicklistener(new view.onlongclicklistener() {
@override
public boolean onlongclick(view v) {
logutil2.log("ondraw--getx---弹框的长按事件:" + isscrollow);
return false;
}
});
histogramchart.setlistener(new histogramround.getnumberlistener() {
@override
public void getnumber(int index, int height, int left,int selectorheight,int ox) {
// rlsingle.removeallviews();
logutil2.log("ondraw--getx---弹框:" + isscrollow);
isscrollow=true;
// if(!isfresh){
rlsingle.removeview(llsingle);
rlsingle.removeview(line);
line= (linearlayout) layoutinflater.from(familystatusactivity.this).inflate(r.layout.layout_dash_line, null);
// textview view=new textview(mcontext);
// view.setbackground(mcontext.getresources().getdrawable(r.drawable.shape_dash_line));
relativelayout.layoutparams viewparam=new relativelayout.layoutparams(relativelayout.layoutparams.match_parent, relativelayout.layoutparams.wrap_content);viewparam. topmargin=height-selectorheight;
viewparam.topmargin=selectorheight-5;
viewparam.leftmargin=dip2px(mcontext,40);
viewparam.rightmargin=dip2px(mcontext,30);
line.setlayoutparams(viewparam);
rlsingle.addview(line);
llsingle = (linearlayout) layoutinflater.from(familystatusactivity.this).inflate(r.layout.layout_pro_expense, null);
linearlayout ll_back=(linearlayout)llsingle.findviewbyid(r.id.ll_back);
textview tvmoney = (textview) llsingle.findviewbyid(r.id.tv_month);
textview tv_money=(textview) llsingle.findviewbyid(r.id.tv_money);
if (singlelist!=null&&singlelist.size()>0){
tv_money.settext(formattosepara2(singlelist.get(index))+"");
}else {
tv_money.settext("0");
}
string[] strnow = new simpledateformat("yyyy-mm-dd").format(new date()).tostring().split("-");
string year = strnow[0];
tvmoney.settext(year+"-"+xdatashow[index]);
relativelayout.layoutparams params = new relativelayout.layoutparams(relativelayout.layoutparams.wrap_content,
relativelayout.layoutparams.wrap_content);
logutil2.log("setselect--callback--"+height+"--left---"+left+"---"+selectorheight+"弹框高--"+dip2px(mcontext,60)+"--差值--"+(height-(height-selectorheight/*+px2dip(mcontext,70)*/)-dip2px(mcontext,60)));
logutil2.log("----宽-----+++"+params.width);
logutil2.log("setselect--转换"+px2dip(mcontext,height)+"--left---"+px2dip(mcontext,left)+"---"+dip2px(mcontext,selectorheight));
int topmargin=0;
int leftmargin=0;
logutil2.log("setselect--差距"+px2dip(mcontext,height-selectorheight));
if (index+1>6){
if (height-(height-selectorheight)-dip2px(mcontext,60)-dip2px(mcontext,5)>0){
ll_back.setbackground(mcontext.getresources().getdrawable(r.mipmap.right_bottom));
topmargin=height-(height-selectorheight)-dip2px(mcontext,60)-dip2px(mcontext,5)/*+dip2px(mcontext,70)*/;
}else {
topmargin= height-(height-selectorheight)+dip2px(mcontext,5)/*+dip2px(mcontext,70)*/;
ll_back.setbackground(mcontext.getresources().getdrawable(r.mipmap.right_top));
}
//
leftmargin=left-dip2px(mcontext,150)+dip2px(mcontext,40);
}else {
if (height-(height-selectorheight)-dip2px(mcontext,60)-dip2px(mcontext,5)>0){
ll_back.setbackground(mcontext.getresources().getdrawable(r.mipmap.left_bottom));
topmargin=height-(height-selectorheight)-dip2px(mcontext,60)-dip2px(mcontext,5);
}else {
ll_back.setbackground(mcontext.getresources().getdrawable(r.mipmap.left_top));
topmargin=height-(height-selectorheight)+dip2px(mcontext,5);
}
leftmargin=left;
}
params.leftmargin = leftmargin;
//相当于总布局的上方,需要减去家庭保费和保费距离
params.topmargin=topmargin/* selectorheight+px2dip(mcontext,64)*/;
// logutil2.log("setselect--callback--"+histogramchart.getheight()+"---"+selectorheight+"---left"+ params.topmargin);
// if (x - 100 < 0) {
// params.leftmargin = 0;
// } else if (x - 100 > relativelayout.getwidth() - llsingle.getmeasuredwidth()) {
// params.leftmargin = relativelayout.getwidth() - llsingle.getmeasuredwidth();
// }
llsingle.setlayoutparams(params);
rlsingle.addview(llsingle);
// }
}
});
}
private void changestatusbartextcolor(boolean isblack) {
if (build.version.sdk_int > build.version_codes.m) {
if (isblack) {
getwindow().getdecorview().setsystemuivisibility(view.system_ui_flag_light_status_bar);//设置状态栏黑色字体
}else {
getwindow().getdecorview().setsystemuivisibility(view.system_ui_flag_visible);//恢复状态栏白色字体
}
}
}
private void setdate(familyyearcheakbean yearcheakbean) {
if (yearcheakbean != null) {
if (yearcheakbean.familypremiumtotal != null && !yearcheakbean.familypremiumtotal.equals("")) {
tv_total_money.settext("合计年缴"+formattosepara(double.valueof(string.valueof(yearcheakbean.familypremiumtotal))) + "元");
}else {
tv_total_money.settext("合计年缴0.00元");
}
string[] strnow = new simpledateformat("yyyy-mm-dd").format(new date()).tostring().split("-");
integer year = integer.parseint(strnow[0]);
integer month = integer.parseint(strnow[1]);
listdata = yearcheakbean.familypremiumarray;
list<double> list = new arraylist<>();
arraylist<dotvo> temp = new arraylist();
for (int i = 0; i < listdata.size(); i++) {
familypremiumarraybean bean = listdata.get(i);
string yearback = bean.month.substring(0, bean.month.indexof("-"));
monthback = bean.month.substring(bean.month.lastindexof("-") + 1);
// mxdots[i] = yearback + "年\n" + monthback + "月";
list.add(double.valueof(bean.premium));
double premium = 0;
if (bean.premium != null && !bean.premium.equals("")) {
premium = double.valueof(bean.premium);
list.add(double.valueof(bean.premium));
singlelist.add(float.valueof(bean.premium));
ydata[i]=float.valueof(bean.premium);
}
dotvo tempdotvo = new dotvo(monthback, premium);
temp.add(tempdotvo);
}
double[] tobestored = list.toarray(new double[list.size()]);
mmax = checkmax(tobestored);
}
//向下取整
int att=(int) math.floor(mmax);
string mbigst=string.valueof(att);
int maxlength=mbigst.length();
int basemax= att+1;
if (maxlength>=2){
basemax= integer.valueof(mbigst.substring(0, 2))+1;
}
boolean isbreak=false;
for (int i=basemax;i<basemax+100;i++){
for (int a=100;a>0;a--){
if (i%a==0&&i/a<=6&&i/a>=4){
margcount=i/a;
isbreak=true;
break;
}
}
if (isbreak)
break;
}
for (int i=0;i<maxlength-2;i++){
}
logutil2.log("ydata---设置数据"+ydata.tostring()+"--最大分数--"+margcount);
histogramdata = histogramdata.builder()
.setxdata(xdata)
.setydata(ydata)
.setypcount(margcount)
// .setanimtype(anim.anim_alpha)
.build();
histogramchart.setchartydatedata(histogramdata);
histogramchart.update(histogramdata);
}
public double checkmax(double[] args) {
double max = 0;
for (int i = 0; i < args.length; i++) {
if (args[i] > max) {
max = args[i];
}
}
return max;
}
@override
protected void onsuccess(string response, int id) {
super.onsuccess(response, id);
switch (id){
case 200:
yearcheakbean= gsonutils.toobject(response,familyyearcheakbean.class);
setdate(yearcheakbean);
break;
}
}
/**
* 将float类型的数据转换成以4位逗号隔开的字符串,并且保留两位有效数字
*/
public string formattosepara(double data) {
int length = string.valueof(data).split("\\.")[0].length();
if (length < 4) {
return string.format("%.2f", data);
}
decimalformat df = new decimalformat("#,####.00");
return df.format(data);
}
public string formattosepara2(double data) {
int length = string.valueof(data).split("\\.")[0].length();
if (length < 4) {
return string.format("%.2f", data);
}
decimalformat df = new decimalformat("##,###");
return df.format(data);
}
}
5.histogramdata
package com.broker.liming.widget;
import com.broker.liming.bean.chartdata;
/**
* @author chenhuirong
* @date 2018/12/10
* @description 柱状图s
*/
public class histogramdata extends chartdata {
private int[] rectcolor;
private int recttextcolor;
private int recttextsize;
private histogramdata(builder builder) {
setxdata(builder.xdata);
setydata(builder.ydata);
setxpcount(builder.xpcount);
setypcount(builder.ypcount);
setcoordinatescolor(builder.coordinatescolor);
setxtextsize(builder.xtextsize);
setytextsize(builder.ytextsize);
setxtextcolor(builder.xtextcolor);
setytextcolor(builder.ytextcolor);
setymax(builder.ymax);
setinterval(builder.interval);
setanimtype(builder.animtype);
setrectcolor(builder.rectcolor);
setrecttextcolor(builder.recttextcolor);
setrecttextsize(builder.recttextsize);
}
public static builder builder() {
return new builder();
}
public int[] getrectcolor() {
return rectcolor;
}
public void setrectcolor(int[] rectcolor) {
this.rectcolor = rectcolor;
}
public int getrecttextcolor() {
return recttextcolor;
}
public void setrecttextcolor(int recttextcolor) {
this.recttextcolor = recttextcolor;
}
public int getrecttextsize() {
return recttextsize;
}
public void setrecttextsize(int recttextsize) {
this.recttextsize = recttextsize;
}
public static final class builder{
private int recttextsize;
private int recttextcolor;
private int[] rectcolor;
private int animtype;
private int interval;
private int ymax;
private int ytextcolor;
private int xtextcolor;
private int ytextsize;
private int xtextsize;
private int coordinatescolor;
private int ypcount;
private int xpcount;
private float[] ydata;
private string[] xdata;
private builder(){}
public builder setrecttextsize(int val) {
recttextsize = val;
return this;
}
public builder setrecttextcolor(int val) {
recttextcolor = val;
return this;
}
public builder setrectcolor(int[] val) {
rectcolor = val;
return this;
}
public builder setanimtype(int val) {
animtype = val;
return this;
}
public builder setinterval(int val) {
interval = val;
return this;
}
public builder setymax(int val) {
ymax = val;
return this;
}
public builder setytextcolor(int val) {
ytextcolor = val;
return this;
}
public builder setxtextcolor(int val) {
xtextcolor = val;
return this;
}
public builder setytextsize(int val) {
ytextsize = val;
return this;
}
public builder setxtextsize(int val) {
xtextsize = val;
return this;
}
public builder setcoordinatescolor(int val) {
coordinatescolor = val;
return this;
}
public builder setypcount(int val) {
ypcount = val;
return this;
}
public builder setxpcount(int val) {
xpcount = val;
return this;
}
public builder setydata(float[] val) {
ydata = val;
return this;
}
public builder setxdata(string[] val) {
xdata = val;
return this;
}
public histogramdata build() {
return new histogramdata(this);
}
}
}
6.chartdata
package com.broker.liming.bean;
/**
* 统计图父类数据类
* created by zqx on 16/6/27.
*/
public class chartdata {
protected string[] xdata;
protected float[] ydata;
protected int xpcount;
protected int ypcount;
protected int coordinatescolor;
protected int xtextsize;
protected int ytextsize;
protected int xtextcolor;
protected int ytextcolor;
protected int ymax;
protected int interval;
protected int animtype = -2;
protected chartdata(){}
public string[] getxdata() {
return xdata;
}
public void setxdata(string[] xdata) {
this.xdata = xdata;
}
public float[] getydata() {
return ydata;
}
public void setydata(float[] ydata) {
this.ydata = ydata;
}
public int getxpcount() {
return xpcount;
}
public void setxpcount(int xpcount) {
this.xpcount = xpcount;
}
public int getypcount() {
return ypcount;
}
public void setypcount(int ypcount) {
this.ypcount = ypcount;
}
public int getcoordinatescolor() {
return coordinatescolor;
}
public void setcoordinatescolor(int coordinatescolor) {
this.coordinatescolor = coordinatescolor;
}
public int getxtextsize() {
return xtextsize;
}
public void setxtextsize(int xtextsize) {
this.xtextsize = xtextsize;
}
public int getytextsize() {
return ytextsize;
}
public void setytextsize(int ytextsize) {
this.ytextsize = ytextsize;
}
public int getxtextcolor() {
return xtextcolor;
}
public void setxtextcolor(int xtextcolor) {
this.xtextcolor = xtextcolor;
}
public int getytextcolor() {
return ytextcolor;
}
public void setytextcolor(int ytextcolor) {
this.ytextcolor = ytextcolor;
}
public int getymax() {
return ymax;
}
public void setymax(int ymax) {
this.ymax = ymax;
}
public int getinterval() {
return interval;
}
public void setinterval(int interval) {
this.interval = interval;
}
public int getanimtype() {
return animtype;
}
public void setanimtype(int animtype) {
this.animtype = animtype;
}
}
注:参考demo时间太久我忘记了,网上可找到
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持www.887551.com。