Android 如何 画 柱状图 -------自定义View

实现了 柱状图 根据 SeekBar的滑动 改变的效果:

图示效果:

自定义View的代码:

package com.example.coustomviewdemo;

import android.R.color;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.view.View;

public class StatscsView extends View {

	public StatscsView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub

		init(context, null);
	}

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

//	坐标轴 轴线 画笔:
	private Paint axisLinePaint;
//	坐标轴水平内部 虚线画笔
	private Paint hLinePaint;
//	绘制文本的画笔
	private Paint titlePaint;
//	矩形画笔 柱状图的样式信息
	private Paint recPaint;
	private void init(Context context, AttributeSet attrs)
	{

		axisLinePaint = new Paint();
		hLinePaint = new Paint();
		titlePaint = new Paint();
		recPaint = new Paint();

		axisLinePaint.setColor(Color.DKGRAY);
		hLinePaint.setColor(Color.LTGRAY);
		titlePaint.setColor(Color.BLACK);

	}

	//7 条
	private int[] thisYear;

	//7 条
	private int[] lastYear;

	/**
	 * 跟新自身的数据 需要View子类重绘。
	 *
	 * 主线程 刷新控件的时候调用:
	 * this.invalidate();  失效的意思。
	 * this.postInvalidate();  可以子线程 更新视图的方法调用。
	 *
	 * */
	//updata this year data
	public void updateThisData(int[] thisData)
	{
		thisYear = thisData;
//		this.invalidate(); //失效的意思。
		this.postInvalidate();  //可以子线程 更新视图的方法调用。
	}

	//updata last year data
	public void updateLastData(int[] lastData)
	{
		lastYear = lastData;
//		this.invalidate(); //失效的意思。
		this.postInvalidate();  //可以子线程 更新视图的方法调用。
	}

	private String[] yTitlesStrings =
			new String[]{"80000","60000","40000","20000","0"};

	private String[] xTitles =
			new String[]{"1","2","3","4","5","6","7"};

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);

		int width = getWidth();
		int height = getHeight();

		// 1 绘制坐标线:
		canvas.drawLine(100, 10, 100, 320, axisLinePaint);

		canvas.drawLine(100, 320, width-10 , 320, axisLinePaint);

		// 2 绘制坐标内部的水平线

		int leftHeight = 300;// 左侧外周的 需要划分的高度:

		int hPerHeight = leftHeight/4;

		hLinePaint.setTextAlign(Align.CENTER);
		for(int i=0;i<4;i++)
		{
			canvas.drawLine(100, 20+i*hPerHeight, width-10, 20+i*hPerHeight, hLinePaint);
		}

		// 3 绘制 Y 周坐标

		FontMetrics metrics =titlePaint.getFontMetrics();
		int descent = (int)metrics.descent;
		titlePaint.setTextAlign(Align.RIGHT);
		for(int i=0;i<yTitlesStrings.length;i++)
		{
			canvas.drawText(yTitlesStrings[i], 80, 20+i*hPerHeight+descent, titlePaint);
		}

		// 4  绘制 X 周 做坐标

		int xAxisLength = width-110;
		int columCount = xTitles.length+1;
		int step = xAxisLength/columCount;

		for(int i=0;i<columCount-1;i++)
		{
			canvas.drawText(xTitles[i], 100+step*(i+1), 360 , titlePaint);
		}

		// 5 绘制矩形

		if(thisYear != null && thisYear.length >0)
		{
			int thisCount = thisYear.length;

			for(int i=0;i<thisCount;i++)
			{
				int value = thisYear[i];

				int num = 8 - value / 10000 ;

				recPaint.setColor(0xFF1078CF);

				Rect rect = new Rect();

				rect.left  = 100 + step * (i+1)  - 10;
				rect.right = 100 + step * (i+1)  + 10;

//				当前的相对高度:
				int rh = (leftHeight * num) / 8 ;

				rect.top = rh + 20;
				rect.bottom = 320 ;

				canvas.drawRect(rect, recPaint);

			}
		}

		if(lastYear != null && lastYear.length >0)
		{
			int thisCount = lastYear.length;

			for(int i=0;i<thisCount;i++)
			{
				int value = lastYear[i];

				int num = 8 - value / 10000 ;

				recPaint.setColor(0xFFAA1122);

				Rect rect = new Rect();

				rect.left  = 100 + step * (i+1)  - 10;
				rect.right = 100 + step * (i+1)  + 10;

//				当前的相对高度:
				int rh = (leftHeight * num) / 8 ;

				rect.top = rh + 20;
				rect.bottom = 320 ;

				canvas.drawRect(rect, recPaint);

			}
		}

	}

}

Activity:

package com.example.coustomviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

public class StatscsActivity extends Activity implements
		OnSeekBarChangeListener {

	private SeekBar seekBar;

	private StatscsView statscsView;

	public StatscsActivity() {
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.sycts);

		seekBar = (SeekBar) this.findViewById(R.id.seekBar);

		statscsView = (StatscsView) this.findViewById(R.id.statscsView1);

		// seekerBar
		seekBar.setOnSeekBarChangeListener(this);

	}

	private int[] lastData0 = new int[] { 70000, 10000, 20000, 40000, 50000,
			80000, 40000 };
	private int[] thisData0 = new int[] { 40000, 10000, 10000, 20000, 30000,
			50000, 30000 };

	private int[] lastData1 = new int[] { 70000, 60000, 60000, 40000, 50000,
			80000, 80000 };
	private int[] thisData1 = new int[] { 40000, 30000, 30000, 20000, 30000,
			50000, 30000 };

	private int[] lastData2 = new int[] { 70000, 50000, 70000, 80000, 80000,
			80000, 70000 };
	private int[] thisData2 = new int[] { 40000, 10000, 40000, 40000, 30000,
			40000, 10000 };

	private int[] lastData3 = new int[] { 70000, 80000, 70000, 40000, 50000,
			80000, 40000 };
	private int[] thisData3 = new int[] { 10000, 10000, 10000, 20000, 30000,
			10000, 30000 };

	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		// TODO Auto-generated method stub

		int cc = progress / 4;

		switch (cc) {
		case 0:
			statscsView.updateThisData(lastData0);
			statscsView.updateLastData(thisData0);

			break;
		case 1:
			statscsView.updateThisData(lastData1);
			statscsView.updateLastData(thisData1);

			break;
		case 2:
			statscsView.updateThisData(lastData2);
			statscsView.updateLastData(thisData2);

			break;
		case 3:
			statscsView.updateThisData(lastData3);
			statscsView.updateLastData(thisData3);

			break;

		default:
			break;
		}

	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {
		// TODO Auto-generated method stub

	}
}

main.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" >

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="48"

        />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:gravity="center"
        >

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="1"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="2"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="3"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="4"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="5"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="6"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="7"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="8"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="9"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="10"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="11"
            />
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1" android:gravity="center"
            android:text="12"
            />

    </LinearLayout>

    <com.example.coustomviewdemo.StatscsView
        android:id="@+id/statscsView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

时间: 2024-10-21 17:48:10

Android 如何 画 柱状图 -------自定义View的相关文章

Android 绘制字符串到自定义view的中心

处理字符串的长度和宽度,并没有想象中的那么简单,要讲字符串画到自定义view的中心点,更加没有那么简单! 1. 计算字符串的长度 介绍两种计算方法,但是结果却很意外哦! (1)最小外接矩形 paint.setTextSize(textSize);paint.setTypeface(Typeface.MONOSPACE);Rect r = new Rect();paint.getTextBounds(text,0,text.length(),r);int height = r.bottom - r

Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)

转载请注明地址:http://blog.csdn.net/xiaanming/article/details/10298163 很多的时候,系统自带的View满足不了我们功能的需求,那么我们就需要自己来自定义一个能满足我们需求的View,自定义View我们需要先继承View,添加类的构造方法,重写父类View的一些方法,例如onDraw,为了我们自定义的View在一个项目中能够重用,有时候我们需要自定义其属性,举个很简单的例子,我在项目中的多个界面使用我自定义的View,每个界面该自定义View

Android知识梳理之自定义View

虽然android本身给我们提供了形形色色的控件,基本能够满足日常开发的需求,但是面对日益同质化的app界面,和不同的业务需求.我们可能就需要自定义一些View来获得比较好的效果.自定义View是android开发者走向高级开发工程师必须要走的一关. 转载请标明出处:http://blog.csdn.net/unreliable_narrator/article/details/51274264 一,构造函数: 当我们创建一个类去继承View的时候,会要求我们至少去实现一个构造函数. publi

Android Matrix手势缩放自定义view 不止于Imageview

转载请注明出处:http://blog.csdn.net/coderyue/article/details/51397409 之前写过一篇文章Android TextView 横竖排切换(字方向不变) 是自定义了一个LinearLayout, 实现了当然还不够, 还要对它进行操作, 平移,旋转 and 缩放, 相信很多小伙伴都知道对图片的平移等等操作最好用的就是矩阵了,因为有个方法叫做imageview.setImageMatrix(matrix), 直接构造一个矩阵对象然后设置到图片上就进行相

Android属性动画与自定义View——实现vivo x6更新系统的动画效果

晚上好,现在是凌晨两点半,然后我还在写代码.电脑里播放着<凌晨两点半>,晚上写代码,脑子更清醒,思路更清晰. 今天聊聊属性动画和自定义View搭配使用,前面都讲到自定义View和属性动画,但是一起用的还是不多,刚巧今晚手机提示我更新系统,我看到那个更新的动画还不错,仔细的分析了一下,于是我也决定写一个,不是一模一样的,但是效果和原理是一样的. 先看看图: 这是一张静态的图,这里有三个波浪线,当下载完之后,波浪线会往上活动,一直到消失. 所以难点也是在这个波浪线上.这个波浪线类似于一个水波纹,也

Android应用开发之自定义View触摸相关工具类全解

背景 最近有些乱,各种事情,各种交叉.好在还有一点上进心,于是继续将自定义这个系列的核心知识再梳理一下吧.关于自定义控件前面博文说过了,这里不会教你拿来主义,只授之以渔,如果你喜欢拿来主义,不好意思,请绕行,如果你喜欢得渔,那请继续. 前面我们已经叙述过了几篇关于自定义View涉及的东西,大家可以自己回过头去看我之前的博客,譬如事件处理.坐标系.工具类等.下面我们还是继续补充一些常用的自定义控件工具类. [工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请

Android ——利用OnDraw实现自定义View(转)

自定义View的实现方式大概可以分为三种,自绘控件.组合控件.以及继承控件.本文将介绍自绘控件的用法.自绘控件的意思是,这个控件上的内容是用onDraw函数绘制出来的.关于onDraw函数的介绍可参看 Android视图绘制流程完全解析,带你一步步深入了解View(二) . 例子1:在layout文件中使用自绘控件 出处:http://blog.csdn.net/guolin_blog/article/details/17357967 下面我们准备来自定义一个计数器View,这个View可以响应

【Android 应用开发】 自定义 View 组件 -- 圆形进度条

转载著名出处 : http://blog.csdn.net/shulianghan/article/details/40351487 代码下载 : -- CSDN 下载地址 : http://download.csdn.net/detail/han1202012/8069497 ; -- GitHub 地址 : https://github.com/han1202012/CircleProcess.git ; -- 工程示例 : 一. 相关知识点解析 1. 自定义 View 组件构造方法 构造方

Android 用属性动画自定义view的渐变背景

自定义view渐变背景,同时监听手势自动生成小圆球. 宿主Activity如下: package com.edaixi.tempbak; import java.util.ArrayList; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ArgbE