Android 自定义柱状图及属性动画

来源:互联网 发布:js日期写出某天的日期 编辑:程序博客网 时间:2024/05/23 14:10

前段时间公司项目中用到了统计图,网上找了些资料和框架都不能满足我的需求,没办法,只有自己写了。

近来清闲,将其抽出一个demo了,欢迎大家交流指正。

效果图先行

实现方案有两个,一是自定义控件,二是使用属性动画。属性动画在api11以上版本才有,在11版本以下使用可以引入nineoldandroids框架。

由于属性动画比较简单,这里主要说下自定义控件

自定义控件源码如下:

/** * 工程名: histogram * 文件名: HistogramView.java * 包名: com.style.histogram * 日期: 2014-4-21下午8:23:38 * Copyright (c) 2014 **/package com.style.histogram; 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.Rect;import android.graphics.RectF;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.LinearLayout;import android.widget.RelativeLayout;import android.widget.RelativeLayout.LayoutParams;/** * 类名: HistogramView <br/> * 功能: 柱状图. <br/> * 日期: 2014-4-21 下午8:23:38 <br/> * * @author   msl * @version    */public class HistogramView extends View implements Runnable{private static final String TAG = HistogramView.class.getSimpleName();private int comWidth; //控件宽度private int comHeight;//控件高度private View rateView;//进度条private View rateTopView; //进度条顶部Viewprivate String rateBackgroundColor;//进图条背景颜色private int rateBackgroundId; //进图条背景图片idprivate Bitmap rataBackgroundBitmap;private boolean isHasRateTopView; //进度条顶部Viewprivate int rateHeight; //进度条的高private int rateWidth; //进度条的宽private int rateAnimValue;//进度条动画高度private int orientation; //设置柱状图方向private double progress;//设置进度  1为最大值private boolean isAnim = true; //是否动画显示统计条    private Handler handler = new Handler();//动画handlerprivate int animRate = 1; //动画速度   以每1毫秒计private int animTime = 1;//动画延迟执行时间private Canvas canvas;//画布public HistogramView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle); }public HistogramView(Context context, AttributeSet attrs) {super(context, attrs); }public HistogramView(Context context) {super(context); } @Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //初始化控件和进度的条相关参数comWidth = w;comHeight = h;if(orientation==LinearLayout.HORIZONTAL){rateWidth = (int) (w*progress); rateHeight = h;}else{rateHeight = (int) (h*progress); rateWidth = w;}}@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas);this.canvas = canvas;Paint paint = new Paint();paint.setAntiAlias(true);paint.setStyle(Paint.Style.FILL);Log.d(TAG, "onDraw  rateBackgroundColor===="+rateBackgroundColor);if(rateBackgroundColor!=null){drawViewWithColor(paint,isAnim);}else if(rateBackgroundId!=-1){drawViewWithBitmap(paint, isAnim);}}/** *  * drawViewWithColor:(绘制颜色进度条). <br/> * @author msl * @param paint * @param isAnim * @since 1.0 */private void drawViewWithColor(Paint paint,boolean isAnim){paint.setColor(Color.parseColor(rateBackgroundColor));Log.d(TAG, "rateBackgroundColor===="+rateBackgroundColor);if(isAnim){handler.postDelayed(this, animTime); if(orientation==LinearLayout.HORIZONTAL){//水平方向柱状图canvas.drawRect(0, 0, rateAnimValue, comHeight, paint); }else{//垂直方向柱状图canvas.drawRect(0, comHeight-rateAnimValue, comWidth, comHeight, paint); }}else {if(orientation==LinearLayout.HORIZONTAL){//水平方向无动画柱状图canvas.drawRect(0, 0, rateWidth, comHeight, paint);}else{//垂直方向无动画柱状图canvas.drawRect(0, comHeight-rateHeight, comWidth, comHeight, paint); }}}/** *  * drawViewWithBitmap:(绘制图片进度条). <br/> * @author msl * @param paint * @param isAnim * @since 1.0 */private void drawViewWithBitmap(Paint paint,boolean isAnim){Log.d(TAG, "bitmap===="+rataBackgroundBitmap);RectF dst = null;if(isAnim){handler.postDelayed(this, animTime); if(orientation==LinearLayout.HORIZONTAL){//水平方向柱状图    dst = new RectF(0, 0, rateAnimValue, comHeight);    canvas.drawBitmap(rataBackgroundBitmap, null, dst, paint);}else{//垂直方向柱状图dst = new RectF(0, comHeight-rateAnimValue, comWidth, comHeight);canvas.drawBitmap(rataBackgroundBitmap, null, dst, paint);}}else {if(orientation==LinearLayout.HORIZONTAL){//水平方向无动画柱状图dst = new RectF(0, 0, rateWidth, comHeight);canvas.drawBitmap(rataBackgroundBitmap, null, dst, paint);}else{//垂直方向无动画柱状图 dst = new RectF(0, comHeight-rateHeight, comWidth, comHeight);canvas.drawBitmap(rataBackgroundBitmap, null, dst, paint);}}}    public double getProgress() {return progress;}public void setProgress(double progress) {this.progress = progress; }public View getRateView() {return rateView;}public void setRateView(View rateView) {this.rateView = rateView;}public int getRateHeight() {return rateHeight;}public void setRateHeight(int rateHeight) {this.rateHeight = rateHeight;}public int getRateWidth() {return rateWidth;}public void setRateWidth(int rateWidth) {this.rateWidth = rateWidth;}public int getOrientation() {return orientation;}public void setOrientation(int orientation) {this.orientation = orientation;}public boolean isAnim() {return isAnim;}public void setAnim(boolean isAnim) {this.isAnim = isAnim;}public int getAnimRate() {return animRate;}public void setAnimRate(int animRate) {this.animRate = animRate;}public String getRateBackgroundColor() {return rateBackgroundColor;}public void setRateBackgroundColor(String rateBackgroundColor) {this.rateBackgroundColor = rateBackgroundColor;rateBackgroundId = -1;rataBackgroundBitmap = null;}public int getRateBackgroundId() {return rateBackgroundId;}public void setRateBackgroundId(int rateBackground) {this.rateBackgroundId = rateBackground;rataBackgroundBitmap = BitmapFactory.decodeResource(getResources(), rateBackgroundId);rateBackgroundColor = null;}/** *  *刷新界面 * @see java.lang.Runnable#run() */@Overridepublic void run() {if(orientation==LinearLayout.HORIZONTAL&&(rateAnimValue<=rateWidth)){rateAnimValue+=animRate;invalidate();}else if(orientation==LinearLayout.VERTICAL&&(rateAnimValue<=rateHeight)){rateAnimValue+=animRate;invalidate();}else{ handler.removeCallbacks(this);rateAnimValue = 0;}}}


因为需要有动画效果,故HistogramView实现Runable接口,结合Handler的postDelayed方法,使柱状条慢慢增长。

1、首先我们在onSizeChanged方法中初始化控件的相关参数,控件的宽高,柱状条的宽高。当然也可以在其它方法中初始化。这个随个人喜好。


2、接下来在onDraw方法中绘制我们的柱状条。代码挺简单的,没啥好说的。主要用到了两个方法

如果我们的柱状条为颜色值,则用drawRect,它有四个参数,分别是所要绘制区域的四个顶点坐标。

如果我们的柱状条为一张图片,使用drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) 

bitmap表示所要绘制上去的图片,src为图片的绘制区域,如果为null表示整张图片

dst表示图片在控件上的绘制区域,paint为我们的画笔。

使用

布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:padding="@dimen/activity_vertical_margin" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal" >        <com.style.histogram.HistogramView            android:id="@+id/hv1"            android:layout_width="50dp"            android:layout_height="100dp"            android:background="@drawable/asset_column_bg" />        <com.style.histogram.HistogramView            android:id="@+id/hv2"            android:layout_width="50dp"            android:layout_height="100dp"            android:layout_marginLeft="20dp"            android:background="#ee8833" />        <com.style.histogram.HistogramView            android:id="@+id/hv3"            android:layout_width="50dp"            android:layout_height="100dp"            android:layout_marginLeft="20dp"            android:background="@drawable/asset_column_bg" />        <com.style.histogram.HistogramView            android:id="@+id/hv4"            android:layout_width="50dp"            android:layout_height="100dp"            android:layout_marginLeft="20dp"            android:background="#ee8833" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:orientation="vertical" >        <com.style.histogram.HistogramView            android:id="@+id/hv5"            android:layout_width="match_parent"            android:layout_height="50dp"            android:background="#ee8833" />        <com.style.histogram.HistogramView            android:id="@+id/hv6"        android:layout_marginTop="20dp"            android:layout_width="match_parent"            android:layout_height="50dp"            android:background="#ee8833" />    </LinearLayout>         <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dp"        android:orientation="vertical" >        <RelativeLayout android:layout_width="50dp"        android:layout_height="100dp"               android:background="@drawable/asset_column_bg">        <View android:layout_width="50dp"            android:layout_height="0dp"            android:background="@drawable/dq_column"            android:layout_alignParentBottom="true"            android:id="@+id/v1"/>    </RelativeLayout>        <FrameLayout android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginLeft="20dp"        android:layout_marginTop="20dp"        android:background="#ee8833">        <View android:layout_width="0dp"            android:layout_height="50dp"            android:background="#123456"            android:id="@+id/v2"/>    </FrameLayout>   </LinearLayout></LinearLayout>


 java代码

package com.style.histogram;import android.os.Bundle;import android.view.View;import android.widget.LinearLayout;import android.animation.ObjectAnimator;import android.app.Activity; public class MainActivity extends Activity { @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);HistogramView hv1 = (HistogramView) findViewById(R.id.hv1);hv1.setProgress(0.4);hv1.setRateBackgroundId(R.drawable.dq_column);hv1.setOrientation(LinearLayout.VERTICAL);HistogramView hv2 = (HistogramView) findViewById(R.id.hv2);hv2.setProgress(0.4);hv2.setRateBackgroundColor("#123456");hv2.setOrientation(LinearLayout.VERTICAL);HistogramView hv3 = (HistogramView) findViewById(R.id.hv3);hv3.setProgress(0.4);hv3.setRateBackgroundId(R.drawable.dq_column);hv3.setOrientation(LinearLayout.VERTICAL);hv3.setAnim(false);HistogramView hv4 = (HistogramView) findViewById(R.id.hv4);hv4.setProgress(0.4);hv4.setRateBackgroundColor("#123456");hv4.setOrientation(LinearLayout.VERTICAL);hv4.setAnim(false);HistogramView hv5 = (HistogramView) findViewById(R.id.hv5);hv5.setProgress(0.4);hv5.setRateBackgroundColor("#123456");hv5.setOrientation(LinearLayout.HORIZONTAL); HistogramView hv6 = (HistogramView) findViewById(R.id.hv6);hv6.setProgress(0.4);hv6.setRateBackgroundColor("#123456");hv6.setOrientation(LinearLayout.HORIZONTAL);hv6.setAnim(false);View v1 = findViewById(R.id.v1); ObjectAnimator.ofInt(new ViewWrapper(v1), "height", 30).setDuration(4000).start(); View v2 = findViewById(R.id.v2); ObjectAnimator.ofInt(new ViewWrapper(v2), "width", 200).setDuration(4000).start();} class ViewWrapper{ private View mTarget;  public ViewWrapper(View target) {          mTarget = target;      }        public int getWidth() {          return mTarget.getLayoutParams().width;      }        public void setWidth(int width) {          mTarget.getLayoutParams().width = width;          mTarget.requestLayout();      }          public int getHeight() {          return mTarget.getLayoutParams().height;      }        public void setHeight(int height) {          mTarget.getLayoutParams().height = height;          mTarget.requestLayout();      }   } }


       

没啥难的,demo下载:github

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 五年级了计算题老是出错怎么办 三年级的孩子老是计算题出错怎么办 写在表上的字写错了怎么办不能涂改 我的孩子做作业很马虎怎么办 幼儿园老师把学生名字写错怎么办 孩子的手写字磨了疙瘩怎么办 我家孩子上一年级算题特慢怎么办 脚注太多导致与正文距离太大怎么办 搜狗输入法打字不显示选字框怎么办 粘贴文字时带自动添加了序号怎么办 电脑上是表字打印出来是坔怎么办 不同颜色的衣服一起洗染色了怎么办 两岁宝宝不爱吃饭怎么办且消瘦 一岁两个月宝宝不爱吃饭怎么办 罗汉鱼头座大颜色不红怎么办 为什么孩子的牙都是龋齿怎么办呀 蓝迪儿童墙膜出现气泡了怎么办 空sd卡或文件系统不受支持怎么办 8个月宝宝吃了纸怎么办 宝宝出生两天了不吃不喝怎么办 八个月宝宝阴唇边红肿痛怎么办 儿童五周岁九个月比同龄矮怎么办 8个月宝宝长牙母乳喂养咬人怎么办 6周的孩子视力低常怎么办 宝宝吃了甜食生痰咳嗽怎么办 两个月的边牧抵抗力差怎么办 阴茎勃起后向上翘的厉害怎么办 5个月宝宝发烧38.5度怎么办 9个月宝宝发烧38.5度怎么办 八个月宝宝只吃母乳不吃奶粉怎么办 八个月母乳不够宝宝不吃奶粉怎么办 八个月宝宝吃母乳不吃奶粉怎么办 八个月宝宝戒奶不吃奶粉怎么办 刚满月的宝宝发烧38度怎么办 未满月的宝宝发烧38度怎么办 半月大的婴儿吃奶就漾奶怎么办 上司交给你不能完成的任务怎么办 电脑光驱里放入光碟放不出来怎么办 黑暗之魂3太难了怎么办 苹果手机下载的游戏闪退怎么办 宝宝两岁了不怎么爱拉大便怎么办?