本文实例讲述了AndroID编程实现canvas绘制柱状统计图功能。分享给大家供大家参考,具体如下:
这里实现了一个简单的柱状统计图,如下:
特点:
1.根据数据源自动计算每个条目的高度、宽度、间距,自动计算分度值。
2.当条目数较多时,可左右滑动查看全部内容,图形、文字同步滑动,并且松手后会渐渐的停下来(而不是立刻停下来)。
代码:
(1)核心代码:barChartVIEw.Java
package com.sina.appbarchart;import androID.app.Activity;import androID.content.Context;import androID.graphics.Bitmap;import androID.graphics.BitmapFactory;import androID.graphics.Canvas;import androID.graphics.color;import androID.graphics.Paint;import androID.graphics.Path;import androID.graphics.Rect;import androID.support.annotation.NonNull;import androID.support.v7.app.Actionbar;import androID.support.v7.app.ActionBaractivity;import androID.util.AttributeSet;import androID.vIEw.MotionEvent;import androID.vIEw.VIEw;/** * 自定义组件:条形统计图 * Created by hanj on 14-12-30. */public class barChartVIEw extends VIEw { private int screenW,screenH; private barChartItemBean[] mItems; //max value in mItems. private float maxValue; //max height of the bar private int maxHeight; private int[] mbarcolors = new int[]{color.RED,color.GREEN,color.BLUE,color.YELLOW,color.magenta,color.CYAN}; private Paint barPaint,linePaint,textPaint; private Rect barRect,leftWhiteRect,rightWhiteRect; private Path textPath; private int leftmargin,topmargin,smallmargin; //the wIDth of one bar item private int barItemWIDth; //the spacing between two bar items. private int barSpace; //the wIDth of the line. private int linestrokeWIDth; /** * The x-position of y-index and the y-position of the x-index.. */ private float x_index_startY,y_index_startX; private Bitmap arrowBmp; private Rect x_index_arrowRect,y_index_arrowRect; private static final int BG_color = color.parsecolor("#E5E5E5"); public barChartVIEw(Context context,AttributeSet attrs) { super(context,attrs); init(context); } private voID init(Context context) { screenW = ScreenUtils.getScreenW(context); screenH = ScreenUtils.getScreenH(context); leftmargin = ScreenUtils.dp2px(context,16); topmargin = ScreenUtils.dp2px(context,40); smallmargin = ScreenUtils.dp2px(context,6); barPaint = new Paint(); barPaint.setcolor(mbarcolors[0]); linePaint = new Paint(); linestrokeWIDth = ScreenUtils.dp2px(context,1); linePaint.setstrokeWIDth(linestrokeWIDth); textPaint = new Paint(); textPaint.setAntiAlias(true); barRect = new Rect(0,0); textPath = new Path(); leftWhiteRect = new Rect(0,screenH); rightWhiteRect = new Rect(screenW - leftmargin,screenW,screenH); arrowBmp = BitmapFactory.decodeResource(context.getResources(),R.drawable.arrow_up); } //标记是否已经获取过状态拉的高度 private boolean statusHeightHasGet; @OverrIDe protected voID onDraw(Canvas canvas) { super.onDraw(canvas); if (!statusHeightHasGet) { subStatusbarHeight(); statusHeightHasGet = true; } //draw background canvas.drawcolor(BG_color); //bounds checkleftMoving(); textPaint.setTextSize(ScreenUtils.dp2px(getContext(),16)); for (int i = 0; i < mItems.length; i++) { //draw bar rect barRect.left = (int) y_index_startX + barItemWIDth * i + barSpace * (i + 1) - (int) leftMoving; barRect.top = topmargin * 2 + (int) (maxHeight * (1.0f - mItems[i].itemValue / maxValue)); barRect.right = barRect.left + barItemWIDth; barPaint.setcolor(mbarcolors[i % mbarcolors.length]); canvas.drawRect(barRect,barPaint); //draw type text String typeText = mItems[i].itemType; float textPathStartX = barRect.left + barItemWIDth / 2 - (float) (Math.sin(Math.PI / 6)) * textPaint.measureText("好") / 2; float textPathStartY = barRect.bottom; textPath.reset(); textPath.moveto(textPathStartX,textPathStartY); textPath.lineto(textPathStartX + (float) (1000 * Math.tan(Math.PI / 6)),textPathStartY + 1000); canvas.drawTextOnPath(typeText,textPath,smallmargin * 1.5f,smallmargin * 2,textPaint); //draw value text String valueText = String.valueOf(mItems[i].itemValue); canvas.drawText(valueText,barRect.left - (textPaint.measureText(valueText) - barItemWIDth) / 2,barRect.top - smallmargin,textPaint); } //draw left white space and right white space int c = barPaint.getcolor(); barPaint.setcolor(BG_color); leftWhiteRect.right = (int) y_index_startX; canvas.drawRect(leftWhiteRect,barPaint); canvas.drawRect(rightWhiteRect,barPaint); barPaint.setcolor(c); //draw x-index line. canvas.drawline( y_index_startX - linestrokeWIDth / 2,x_index_startY,screenW - leftmargin,linePaint); //draw y-index line. canvas.drawline( y_index_startX,x_index_startY + linestrokeWIDth / 2,y_index_startX,topmargin / 2,linePaint); canvas.drawBitmap(arrowBmp,null,y_index_arrowRect,null); canvas.save(); canvas.rotate(90,(x_index_arrowRect.left + x_index_arrowRect.right) / 2,(x_index_arrowRect.top + x_index_arrowRect.bottom) / 2); canvas.drawBitmap(arrowBmp,x_index_arrowRect,null); canvas.restore(); //draw division value int maxdivisionValueHeight = (int) (maxHeight * 1.0f / maxValue * maxdivisionValue); textPaint.setTextSize(ScreenUtils.dp2px(getContext(),10)); for (int i = 1; i <= 10; i++) { float startY = barRect.bottom - maxdivisionValueHeight * 0.1f * i; if (startY < topmargin / 2) { break; } canvas.drawline(y_index_startX,startY,y_index_startX + 10,linePaint); String text = String.valueOf(maxdivisionValue * 0.1f * i); canvas.drawText(text,y_index_startX - textPaint.measureText(text) - 5,startY + textPaint.measureText("0") / 2,textPaint); } } private float leftMoving; private float lastPointX; private float movingleftThisTime = 0.0f; @OverrIDe public boolean ontouchEvent(@NonNull MotionEvent event) { int type = event.getAction(); switch (type) { case MotionEvent.ACTION_DOWN: lastPointX = event.getRawX(); break; case MotionEvent.ACTION_MOVE: float x = event.getRawX(); movingleftThisTime = lastPointX - x; leftMoving += movingleftThisTime; lastPointX = x; invalIDate(); break; case MotionEvent.ACTION_UP: //smooth scroll new Thread(new SmoothScrollThread(movingleftThisTime)).start(); break; default: return super.ontouchEvent(event); } return true; } /** * Check the value of leftMoving to ensure that the vIEw is not out of the screen. */ private voID checkleftMoving() { if (leftMoving < 0) { leftMoving = 0; } if (leftMoving > (maxRight - minRight)) { leftMoving = maxRight - minRight; } } public barChartItemBean[] getItems() { return mItems; } public voID setItems(barChartItemBean[] items) { if (items == null) { throw new RuntimeException("barChartVIEw.setItems(): the param items cannot be null."); } if (items.length == 0) { return; } this.mItems = items; //Calculate the max value. maxValue = items[0].itemValue; for (barChartItemBean bean : items) { if (bean.itemValue > maxValue) { maxValue = bean.itemValue; } } //Calculate the max division value. getRange(maxValue,0); //Get the wIDth of each bar. getbarItemWIDth(screenW,items.length); //Refresh the vIEw. invalIDate(); } private int maxRight,minRight; /** * Get the wIDth of each bar which is depended on the screenW and item count. */ private voID getbarItemWIDth(int screenW,int itemCount) { //The min wIDth of the bar is 50dp. int minbarWIDth = ScreenUtils.dp2px(getContext(),40); //The min wIDth of spacing. int minbarSpacing = ScreenUtils.dp2px(getContext(),30); barItemWIDth = (screenW - leftmargin * 2) / (itemCount + 3); barSpace = (screenW - leftmargin * 2 - barItemWIDth * itemCount) / (itemCount + 1); if (barItemWIDth < minbarWIDth || barSpace < minbarSpacing) { barItemWIDth = minbarWIDth; barSpace = minbarSpacing; } maxRight = (int) y_index_startX + linestrokeWIDth + (barSpace + barItemWIDth) * mItems.length; minRight = screenW - leftmargin - barSpace; } /** * Sub the height of status bar and action bar to get the accurate height of screen. */ private voID subStatusbarHeight() { //The height of the status bar int statusHeight = ScreenUtils.getStatusbarHeight((Activity) getContext()); //The height of the actionbar Actionbar ab = ((ActionBaractivity) getContext()).getSupportActionbar(); int abHeight = ab == null ? 0 : ab.getHeight(); screenH -= (statusHeight + abHeight); barRect.top = topmargin * 2; barRect.bottom = screenH - topmargin * 3; maxHeight = barRect.bottom - barRect.top; x_index_startY = barRect.bottom; x_index_arrowRect = new Rect(screenW - leftmargin,(int) (x_index_startY - 10),screenW - leftmargin + 10,(int) (x_index_startY + 10)); } //The max and min division value. private float maxdivisionValue,mindivisionValue; //Get the max and min division value by the max and min value in mItems. private voID getRange(float maxValue,float minValue) { //max int scale = Utility.getScale(maxValue); float unscaledValue = (float) (maxValue / Math.pow(10,scale)); maxdivisionValue = (float) (getRangetop(unscaledValue) * Math.pow(10,scale)); y_index_startX = getdivisionTextMaxWIDth(maxdivisionValue) + 10; y_index_arrowRect = new Rect((int) (y_index_startX - 5),topmargin / 2 - 20,(int) (y_index_startX + 5),topmargin / 2); } private float getRangetop(float value) { //value: [1,10) if (value < 1.2) { return 1.2f; } if (value < 1.5) { return 1.5f; } if (value < 2.0) { return 2.0f; } if (value < 3.0) { return 3.0f; } if (value < 4.0) { return 4.0f; } if (value < 5.0) { return 5.0f; } if (value < 6.0) { return 6.0f; } if (value < 8.0) { return 8.0f; } return 10.0f; } /** * Get the max wIDth of the division value text. */ private float getdivisionTextMaxWIDth(float maxdivisionValue) { Paint textPaint = new Paint(); textPaint.setTextSize(ScreenUtils.dp2px(getContext(),10)); float max = textPaint.measureText(String.valueOf(maxdivisionValue * 0.1f)); for (int i = 2; i <= 10; i++) { float w = textPaint.measureText(String.valueOf(maxdivisionValue * 0.1f * i)); if (w > max) { max = w; } } return max; } /** * Use this thread to create a smooth scroll after ACTION_UP. */ private class SmoothScrollThread implements Runnable { float lastMoving; boolean scrolling = true; private SmoothScrollThread(float lastMoving) { this.lastMoving = lastMoving; scrolling = true; } @OverrIDe public voID run() { while (scrolling) { long start = System.currentTimeMillis(); lastMoving = (int) (0.9f * lastMoving); leftMoving += lastMoving; checkleftMoving(); postInvalIDate(); if (Math.abs(lastMoving) < 5) { scrolling = false; } long end = System.currentTimeMillis(); if (end - start < 20) { try { Thread.sleep(20 - (end - start)); } catch (InterruptedException e) { e.printstacktrace(); } } } } } /** * A model class to keep the bar item info. */ static class barChartItemBean { private String itemType; private float itemValue; public barChartItemBean(String itemType,float itemValue) { this.itemType = itemType; this.itemValue = itemValue; } }}
(2)该自定义组件的使用:
package com.sina.appbarchart;import androID.support.v7.app.ActionBaractivity;import androID.os.Bundle;public class MainActivity extends ActionBaractivity { @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); barChartVIEw barChartVIEw = (barChartVIEw) findVIEwByID(R.ID.bar_chart); barChartVIEw.barChartItemBean[] items = new barChartVIEw.barChartItemBean[]{ new barChartVIEw.barChartItemBean("餐饮",300),new barChartVIEw.barChartItemBean("学习",200),new barChartVIEw.barChartItemBean("旅行",270),new barChartVIEw.barChartItemBean("购物",110),new barChartVIEw.barChartItemBean("人际关系",120),new barChartVIEw.barChartItemBean("娱乐",80),new barChartVIEw.barChartItemBean("投资",new barChartVIEw.barChartItemBean("教育",280) }; barChartVIEw.setItems(items); }}
完整实例代码点击此处本站下载。
更多关于AndroID相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家AndroID程序设计有所帮助。
总结以上是内存溢出为你收集整理的Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】全部内容,希望文章能够帮你解决Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)