Android自定义统计图(柱状图,折线图,饼状图)

Android实现统计图——条形图和折线图 通过这样的方式,你可以绘制两条不同颜色的折线,并且不会填充它们围起来的空间。你可以根据需要调整数据点和其他属性,以适应你的具体需求。这样,当用户点击某个月份的柱条时,会在柱条上方显示所需的提示信息。对象,一个用于绘制文本,另一个用于绘制线条,分别设置了它们的颜色、文本大小、对齐方式、样式和线宽。当鼠标悬停在某个月份的折线上时,会在折线上方显示相应的提示信息。为了实现绘制两条不同颜色的折线,并且确保它们围起来的空间不被填充,在。这意味着只绘制线条的轮廓,而不是填充线条内部。绘制的所有线条都会是黑色的。 阅读详情

最近由于项目需要,研究了一些统计图的做法,开始时,看了很多博文,大部分都是引用第三方的库,虽然简单,

易上手,但是功能太死板,有很多要求都是不能满足的,所以经过研究,自己使用View中的canvas重新绘图制作

统计图。首先上几张的效果图吧。





点击这里下载(0分下载)


一、demo的结构

一个activity中嵌套了三个fragment(v4),是用viewpager对页面进行滑动,下面是整个项目的结构:


二、核心代码

首先是MainActivity,这个demo中只使用到一个activity,现在一个activity中镶嵌多个fragment很火,

很多Android应用都在使用这个布局,例如微信,QQ等。这样做节省了空间上的浪费。

package com.example.statisticalchart;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends FragmentActivity {

	private ViewPager viewPager;
	private List<Fragment> fragments;
	private FragmentPagerAdapter adapter;
	// 设置是否显示动画,为了防止在创建时就开启动画,用以下三个参数做了判断,只有当看到视图后才会显示动画
	public static int flag1 = 2;
	public static int flag2 = 1;
	public static int flag3 = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
		viewPager = (ViewPager) findViewById(R.id.record_viewpager);
		fragments = new ArrayList<Fragment>();
		RecordPager1 recordPager1 = new RecordPager1();
		RecordPager2 recordPager2 = new RecordPager2();
		RecordPager3 recordPager3 = new RecordPager3();
		fragments.add(recordPager1);
		fragments.add(recordPager2);
		fragments.add(recordPager3);

		adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
			@Override
			public Fragment getItem(int position) {
				return fragments.get(position);
			}

			@Override
			public int getCount() {
				return fragments.size();
			}
		};
		viewPager.setAdapter(adapter);

		viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
			@Override
			public void onPageScrolled(int position, float positionOffset,
					int positionOffsetPixels) {

			}

			@Override
			public void onPageSelected(int position) {
				if (position == 0 && flag1 == 1) {
					flag1 = 2;
					fragments.get(0).onResume();
					flag1 = 3;
				}
				if (position == 1 && flag2 == 1) {
					flag2 = 2;
					fragments.get(1).onResume();
					flag2 = 3;

				}
				if (position == 2 && flag3 == 1) {
					flag3 = 2;
					fragments.get(2).onResume();
					flag3 = 3;
				}
			}

			@Override
			public void onPageScrollStateChanged(int state) {

			}
		});
	}

}

接下来是这个项目中最主要的三个类:HistogramView、LineChartView、PinChart。这三个类继承View类,重新构图,分别画成了柱状图,折线图,饼状图,然后给出三个类的代码:

package com.example.statisticalchart;

import android.annotation.SuppressLint;
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.Paint.Align;
import android.graphics.Rect;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class HistogramView extends View {

	private Paint xLinePaint;// 坐标轴 轴线 画笔:
	private Paint hLinePaint;// 坐标轴水平内部 虚线画笔
	private Paint titlePaint;// 绘制文本的画笔
	private Paint paint;// 矩形画笔 柱状图的样式信息
	private int[] progress = { 2000, 5000, 6000, 8000, 500, 6000, 9000 };// 7
																			// 条,显示各个柱状的数据
	private int[] aniProgress;// 实现动画的值
	private final int TRUE = 1;// 在柱状图上显示数字
	private int[] text;// 设置点击事件,显示哪一条柱状的信息
	private Bitmap bitmap;
	// 坐标轴左侧的数标
	private String[] ySteps;
	// 坐标轴底部的星期数
	private String[] xWeeks;
	private int flag;// 是否使用动画

	private HistogramAnimation ani;

	public HistogramView(Context context) {
		super(context);
		init();
	}

	public HistogramView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init() {

		ySteps = new String[] { "10k", "7.5k", "5k", "2.5k", "0" };
		xWeeks = new String[] { "周一", "周二", "周三", "周四", "周五", "周六", "周日" };
		text = new int[] { 0, 0, 0, 0, 0, 0, 0 };
		aniProgress = new int[] { 0, 0, 0, 0, 0, 0, 0 };
		ani = new HistogramAnimation();
		ani.setDuration(2000);

		xLinePaint = new Paint();
		hLinePaint = new Paint();
		titlePaint = new Paint();
		paint = new Paint();

		// 给画笔设置颜色
		xLinePaint.setColor(Color.DKGRAY);
		hLinePaint.setColor(Color.LTGRAY);
		titlePaint.setColor(Color.BLACK);

		// 加载画图
		bitmap = BitmapFactory
				.decodeResource(getResources(), R.drawable.column);
	}

	public void start(int flag) {
		this.flag = flag;
		this.startAnimation(ani);
	}

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

		int width = getWidth();
		int height = getHeight() - dp2px(50);
		// 绘制底部的线条
		canvas.drawLine(dp2px(30), height + dp2px(3), width - dp2px(30), height
				+ dp2px(3), xLinePaint);

		int leftHeight = height - dp2px(5);// 左侧外周的 需要划分的高度:

		int hPerHeight = leftHeight / 4;// 分成四部分

		hLinePaint.setTextAlign(Align.CENTER);
		// 设置四条虚线
		for (int i = 0; i < 4; i++) {
			canvas.drawLine(dp2px(30), dp2px(10) + i * hPerHeight, width
					- dp2px(30), dp2px(10) + i * hPerHeight, hLinePaint);
		}

		// 绘制 Y 周坐标
		titlePaint.setTextAlign(Align.RIGHT);
		titlePaint.setTextSize(sp2px(12));
		titlePaint.setAntiAlias(true);
		titlePaint.setStyle(Paint.Style.FILL);
		// 设置左部的数字
		for (int i = 0; i < ySteps.length; i++) {
			canvas.drawText(ySteps[i], dp2px(25), dp2px(13) + i * hPerHeight,
					titlePaint);
		}

		// 绘制 X 周 做坐标
		int xAxisLength = width - dp2px(30);
		int columCount = xWeeks.length + 1;
		int step = xAxisLength / columCount;

		// 设置底部的数字
		for (int i = 0; i < columCount - 1; i++) {
			// text, baseX, baseY, textPaint
			canvas.drawText(xWeeks[i], dp2px(25) + step * (i + 1), height
					+ dp2px(20), titlePaint);
		}

		// 绘制矩形
		if (aniProgress != null && aniProgress.length > 0) {
			for (int i = 0; i < aniProgress.length; i++) {// 循环遍历将7条柱状图形画出来
				int value = aniProgress[i];
				paint.setAntiAlias(true);// 抗锯齿效果
				paint.setStyle(Paint.Style.FILL);
				paint.setTextSize(sp2px(15));// 字体大小
				paint.setColor(Color.parseColor("#6DCAEC"));// 字体颜色
				Rect rect = new Rect();// 柱状图的形状

				rect.left = step * (i + 1);
				rect.right = dp2px(30) + step * (i + 1);
				int rh = (int) (leftHeight - leftHeight * (value / 10000.0));
				rect.top = rh + dp2px(10);
				rect.bottom = height;

				canvas.drawBitmap(bitmap, null, rect, paint);
				// 是否显示柱状图上方的数字
				if (this.text[i] == TRUE) {
					canvas.drawText(value + "", dp2px(15) + step * (i + 1)
							- dp2px(15), rh + dp2px(5), paint);
				}

			}
		}

	}

	private int dp2px(int value) {
		float v = getContext().getResources().getDisplayMetrics().density;
		return (int) (v * value + 0.5f);
	}

	private int sp2px(int value) {
		float v = getContext().getResources().getDisplayMetrics().scaledDensity;
		return (int) (v * value + 0.5f);
	}

	/**
	 * 设置点击事件,是否显示数字
	 */
	public boolean onTouchEvent(MotionEvent event) {
		int step = (getWidth() - dp2px(30)) / 8;
		int x = (int) event.getX();
		for (int i = 0; i < 7; i++) {
			if (x > (dp2px(15) + step * (i + 1) - dp2px(15))
					&& x < (dp2px(15) + step * (i + 1) + dp2px(15))) {
				text[i] = 1;
				for (int j = 0; j < 7; j++) {
					if (i != j) {
						text[j] = 0;
					}
				}
				if (Looper.getMainLooper() == Looper.myLooper()) {
					invalidate();
				} else {
					postInvalidate();
				}
			}
		}
		return super.onTouchEvent(event);
	}

	/**
	 * 集成animation的一个动画类
	 * 
	 * @author 李垭超
	 */
	private class HistogramAnimation extends Animation {
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f && flag == 2) {
				for (int i = 0; i < aniProgress.length; i++) {
					aniProgress[i] = (int) (progress[i] * interpolatedTime);
				}
			} else {
				for (int i = 0; i < aniProgress.length; i++) {
					aniProgress[i] = progress[i];
				}
			}
			invalidate();
		}
	}

}


package com.example.statisticalchart;

import android.annotation.SuppressLint;
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.Paint.Align;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class LineChartView extends View {

	private Paint rectPaint;// 设置左侧为白色,显示数表
	private Paint hLinePaint;// 坐标轴水平内部 虚线画笔
	private Paint titlePaint;// 绘制文本的画笔
	private Paint linePaint;
	private Paint paint;// 矩形画笔 柱状图的样式信息
	private int[] text;// 折线的转折点
	int x, y, preX, preY;
	// 坐标轴左侧的数标
	private Bitmap mBitmap;
	// 坐标轴底部的星期数
	private String[] str = { "62", "72", "82", "92", "102", "112", "122",
			"132", "142" };

	private HistogramAnimation ani;
	private int flag;

	public LineChartView(Context context) {
		super(context);
		init(context, null);
	}

	public LineChartView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init(context, attrs);
	}

	private void init(Context context, AttributeSet attrs) {

		text = new int[] { 6, 5, 5, 4, 5, 3, 2, 3, 1, 1 };

		ani = new HistogramAnimation();
		ani.setDuration(4000);

		rectPaint = new Paint();
		titlePaint = new Paint();

	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		linePaint = new Paint();

		//
		titlePaint.setAntiAlias(true);
		Rect bundle1 = new Rect();

		Rect bundle2 = new Rect();
		hLinePaint = new Paint();

		int perWidth = getWidth() / 10;// 将宽度分为10部分
		int hPerHeight = getHeight() / 10;// 将高度分为10部分
		rectPaint.setColor(Color.WHITE);

		canvas.drawRect(0, 0, dp2px(30), getHeight(), rectPaint);// 画一块白色区域

		Path path = new Path();// 折线图的路径
		mBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
				Bitmap.Config.ARGB_8888);
		Canvas mCanvas = new Canvas(mBitmap);

		for (int i = 0; i < 10; i++) {// 画x线,并在左侧显示相应的数值
			hLinePaint.setTextAlign(Align.CENTER);
			hLinePaint.setColor(Color.WHITE);
			y = i * hPerHeight;
			if (i == 2) {
				hLinePaint.setStrokeWidth(4);
				for (int j = 0; j < 10; j++) {
					canvas.drawLine(dp2px(30) + j * perWidth, y, dp2px(28)
							+ (j + 1) * perWidth, y, hLinePaint);
				}
				titlePaint.setTextSize(sp2px(20));
				titlePaint.getTextBounds(str[i - 1], 0, str[i - 1].length(),
						bundle1);
				canvas.drawText(str[i - 1], dp2px(25) - bundle1.width(), i
						* hPerHeight + (bundle1.height() / 2), titlePaint);
			} else {
				hLinePaint.setStrokeWidth(1);
				canvas.drawLine(dp2px(30), y, getWidth(), y, hLinePaint);
				if (i != 0) {
					titlePaint.setTextSize(sp2px(15));
					titlePaint.getTextBounds(str[i - 1], 0,
							str[i - 1].length(), bundle2);
					canvas.drawText(str[i - 1], dp2px(25) - bundle2.width(), i
							* hPerHeight + (bundle2.height() / 2), titlePaint);
				}
			}

			x = i * perWidth + dp2px(30);
			if (i == 0) {
				path.moveTo(x, text[i] * hPerHeight);
			} else {
				path.lineTo(x, text[i] * hPerHeight);
			}
			linePaint.setColor(Color.parseColor("#bb2222"));
			linePaint.setAntiAlias(true);

			paint = new Paint();
			paint.setColor(Color.RED);
			paint.setStyle(Paint.Style.STROKE);
			paint.setStrokeWidth(dp2px(1));
			if (i != 0) {
				mCanvas.drawCircle(x, text[i] * hPerHeight, dp2px(3), linePaint);
			}
			paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
			mCanvas.drawPath(path, paint);
		}

		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
		paint.setStyle(Paint.Style.FILL);

		mCanvas.drawRect(preX + dp2px(30), 0, getWidth(), getHeight(), paint);
		canvas.drawBitmap(mBitmap, 0, 0, null);
		// Log.i("tag", "onDraw()1111");
	}

	private int dp2px(int value) {
		float v = getContext().getResources().getDisplayMetrics().density;
		return (int) (v * value + 0.5f);
	}

	private int sp2px(int value) {
		float v = getContext().getResources().getDisplayMetrics().scaledDensity;
		return (int) (v * value + 0.5f);
	}

	public void start(int flag) {
		startAnimation(ani);
		this.flag = flag;
	}

	/**
	 * 集成animation的一个动画类
	 * 
	 * @author 
	 */
	private class HistogramAnimation extends Animation {
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f && flag == 2) {
				preX = (int) ((getWidth() - dp2px(30)) * interpolatedTime);
			} else {

				preX = getWidth();

			}
			invalidate();
		}
	}

}

package com.example.statisticalchart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class PinChart extends View {

	static Canvas c;
	private Paint[] mPaints;
	private RectF mBigOval;
	float[] mSweep = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	private int preWidth;
	private mAnimation ani;
	private int flag;
	private int centerX;
	private int centerY;
	int valueX;
	int valueY;

	public static float[] humidity = { 110, 60, 50, 50, 40, 30, 10, 10 };
	private String str[] = { "数据24%", "数据19%", "数据21%", "其他18%", "数据3%",
			"数据3%", "数据4%", "数据6%" };

	private final String color[] = { "#2cbae7", "#ffa500", "#ff5b3b",
			"#9fa0a4", "#6a71e5", "#f83f5d", "#64a300", "#64ef85" };

	public PinChart(Context context) {
		super(context);
		initView();
	}

	public PinChart(Context context, AttributeSet atr) {
		super(context, atr);
		initView();
	}

	private void initView() {
		ani = new mAnimation();
		ani.setDuration(2000);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.TRANSPARENT);// 设置背景颜色(透明)
		mPaints = new Paint[humidity.length];

		for (int i = 0; i < humidity.length; i++) {
			mPaints[i] = new Paint();
			mPaints[i].setAntiAlias(true);
			mPaints[i].setStyle(Paint.Style.FILL);
			mPaints[i].setColor(Color.parseColor(color[i]));
		}
		int cicleWidth = getWidth() - dp2px(60);
		centerX = getWidth() / 2;
		centerY = dp2px(10) + cicleWidth / 2;
		preWidth = (getWidth() - dp2px(40)) / 4;
		int half = getWidth() / 2;

		mBigOval = new RectF();// 饼图的四周边界
		mBigOval.top = dp2px(10);
		mBigOval.left = half - cicleWidth / 2;
		mBigOval.bottom = dp2px(10) + cicleWidth;
		mBigOval.right = half + cicleWidth / 2;

		float start = -180;
		Rect bounds = new Rect();
		for (int i = 0; i < humidity.length; i++) {
			canvas.drawArc(mBigOval, start, mSweep[i], true, mPaints[i]);
			if (humidity[i] > 45) {
				mPaints[i].setXfermode(new PorterDuffXfermode(
						PorterDuff.Mode.SRC_OVER));
				mPaints[i].setAntiAlias(true);
				mPaints[i].setColor(Color.WHITE);
				mPaints[i].getTextBounds(str[i], 0, str[i].length(), bounds);
				mPaints[i].setTextSize(sp2px(15));
				measureText(start + 180, humidity[i], cicleWidth / 3, i);
				canvas.drawText(str[i], valueX - mPaints[i].measureText(str[i])
						/ 2, valueY + bounds.height() / 2, mPaints[i]);
			}
			start += humidity[i];
			int j = 1;
			int k;
			if (i < 4) {
				j = 0;
				k = i;
			} else {
				j = 1;
				k = i - 4;
			}
			mPaints[i] = new Paint();
			mPaints[i].setAntiAlias(true);
			mPaints[i].setStyle(Paint.Style.FILL);
			mPaints[i].setColor(Color.parseColor(color[i]));
			canvas.drawRect(new RectF(dp2px(20) + preWidth * k, cicleWidth
					+ dp2px(j * 30 + 20), dp2px(20) + preWidth * (k + 1),
					cicleWidth + dp2px(50 + j * 30)), mPaints[i]);
			mPaints[i].setXfermode(new PorterDuffXfermode(
					PorterDuff.Mode.SRC_OVER));
			mPaints[i].setAntiAlias(true);
			mPaints[i].setColor(Color.WHITE);
			mPaints[i].getTextBounds(str[i], 0, str[i].length(), bounds);
			mPaints[i].setTextSize(sp2px(15));
			canvas.drawText(str[i], dp2px(20) + preWidth * k + preWidth / 2
					- mPaints[i].measureText(str[i]) / 2, cicleWidth
					+ dp2px(j * 30 + 20)
					+ (dp2px(30) / 2 + bounds.height() / 2), mPaints[i]);
		}
	}

	/**
	 * 显示相应区域字开始的x,y坐标
	 * 
	 * @param start
	 * @param angle
	 * @param radius
	 * @param i
	 */
	private void measureText(float start, float angle, int radius, int i) {
		float temp = start + (angle / 2);

		if (temp < 90) {
			valueX = (int) (centerX - Math.abs(radius
					* Math.sin((temp / 180) * Math.PI)));
			valueY = (int) (centerY - Math.abs(radius
					* Math.cos((temp / 180) * Math.PI)));
		} else if (temp > 90 && temp < 180) {
			temp = 180 - temp;
			valueX = centerX
					+ (int) Math
							.abs((radius * Math.cos((temp / 180) * Math.PI)));
			valueY = centerY
					- (int) Math
							.abs((radius * Math.sin((temp / 180) * Math.PI)));
		} else if (temp > 180 && temp < 270) {
			temp = temp - 180;
			valueX = centerX
					+ (int) Math
							.abs((radius * Math.cos((temp / 180) * Math.PI)));
			valueY = centerY
					+ (int) Math
							.abs((radius * Math.sin((temp / 180) * Math.PI)));
		} else {
			temp = 360 - temp;
			valueX = centerX
					- (int) Math
							.abs((radius * Math.cos((temp / 180) * Math.PI)));
			valueY = centerY
					+ (int) Math
							.abs((radius * Math.sin((temp / 180) * Math.PI)));
		}

	}

	private int sp2px(int value) {
		float v = getResources().getDisplayMetrics().scaledDensity;
		return (int) (value * v + 0.5f);
	}

	private int dp2px(int value) {
		float v = getResources().getDisplayMetrics().density;
		return (int) (value * v + 0.5f);
	}

	public void start(int flag) {
		startAnimation(ani);
		this.flag = flag;
	}

	class mAnimation extends Animation {
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			super.applyTransformation(interpolatedTime, t);
			if (interpolatedTime < 1.0f && flag == 2) {
				for (int i = 0; i < humidity.length; i++) {
					mSweep[i] = humidity[i] * interpolatedTime;
				}
			} else if (flag == 1) {
				for (int i = 0; i < humidity.length; i++) {
					mSweep[i] = 0;
				}
			} else {
				for (int i = 0; i < humidity.length; i++) {
					mSweep[i] = humidity[i];
				}
			}
			invalidate();
		}
	}

}

以上都是核心代码,并不是全部的代码,起他部分的代码就不贴出来了,感兴趣的朋友可以下载来研究研究。


Android 一步步实现曲线图、折线图、柱状图、雷达图,动态心跳图 本文介绍基于安卓开源图表MPandroidChart实现后台自动绘制二维曲线MPandroidChart效果图,其他开源图表项目,支持高度定制化的图表,例如柱状图的颜色,线条、高低、宽窄、背景颜色、X轴、Y轴的自定义开发,还包括实现点击任意位置显示标签,标签内容可定制数据单位 阅读详情

相关推荐

按周(星期)统计后自动生成滚动式趋势图

@[TOC](这里## 标题写自定义目录标题)## 标题 python日期换算成周数 data_yjc[‘批量星期’]=data_yjc.apply(lambda x: x[‘数据生成时间’][0:4]+’-’+x[‘数据生成时间’][4:6]+’-’+x[‘数据生成时间’][6:8], axis=1)#数据日期转换格式成"%Y-%m-%d" data_yjc[‘批量星期1’] = data_yjc[‘批量星期’].apply(lambda x: (datetime.datetime.strptime(x

如是我闻的博客 4312

Android 圆环统计图(带外延折线可点击)

自定义View RingView.class。辅助工具类GeomTool.class。如有更好的方法,欢迎在评论区讨论。activity中使用。需求先看UI效果图吧。

qq_32136827的博客 1259

Android柱状图、饼状图、折线图

1、效果图 2、代码 1)compile ‘com.github.PhilJay:MPAndroidChart:v3.0.1’ 2)柱状图 com.github.mikephil.charting.charts.BarChart android:id="@+id/chart1" android:layout_width="300dp"

再简单的事,也要用心做成! 888

Android柱状图

先来看效果 MPAndroidChart在github上地址:https://github.com/PhilJay/MPAndroidChart 1. 依赖: Project 的build.gradle文件中添加 Project 的build.gradle文件中添加 allprojects { repositories { maven { url '...

guodashen007的博客 4200

E4A MPChart折线图 曲线图

entries 数量自动生成的 legend 取决于DataSet 的标签 不同颜色的数量(在所有 DataSet 的对象)。MPAndroidChart是在Android平台上开源的第三方统计图表库,可以绘制样式复杂、丰富的各种统计图表,如一般常见的折线图、饼状图、柱状图、散点图、金融股票中使用的的“蜡烛”图、“泡泡”统计图、雷达状统计饼状图等等。现在,先做一个基础的AndroidMPChart折线图,折线图在平时的统计图表中应用最多,AndroidMPChart提供了丰富的功能给予支持。

嵌入式单片机实验室 2241

别再折腾虚拟机了!手把手教你用WSL2在Windows 11上安装Kali Linux(含汉化与图形界面)

本文详细介绍了如何在Windows 11上通过WSL2安装和配置Kali Linux,包括汉化与图形界面设置。通过WSL2,用户可以享受接近原生性能的Linux体验,同时保持与Windows系统的无缝集成,特别适合网络安全爱好者和开发者。文章还提供了常见问题解决和性能优化建议,帮助用户高效使用Kali工具集。

weixin_42525369的博客 322

(转)Android自定义统计图(柱状图,折线图,饼状图)

最近由于项目需要,研究了一些统计图的做法,开始时,看了很多博文,大部分都是引用第三方的库,虽然简单, 易上手,但是功能太死板,有很多要求都是不能满足的,所以经过研究,自己使用View中的canvas重新绘图制作 统计图。首先上几张的效果图吧。 点击这里下载(0分下载) 一、demo的结构 一个activity

yuelinqiu的博客 1535

局域网ip冲突检测工具_python 小工具实现 windows笔记本与 ipad数据互传

宅在家没事的时候就开始琢磨ipad的进阶使用,由于没有mac无法隔空投送,ipad与windows的数据交互表现极差,所以设计了这个ftp小工具。当然,这个工具不仅仅能用于windows与ipad,还可以用于局域网任意两台设备之间程序源码与下载见文章末尾使用说明windows端:biubiubiu.exeipad端: appsotre下载 FE文件管理器windows端操作在c盘下创建ftp目录...

weixin_39866265的博客 4435

StatisticsView

各种常用的统计图,折线图,饼状图,渐变色处理

a412845064的博客 730

Xilinx XDMA IP核配置实战:AXI Memory Mapped vs Stream选型指南(附PCIe调试技巧)

本文深入解析Xilinx XDMA IP核配置中AXI Memory Mapped与AXI Stream两种DMA接口的核心区别与选型策略。针对PCIe高速数据传输场景,详细对比了二者在数据特性、延迟、硬件资源及软件复杂度上的差异,为FPGA工程师在数据采集、实时处理等项目中做出高效设计决策提供实战指南,并附有关键的PCIe调试技巧。

qsc901234的博客 585

CTP-API开发系列之三:柜台系统简介

综合交易平台(Comprehensive Transaction Platform,CTP)是专门为期货公司开发的一套期货经纪业务管理系统,由交易、风险控制和结算三大系统组成。接下来分享的内容,对于期货公司的负责交易、运维同事会比较熟悉,针对CTP-API接口对接的朋友可以了解一下,在接口之上的系统是怎样的。

码上助君的专栏 6195

MPAndroidChart 绘制 饼状图、柱状图和折线图简单汇总

Android 绘制图表方式

qq_19688207的博客 1088

ESD放电模式以及电源箝位 (power clamp )电路

由于ESD电压具有很快的上升速度(其ESD脉冲上升时间约在10ns左右),Vrc端的电压因为RC延迟效应无法跟得上VDD端的ESD电压上升速度,Vrc端的为低电位导致反相器工由于ESD电压具有很快的上升速度(其ESD脉冲上升时间约在10ns左右),Vrc端的电压因为RC延迟效应无法跟得上VDD端的ESD电压上升速度,Vrc端的为低电位导致反相器工作将输出端Vout电压上拉到高电位。从而Vg端的高电位触发导通了NMOS元件(Mesd)的晶体管,因而ESD电流便经由Mesd而泄放掉。由于晶体管Mesd的栅极导通

DOG_BITE_DOG的博客 2万+

java饼状图图标_MPAndroidChart开源图表库的使用介绍之饼状图、折线图和柱状图

MPAndroidChart开源图表库之饼状图为大家介绍一款图标开源库MPAndroidChart,它不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,用起来非常灵活。MPAndroidChart同样拥有常用的图表类型:线型图、饼图、柱状图和散点图。mpandroidchartlibrary.jar包下载地址:下面主要实现以下饼状图:1.从上面的地址中下载最新mpa...

weixin_36185970的博客 550

2xmax96717+max96724+agx orin驱动代码

说明:这里主要解决max96717的设备地址和sensor地址映射,vc0->vc1多颗max96717+max96724使用配置思路如下: 1、改变max96717的pipez stream id,然后max96724的pipe绑定使用相应的stream id 2、max96717默认是vc0,把vc0改写成vc1\vc2\vc3,然后max96724再重新映射vc输出

mantouyouyou的博客 113

大模型LoRA微调调参的实战技巧(持续更新)

本文主要介绍了大模型LoRA微调调参的实战技巧,希望对学习大语言模型的同学们有所帮助。 文章目录 1. 前言 2. 实战技巧

herosunly的博客 20万+

Android集成统计图 饼状图 折线图 和 柱状图

先上效果图:使用到第三方的Jar包:下载链接:下载地址下载好之后 添加到buildPath下面是布局文件中的代码:只需要使用一个空白的布局文件去接收存放这个图形就行 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/t

情怀中的释然~ 1万+

百度ECharts Android在线展示统计图表(折线,柱状,饼状图)

做金融类型的应用经常会用到数据的统计报表 诸如折线图 , K线图, 饼状图,柱状图 既能形象的表述数据的分布 , 同时又增加了数据的可读性 实现思路: 百度Echarts支持安卓移动端的运用 , WebView加载html, 嵌套JavaScript代码 , 即可动态实现在线图表的展示功能.. 下面展示下今天要实现的效果 进入Echarts官网下载页...

吃狗屎糖,走狗屎运... 1万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

MPAndroidChart统计图开发总结

前段时间公司要求要给项目里面用统计图来统计数据的直观信息。之后在GitHub上找到了 MPAndroidChart这个库, 今天不对其原理进行解剖。指记录其用法以及常用的属性设置。围绕柱状图、折线图、和饼状图来给大家解析。。。 一、引言MPAndroidChart 是 Android 一个强大且容易使用的图表库 支持线状图、柱状图、散点图、烛状图、气泡图、饼状图和蜘蛛网状图 支持缩放、拖动(平移)

Mr.常的博客 1721

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android开发笔记(一百零二)统计图表

AChartEngine AChartEngine是Android平台上的图表绘制引擎,提供了包括折线图、柱状图、饼状图等图表显示。它的官网地址是http://achartengine.org/,源码下载页面是http://code.google.com/p/achartengine/,当然谷歌失火,殃及AChartEngine,大陆访问不了这个下载页面,若要下载最新版的jar包可前往下面这个地

aqi00的博客 2992

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

php jq 饼状图,Java、PHP、Python、JS 等开发者都如何绘制统计图

目前很多程序员绘图基本上都是采用后端生成数据传递给前端,然后前端将数据渲染到绘图库上面进行显示,从而得到我们***看到的各种图,但是有时候,我们发现需要传递的数据很多很多,那么这个时候如果将数据传递给前端进行分析并展示的话是非常慢的,所以有必要在后端进行各种统计图的生成,下面我们就来聊聊各种程序员都是怎么进行图制作的?PHP程序员用PHP制作过统计图的人都应该知道,JqGraph与PHP的黄金搭档...

weixin_31527905的博客 234
上一篇: Android的自定义Menu使用PopupWindow实现
下一篇: Android手机通讯录
Bobby_lyc
博客等级 码龄16年 1164粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值