android自定义折线图

BrokenLine控件:

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.Shader;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;

import com.qianhua.healthy_brain.R;

/**
 * 线框图
 *
 * @author Administrator
 *
 */
public class BrokenLine extends View {

	private List<Integer> milliliter;
	private float tb;
	private float interval_left_right;
	private float interval_left;
	private float margin_bottom;
	private Paint paint_date, paint_brokenLine, paint_dottedline,
			paint_brokenline_big, framPanint;

	private int time_index;
	private Bitmap bitmap_point;
	private Path path;
	private float dotted_text;

	public float getDotted_text() {
		return dotted_text;
	}

	public void setDotted_text(float dotted_text) {
		this.dotted_text = dotted_text;
	}

	private int fineLineColor = 0x5faaaaaa; // 灰色
	private int blueLineColor = 0xff00ffff; // 蓝色
	private int orangeLineColor = 0xffd56f2b; // 橙色

	public BrokenLine(Context context, List<Integer> milliliter) {
		super(context);
		init(milliliter);
	}

	public void init(List<Integer> milliliter) {
		if (null == milliliter || milliliter.size() == 0)
			return;
		this.milliliter = delZero(milliliter);
		Resources res = getResources();
		tb = res.getDimension(R.dimen.historyscore_tb);
		interval_left_right = tb * 5.0f;
		interval_left = tb * 0.5f;
		margin_bottom=8*tb * 0.2f;

		paint_date = new Paint();
		paint_date.setStrokeWidth(tb * 0.1f);
		paint_date.setTextSize(tb * 1.2f);
		paint_date.setColor(fineLineColor);

		paint_brokenLine = new Paint();
		paint_brokenLine.setStrokeWidth(tb * 0.1f);
		paint_brokenLine.setColor(blueLineColor);
		paint_brokenLine.setAntiAlias(true);

		paint_dottedline = new Paint();
		paint_dottedline.setStyle(Paint.Style.STROKE);
		paint_dottedline.setColor(fineLineColor);

		paint_brokenline_big = new Paint();
		paint_brokenline_big.setStrokeWidth(tb * 0.2f);
		paint_brokenline_big.setColor(fineLineColor);
		paint_brokenline_big.setAntiAlias(true);

		framPanint = new Paint();
		framPanint.setAntiAlias(true);
		framPanint.setStrokeWidth(2f);

		path = new Path();
		bitmap_point = BitmapFactory.decodeResource(getResources(),
				R.drawable.icon_point_blue);
		setLayoutParams(new LayoutParams(
				(int) (this.milliliter.size() * interval_left_right),
				LayoutParams.MATCH_PARENT));
	}

	/**
	 * 移除左右为零的数据
	 *
	 * @return
	 */
	public List<Integer> delZero(List<Integer> milliliter) {
		List<Integer> list = new ArrayList<Integer>();
		int sta = 0;
		int end = 0;
		for (int i = 0; i < milliliter.size(); i++) {
			if (milliliter.get(i) != 0) {
				sta = i;
				break;
			}
		}
		for (int i = milliliter.size() - 1; i >= 0; i--) {
			if (milliliter.get(i) != 0) {
				end = i;
				break;
			}
		}
		for (int i = 0; i < milliliter.size(); i++) {
			if (i >= sta && i <= end) {
				list.add(milliliter.get(i));
			}
		}
		time_index = sta;
//		dotted_text = ((Collections.max(milliliter) - Collections .min(milliliter)) / 12.0f * 5.0f);
		return list;
	}

	protected void onDraw(Canvas c) {
		if (null == milliliter || milliliter.size() == 0)
			return;
		drawStraightLine(c);
		drawBrokenLine(c);
		drawDate(c);
	}

	/**
	 * 绘制竖线
	 *
	 * @param c
	 */
	public void drawStraightLine(Canvas c) {

		int count_line = 0;
		for (int i = 0; i < milliliter.size(); i++) {
			if (i==0) {//绘制Y轴
				c.drawLine(interval_left_right * i, 0, interval_left_right * i, getHeight() - margin_bottom, paint_date);
				for (int j = 0; j <10; j++) {
					c.drawText(String.valueOf(10*(j+1)), 0 ,(getHeight()-margin_bottom)/10*(10-(j+1)), paint_date);
					if (j==5){//绘制虚线
						paint_dottedline.setColor(orangeLineColor);
						Path path = new Path();
						path.moveTo(0, (getHeight()-margin_bottom)/10*(10-(j+1)));
						path.lineTo(getWidth(), (getHeight()-margin_bottom)/10*(10-(j+1)));
						PathEffect effects = new DashPathEffect(new float[] { tb * 0.3f,
								tb * 0.3f, tb * 0.3f, tb * 0.3f }, tb * 0.1f);
						paint_dottedline.setPathEffect(effects);
						c.drawPath(path, paint_dottedline);
					} 					

				}
				continue;
			}
			//绘制竖线 连续四条为一组
			paint_dottedline.setColor(fineLineColor);
			if (count_line == 0) {
				c.drawLine(interval_left_right * i, 0, interval_left_right * i, getHeight() - margin_bottom, paint_date);
			}
			if (count_line == 2) {
				c.drawLine(interval_left_right * i, tb * 1.5f, interval_left_right * i, getHeight() - margin_bottom, paint_date);
			}
			if (count_line == 1 || count_line == 3) {
				Path path = new Path();
				path.moveTo(interval_left_right * i, tb * 1.5f);
				path.lineTo(interval_left_right * i, getHeight() - margin_bottom);
				PathEffect effects = new DashPathEffect(new float[] { tb * 0.3f, tb * 0.3f, tb * 0.3f, tb * 0.3f }, tb * 0.1f);
				paint_dottedline.setPathEffect(effects);
				c.drawPath(path, paint_dottedline);
			}
			count_line++;
			if (count_line >= 4) {
				count_line = 0;
			}
		}
		//绘制X轴
		c.drawLine(0, getHeight() - margin_bottom, getWidth(), getHeight() - margin_bottom, paint_brokenline_big);
	}

	/**
	 * 绘制折线
	 *
	 * @param c
	 */
	public void drawBrokenLine(Canvas c) {
		int index = 0;
		float temp_x = 0;
		float temp_y = 0;
//		float base = (getHeight() - tb * 3.0f) / (Collections.max(milliliter) - Collections.min(milliliter));
		float base = (getHeight() - margin_bottom) / 100;

		Shader mShader = new LinearGradient(0, 0, 0, getHeight(), new int[] {
				Color.argb(100, 0, 255, 255), Color.argb(45, 0, 255, 255),
				Color.argb(10, 0, 255, 255) }, null, Shader.TileMode.CLAMP);
		framPanint.setShader(mShader);

		for (int i = 0; i < milliliter.size() - 1; i++) {
			Log.e("i", ""+milliliter.get(i));
			float x1 = interval_left_right * i;
			float y1 =  getHeight() - margin_bottom - (base * milliliter.get(i));
			float Y1 =  milliliter.get(i);
			float x2 = interval_left_right * (i + 1);
			float y2 =  getHeight() - margin_bottom - (base * milliliter.get(i + 1));
			float Y2 =  milliliter.get(i+1);

			if ((int) (base * milliliter.get(i + 1)) == 0 && index == 0) {
				index++;
				temp_x = x1;
				temp_y = y1;
			}
			if ((int) (base * milliliter.get(i + 1)) != 0 && index != 0) {
				index = 0;
				x1 = temp_x;
				y1 = temp_y;
			}

			paint_date.setColor(orangeLineColor);
			if (i==0) c.drawText(String.valueOf(Y1), x1, y1, paint_date);//绘出第一个值的大小

			if (index == 0) {
				c.drawText(String.valueOf(Y2), x2, y2, paint_date);//绘出第i+1个值的大小
				c.drawLine(x1, y1, x2, y2, paint_brokenLine);
				path.lineTo(x1, y1);
				if (i != 0)
					c.drawBitmap(bitmap_point,
							x1 - bitmap_point.getWidth() / 2,
							y1 - bitmap_point.getHeight() / 2, null);
				if (i == milliliter.size() - 2) {
					path.lineTo(x2, y2);
					path.lineTo(x2, getHeight());
					path.lineTo(0, getHeight());
					path.close();
					c.drawPath(path, framPanint);
					c.drawBitmap(bitmap_point,
							x2 - bitmap_point.getWidth() / 2,
							y2 - bitmap_point.getHeight() / 2, null);
				}
			}
		}
		paint_date.setColor(fineLineColor);

	}

	/**
	 * 绘制时间
	 *
	 * @param c
	 */
	public void drawDate(Canvas c) {

		Date date=new Date();//取时间
		Calendar calendar =new  GregorianCalendar();
		calendar.setTime(date);
		SimpleDateFormat dateFormat=new SimpleDateFormat("MM-dd");
		String[] dates=new String[milliliter.size()];
		for (int i = 0; i < milliliter.size(); i++) {
		     calendar.add(calendar.DATE,1);//把日期往后增加一天.整数往后推,负数往前移动
		     date=calendar.getTime();   //这个时间就是日期往后推一天的结果
		     dates[i]=dateFormat.format(date).toString();
		}

		for (int i = 0; i < milliliter.size(); i += 1) {
			paint_date.setStrokeWidth(tb * 2.8f);
			c.drawText(dates[i], interval_left_right * i ,getHeight(), paint_date);
		}

	}
}

Activity:

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

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.RelativeLayout;

import com.qianhua.healthy_brain.R;
import com.qianhua.healthy_brain.widget.BrokenLine;

public class TrainResultActivity extends Activity {
	RelativeLayout linear;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.train_result);
		List<Integer> lists = new ArrayList<Integer>();//线性图  范围0-100
		for (int i = 0; i < 48; i++) {
			if (i < 8 || i == 28 || i == 12 || i == 18 || i == 20 || i == 30
					|| i == 34) {
				lists.add(0);
			} else {
//				int item=getRandom(0, 100);
//				Log.w(""+i, ""+item);
				lists.add(getRandom(0, 100));
			}
		}
		linear= (RelativeLayout) findViewById(R.id.linear);
		linear.addView(new BrokenLine(this,lists));
	}

	public int getRandom(int min,int max){
		return (int) Math.round(Math.random()*(max-min)+min);
	}
}

xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#f4f4f7"
        android:orientation="vertical" >

        <HorizontalScrollView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_margin="10dp"
            android:scrollbars="none" >

            <RelativeLayout
                android:id="@+id/linear"
                android:layout_marginTop="30dp"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" >
            </RelativeLayout>
        </HorizontalScrollView>
    </LinearLayout>

</LinearLayout>

参考:http://www.apkbus.com/forum.php?mod=viewthread&tid=158365&extra=page%3D1

时间: 2024-11-11 06:44:39

android自定义折线图的相关文章

android 自定义折线图

看图: 比较简陋,主要是通过canvas画上去的: package com.example.democurvegraph.view; import java.util.ArrayList; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.Attribute

android绘画折线图一

最近需要实现用android来画折线图,所以百度了一下,发现确实很多,也很乱,现在整理两种方法(第二种方法在[android绘画折线图二]中实现),仅供大家参考,一起学习研究. 第一种使用ChartFactory.getLineChartIntent()方法获取,这种方法首先需要一个achartengine-1.0.0.jar(项目中有),然后建立一个简单的android项目 项目中所需要导入的包有: import java.util.ArrayList; import java.util.Ha

Android自定义控件-折线图

好长时间没有更新博客了,终于可以抽出时间写点东西了,写点什么呢?最近在qq群里边有人问,下边的这个控件怎么画?如下图所示:图可以左右拖动,直到显示完全为止.刚开始看到这个效果图,我也想了一下总共分为以下几个步骤: (1)坐标轴的绘画,并绘画坐标轴上的坐标值 (2)绘画坐标上的点,并将其串联起来 (3)最后进行封闭图形的填充 (4)事件的拖动重绘 1.首先定义自定义属性文件,并确定坐标轴的颜色,宽度,坐标文字的大小,线的颜色等 <?xml version="1.0" encodin

Android画折线图、柱状图、饼图(使用achartengine.jar)

自从用了画折线的jar包之后,就不想再用canvas画布去画了,编程就是要站在巨人的肩膀上. 所需要的jar包achartenginejar 折线代码布局文件就不上传了很简单 另一种线的渲染器 扇形图代码 柱状图代码 属性总结部分代码 新测试代码下载地址 所需要的jar包:achartengine.jar 下载地址:http://download.csdn.net/detail/zhengyikuangge/9460642 折线代码(布局文件就不上传了,很简单): package com.exa

echarts自定义折线图横坐标时间间隔踩坑总结

折线图需求:横坐标为时间,要求按一定间隔展示,鼠标移至折线上间隔时间内的数据也可展示 其实很简单的一个配置就可搞定,但在不熟悉echarts配置的情况下,就很懵逼 xAxis: { boundaryGap: false, // 距离坐标原点是否有间隙 axisLabel: { //  如果这个字段不设置,echarts会根据屏宽及横坐标数据自动给出间隔 interval: 30, // 间隔长度,可自定义(如果是时间格式,echarts会自动处理) rotate: 40 // 横坐标上label

Android 自定义码表图

项目里面又碰到一个酷炫的刻度盘,还要带平滑动画的,真伤脑筋啊,网上搜索半天无果,果然还是得自己动手啊. 用时半天,做了一个DEMO,效果图如下: 代码如下,复制粘贴就能跑了: MeterView.java: /** * Copyright (C) 2015 * * MeterView.java * * Description: * * Author: Liao Longhui * * Ver 1.0, 2015-05-17, Liao Longhui, Create file */ packag

qt 自定义折线图

一.  底层代码开发示例 参考: https://blog.csdn.net/qq_37385181/article/details/83055915 demo下载地址:https://download.csdn.net/download/qq_37385181/10774870 二 qt Qtchart开发示例 https://blog.csdn.net/zcy123321/article/details/90024845 https://blog.csdn.net/mars_xiaolei/

iOS 动画绘制线条颜色渐变的折线图

效果图 .................... 概述 现状 折线图的应用比较广泛,为了增强用户体验,很多应用中都嵌入了折线图.折线图可以更加直观的表示数据的变化.网络上有很多绘制折线图的demo,有的也使用了动画,但是线条颜色渐变的折线图的demo少之又少,甚至可以说没有.该Blog阐述了动画绘制线条颜色渐变的折线图的实现方案,以及折线图线条颜色渐变的实现原理,并附以完整的示例. 成果 本人已将折线图封装到了一个UIView子类中,并提供了相应的接口.该自定义折线图视图,基本上可以适用于大部分

Android自定义视图三:给自定义视图添加“流畅”的动画

在第二部分我们实现了一个简单的折线图.这里假设你已经读了前篇.下面我们将继续为这个折线图添砖加瓦. 我在想给这个图的上方添加三个按钮,这样用户可以点选不同的按钮来查看不同类别的数据.比如,用户可以查看走路的.跑步的和骑车的.用户点不同的按钮,我们就跟还不同的运动数据显示在图形里. 我们实现了按钮点击后,设置不同的坐标点数据,然后运行APP.你会发现,虽然方法setChartData()已经被调用了,但是图形一点变化都没有.为什么呢?因为我们没有通知折线图"重绘".这可以通过调用inva