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
- Android 自定义柱状图及属性动画
- android自定义带动画的柱状图控件
- Android自定义属性动画
- 自定义控件-- 柱状图--Android
- android自定义柱状图
- android自定义横向柱状图
- 【android自定义控件】属性动画 <五>
- Android 2.x自定义属性动画ValueAnimator
- android自定义路径的属性动画
- Android自定义view之属性动画初见
- Android 属性动画——自定义Drawable
- 属性动画 自定义属性
- Android自定义控件:动画类----alpha、scale、translate、rotate、set的xml属性及用法
- Android自定义控件:动画类----alpha、scale、translate、rotate、set的xml属性及用法
- Android自定义控件:动画类----alpha、scale、translate、rotate、set的xml属性及用法
- Android自定义属性及使用
- Android自定义控件及属性
- Android中自定义组件及自定义属性
- NYOJ 622 Vote
- 早已陌路相去
- java 语句
- Java使用foreach遍历集合元素
- poj 2194 Stacking Cylinders 计算几何之向量旋转
- Android 自定义柱状图及属性动画
- Apache Http Server学习笔记
- JBoss启动项目报错
- 创建守护进程
- Android开发无法关联源码
- 求数组中最长递增子序列
- http://dongxi.douban.com/article/1144963/
- thinkphp 判断volist 最后一条
- ArcGIS提取CAD数据