意见箱
恒创运营部门将仔细参阅您的意见和建议,必要时将通过预留邮箱与您保持联络。感谢您的支持!
意见/建议
提交建议

Android项目(一):自定义View绘制“柱状图”

来源:恒创科技 编辑:恒创科技编辑部
2024-02-02 22:09:59


Android  项目(一):自定义View绘制“柱状图”_柱状图



Android项目(一):自定义View绘制“柱状图”

  为什么要绘制柱状图?这是因为在有些应用中需要展示数据,单纯的列出一些数据估计谁看了都会烦,因此数据的展示通常会使用一些图表的形式展现出来。

  上面的柱子是怎样绘制的呢?先来梳理一下思路:通过上面的图片展示可以看出来,需要一个白色的背景+一个留有上下边距的矩形区域+顶部空白处的文本+底部空白处的文本+中间的柱形图(实际上是绘制的线,线的画笔给的宽了一点,你也可以采用绘制矩形的方式只是绘制矩形需要左上右下坐标,计算坐标比较麻烦,还是建议采用线条的形式),最后,为了让图表能够滑动,需要将整个自定义view放置到一个HorizontalScrollView上面去(这里为了以后管理的方便性,我创建了一个继承于HorizontalScrollView的class,将柱状图添加到其中放置)。

  PS:原谅我底部的“张三”的信息没有调试好位置

相关文章

​​[ Android 项目(一):自定义View绘制“折线图” ]​​​
可以先参考上面的博客,也可以直接看这篇文章,上面的博客由于绘制比较麻烦,我先写的准备工作,这篇博客由于绘制简单,就直接看如何绘制柱状图了。

一、绘制柱状图

柱状图的绘制直接看代码吧,思路就是上面介绍的。

/**
* Created by Administrator on 2015/10/12.
*/
public class Histogromview extends View
//view 的宽与高
private int width;
private int heigh;


//单个柱状图的间隔与宽度
private int hisgrom_space;
private int hisgrom_width;

//柱状图上边距和下边距
private int histogrom_topspa;
private int histogrom_bottomspa;

//矩形背景的画笔
private Paint mpaint_bg;

//单个柱子的背景
private Paint mpaint_hisbg;
//单个柱子的颜色
private Paint mpaint_hiscolor;
//文本的画笔
private Paint mapint_text;
private Paint.FontMetrics mMetrics;

//总的数据个数
private int totaldata;

//绘制图形时需要用到的数据,数据在MainActivity中添加,
//Histogrom是Dao模式的数据
private List<Histogrom> mdata=new ArrayList<>();


//两个构造器
public Histogromview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);

}



public Histogromview(Context context) {
super(context);

}

//mdata的set/get方法
public List<Histogrom> getMdata() {
return mdata;
}

public void setMdata(List<Histogrom> mdata) {
this.mdata = mdata;
requestLayout();//相当于调用onMeasure方法
invalidate();//相当于调用onDraw方法
}

private void init(Context context){
//调用了一个dp转px的方法,网上有很多这样的方法
histogrom_topspa=SizeConvert.dip2px(context,20);
histogrom_bottomspa=SizeConvert.dip2px(context, 50);
hisgrom_width=SizeConvert.dip2px(context, 10);
hisgrom_space=SizeConvert.dip2px(context, 30);

//画笔的背景颜色(灰色的背景)
mpaint_bg=new Paint(Paint.ANTI_ALIAS_FLAG);
mpaint_bg.setColor(Color.argb(0xff,0xef,0xef,0xef));

//设置柱状图的背景颜色
mpaint_hisbg=new Paint(Paint.ANTI_ALIAS_FLAG);
mpaint_hisbg.setColor(Color.argb(0xff, 0xce, 0xcb, 0xce));
mpaint_hisbg.setStrokeWidth(hisgrom_width);

//设置柱状图的颜色
mpaint_hiscolor=new Paint(Paint.ANTI_ALIAS_FLAG);
mpaint_hiscolor.setColor(Color.RED);
mpaint_hiscolor.setStrokeCap(Paint.Cap.ROUND);
mpaint_hiscolor.setStrokeJoin(Paint.Join.ROUND);
mpaint_hiscolor.setStrokeWidth(hisgrom_width);

mapint_text=new Paint(Paint.ANTI_ALIAS_FLAG);
mapint_text.setColor(Color.BLACK);
// mapint_text.setTextAlign(Paint.Align.CENTER);
mMetrics=mapint_text.getFontMetrics();
}

public void setTotaldata(int totaldata) {
this.totaldata = totaldata;
invalidate();
}

public int getTotaldata() {
return totaldata;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画布的白色背景
canvas.drawColor(Color.WHITE);
//画布分灰色矩形区域,上下各自留出一定空白区域
canvas.drawRect(0,heigh-histogrom_bottomspa,width,histogrom_topspa,mpaint_bg);

//柱状图的绘制
for(int i=0;i<totaldata;i++){

//如果数据中没有数据就添加数据
if(mdata==null){
Histogrom histogrom=new Histogrom("张三",0);
mdata.add(histogrom);
}

//开始绘制
//绘制顶部百分数文本
String percent_str=mdata.get(i).getPercent()+"%";
canvas.drawText(percent_str, hisgrom_space * (i + 1),histogrom_topspa/2, mapint_text);

//绘制单个灰色柱子(总长度为100%)
canvas.drawLine(hisgrom_space * (i + 1),heigh - histogrom_bottomspa, hisgrom_space * (i + 1) ,histogrom_topspa , mpaint_hisbg);

//根据数据中的百分比绘制柱子高度
float dataheigh=mdata.get(i).getPercent();
canvas.drawLine(hisgrom_space * (i + 1), heigh - histogrom_bottomspa, hisgrom_space * (i + 1), heigh - histogrom_bottomspa - (heigh - histogrom_bottomspa - (histogrom_topspa + (mMetrics.descent - mMetrics.ascent))) * dataheigh / 100, mpaint_hiscolor);

//旋转画布,绘制底部文本
canvas.save();
canvas.rotate(-45, (hisgrom_space + hisgrom_width) * (i + 1) , heigh - histogrom_bottomspa );
String name_str=mdata.get(i).getName();
canvas.drawText(name_str,(hisgrom_space + hisgrom_width) * (i + 1)-histogrom_topspa-mapint_text.measureText(name_str), heigh - histogrom_bottomspa, mapint_text);
canvas.restore();


}

}
private ViewGroup findHorizontalScrollView(View view) {
ViewGroup parent = (ViewGroup) view.getParent();
if(parent instanceof HorizontalScrollView) return parent;
else return findHorizontalScrollView(parent);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ViewGroup horizontalScrollView = findHorizontalScrollView(this);
if(mdata.size()==0){
//这里是一个获的父布局宽度的方法,自定义view的
width=horizontalScrollView.getMeasuredWidth();
// width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
}
else{
//根据数据的多少确定绘制的宽度
width=(hisgrom_space+hisgrom_width)*(mdata.size()+1);
}

heigh=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width,heigh);

}
}
二、自定义View继承HorizontalScrollView

这个自定义view主要是用来添加柱状图的,也可以直接将自定义view添加到一个HorizontalScrollView 中。

自定义view的xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<widget.chart.Histogromview
android:id="@+id/histogromview"
android:layout_width="match_parent"
android:layout_height="match_parent"</widget.chart.Histogromview>
</LinearLayout>
自定义的HorizontalScrollview
/**
* Created by Administrator on 2015/10/12.
*/
public class Scrollhistogrom extends HorizontalScrollView

private int width;
private int heigh;


public Scrollhistogrom(Context context) {
super(context);
}

public Scrollhistogrom(Context context, AttributeSet attrs) {
super(context, attrs);
//添加自定义的柱状图,绘制的柱状图直接放在一个布局中
LayoutInflater inflater= (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View view=inflater.inflate(R.layout.activity_histogromview,null);

addView(view);
// View.inflate(context, R.layout.activity_histogromview,this);

// View v=LayoutInflater.from(context).inflate(R.layout.activity_histogromview,this,false);
// addView(v);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
heigh=getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);

setMeasuredDimension(width, heigh);
}
}
使用自定义的HorizontalScrollView

xml

<LinearLayout
android:id="@+id/activity_report_chart_histogrom"
android:layout_width="match_parent"
android:layout_height="100dp"
android:visibility="gone">
<widget.chart.Scrollhistogrom
android:layout_width="match_parent"
android:layout_height="match_parent"
</widget.chart.Scrollhistogrom>
</LinearLayout>
MainActivity中调用布局,设置数据
public class MainActivity extends BaseActivity

private Histogromview histogromview;
private List<Histogrom> data=new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn= (Button) findViewById(R.id.btn);

histogromview= (Histogromview) findViewById(R.id.histogromview);
//设置总的数据条数
histogromview.setTotaldata(20);
//添加数据
for (int i=0;i<histogromview.getTotaldata();i++){
Histogrom histogrom=new Histogrom("张三",20);
data.add(histogrom);
}
//将数据传给自定义view的data
Dao模式类

属性+属性的set/get方法+带有属性参数的构造器

package dao;

/**
* Created by Administrator on 2015/10/13.
*/
public class Histogrom
private String name;
private int percent;

public Histogrom(String name, int percent) {
this.name = name;
this.percent = percent;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getPercent() {
return percent;
}

public void setPercent(int percent) {
this.percent = percent;
}
}


上一篇: 进程与线程 下一篇: 手机怎么远程登录云服务器?