Android自定义View实现简单的折线图、柱状图
来源:互联网 发布:北京市公共图书馆网络 编辑:程序博客网 时间:2024/05/19 04:28
首先说第一个柱状图,实现很简单。一个自定义View,重现里面的OnDraw方法。然后利用paint,canvas绘制带填充的长方形即可。每个长方形的X轴平方View的x轴即可,长方形的高度通过简单的计算即可得到。下面上柱状图代码
package com.hrules.charter.demo.widget;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import android.view.animation.BounceInterpolator;import com.hrules.charter.demo.R;import java.util.Random;/** * 柱状图 * Created by 黄海 on 2017/4/17. */public class Histogram extends View implements View.OnClickListener { int width, height; Paint paintBar, paintText; float[] values = new float[15]; float[] valuesTemp = new float[15]; int colorBackground = R.color.default_barBackgroundColor;//柱状背景 int[] colorBar = new int[]{R.color.lightBlue500, R.color.lightBlue400, R.color.lightBlue300};//柱状颜色 float maxY; int barMarginLeft = 7; int tagHeight = 45;//x和Y轴的数字 boolean anim; boolean showLineXNums = true, showLineYNums = true;//展示X、Y轴的数字 int lineYNums = 5;//Y轴展示的格数 ValueAnimator valueAnimator; public Histogram(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public Histogram(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); paintText = paintBar = new Paint(); paintBar.setAntiAlias(true); paintText.setAntiAlias(true); paintText.setTextSize(25); paintText.setColor(getResources().getColor(colorBar[0])); initValuesAndMaxY(); setOnClickListener(this); } private void initValuesAndMaxY() { Random random = new Random(); for (int i = 0; i < values.length; i++) { values[i] = random.nextFloat() * 100; } for (float i : values) { maxY = maxY < i ? i : maxY; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); width = getMeasuredWidth(); height = getMeasuredHeight(); int barWidth = (width - tagHeight) / values.length; int j = 0; if (!anim) valuesTemp = values.clone(); for (int i = 0; i < valuesTemp.length; i++) { RectF rect = new RectF(); rect.left = tagHeight + i * barWidth + barMarginLeft; rect.top = (height - tagHeight) * (1 - 1.0f * valuesTemp[i] / maxY); rect.right = rect.left + barWidth - barMarginLeft; rect.bottom = height - tagHeight; //draw the barBackground paintBar.setColor(getResources().getColor(colorBackground)); canvas.drawRect(rect.left, 0, rect.right, rect.bottom, paintBar); //paint the bar j = j > colorBar.length - 1 ? 0 : j; paintBar.setColor(getResources().getColor(colorBar[j++])); canvas.drawRect(rect, paintBar); if (showLineXNums) { //draw x-coordinate num float textWidth = paintText.measureText(String.valueOf(i)); float textLeft = rect.left + rect.width() / 2 - textWidth / 2; canvas.drawText(String.valueOf(i), textLeft, height, paintText); } } //draw y-coordinate num if (showLineYNums) { int avgHeight = (height - tagHeight) / lineYNums; for (int i = 0; i < lineYNums; i++) { float x = 0; float y = (height - tagHeight) - avgHeight * (i + 1); int valueY = (int) (maxY * (i + 1) / lineYNums); // canvas写字是从x、y轴往右上写的 canvas.drawText(String.valueOf(valueY), x, y + 30, paintText); } } } @Override public void onClick(View v) { anim = true; valueAnimator = ValueAnimator.ofFloat(0f, 1f); valuesTemp = values.clone(); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { for (int i = 0; i < valuesTemp.length; i++) { //update valuesTemps float animatedValue = (float) animation.getAnimatedValue(); valuesTemp[i] = maxY * animatedValue < values[i] ? maxY * animatedValue : values[i]; } invalidate(); } });// valueAnimator.setInterpolator(new LinearInterpolator()); //落地回调效果 valueAnimator.setInterpolator(new BounceInterpolator()); valueAnimator.setDuration(2000l); valueAnimator.start(); }}
实现比较简单,注释都有。最后说下onClick方法的作用:valuesTemp是原有柱状数据的副本,view点击后让valuesTemp的每个数据从maxY的最小百分比开始不断的增长,从而实现一个动态改变的动画效果,如下:
折线图运用的paint,canvas与path完成,计算每个点的位置和柱状图类似,折线图形成一个填充效果也简单就是path close一下,然后绘制close后的path就是。下面看源码
package com.hrules.charter.demo.widget;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PointF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import com.hrules.charter.demo.R;import java.util.ArrayList;import java.util.List;import java.util.Random;/** * 折线图 * Created by 黄海 on 2017/4/18. */public class LineChart extends View { Path path = new Path(); float[] values = new float[15]; float maxY; Paint paintXy, paintLine; int width, height;//view 宽高 public LineChart(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public LineChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initValuesAndMaxY(); paintXy = new Paint(Paint.ANTI_ALIAS_FLAG); paintXy.setStyle(Paint.Style.STROKE); paintXy.setStrokeWidth(6); paintXy.setColor(getResources().getColor(R.color.lightBlue500)); paintLine = new Paint(Paint.ANTI_ALIAS_FLAG); paintLine.setStyle(Paint.Style.FILL); paintLine.setColor(getResources().getColor(R.color.colorPrimary)); } private void initValuesAndMaxY() { Random random = new Random(); for (int i = 0; i < values.length; i++) { values[i] = random.nextFloat() * 100; maxY = maxY < values[i] ? values[i] : maxY; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); width = getMeasuredWidth(); height = getMeasuredHeight(); //每格宽度 int widthAvg = width / values.length; //画x轴y轴 path.moveTo(0, 0); path.lineTo(0, height); path.lineTo(width, height); canvas.drawPath(path, paintXy); List<PointF> list = new ArrayList<>(); for (int i = 0; i < values.length; i++) {//收集坐标信息 PointF point = new PointF(widthAvg / 2 + i * widthAvg, 0); point.set(widthAvg / 2 + i * widthAvg, (1 - values[i] / maxY) * height); list.add(point); } //画线 path.reset();//清除 画x轴y轴而产生的闭合影响 path.moveTo(list.get(0).x, list.get(0).y); for (int i = 1; i < values.length; i++) { path.lineTo(list.get(i).x, list.get(i).y);// path.cubicTo(ps.x, ps.y,(ps.x+pe.x)/2,(ps.y+pe.y)/2, pe.x, pe.y);//画三次贝塞尔曲线 } canvas.drawPath(path, paintXy); //折线图闭合 path.lineTo(list.get(values.length - 1).x, height); path.lineTo(list.get(0).x, height); path.close(); canvas.drawPath(path, paintLine); //画点 for (int i = 0; i < values.length; i++) { canvas.drawCircle(list.get(i).x, list.get(i).y, 9, paintLine); } }}
0 0
- Android自定义View实现简单的折线图、柱状图
- 自定义View-柱状图和折线图的合体
- 自定义View-轻量级柱状图、饼图、折线图
- Android 自定义View,实现折线图
- Android 自定义View,实现折线图
- 自定义View:画布实现自定义View(折线图的实现)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- Android自定义统计图(柱状图,折线图,饼状图)
- 自定义View简单折线图
- 自定义折线图/柱状图
- Android 自定义View -- 简约的折线图
- Android 自定义View 折线图
- 安卓自定义View实现简单折线图
- android实现折线图和柱状图
- Android 自定义view实现动态柱状图。
- 语言基础-函数
- 算法分析
- 人工智能这么火,.ai会不会成为下一个.com?
- 用HSSFWorkbook来对excel进行读操作
- 【BZOJ】1029 [JSOI2007]建筑抢修 贪心+堆
- Android自定义View实现简单的折线图、柱状图
- iOS下单签名串之字典通过key值进行降序排列
- mysql 修改root密码
- ubuntu安装和查看已安装的几种方法
- MFC下写简易计算器
- 学习留笔文件
- C++ Primer Chapter 6
- C++ 列表初始化 initializer_list 初始化列表 和 POD
- Button--左文又图 上下图文 属性