大佬教程收集整理的这篇文章主要介绍了Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
本文实例讲述了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 last@R_15_7616@; private float movingLeftThisTime = 0.0f; @Override public Boolean onTouchEvent(@NonNull MotionEvent event) { int type = event.getAction(); switch (typE) { case MotionEvent.ACTION_DOWN: last@R_15_7616@ = event.getRawX(); break; case MotionEvent.ACTION_MOVE: float x = event.getRawX(); movingLeftThisTime = last@R_15_7616@ - x; leftMoving += movingLeftThisTime; last@R_15_7616@ = 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绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。