【Android开发日记】AndroidCharts 柱状图 BarView修改:添加数值和颜色

本文介绍如何修改AndroidCharts库的BarView,使其能显示数值和颜色。作者分享了修改BarView的步骤,包括设置底部横坐标、空座位数、总座位数,以及在onDraw方法中绘制数据和颜色。此外,还提供了实现点击横轴坐标打开WebView的功能。示例代码展示了如何实例化BarView并传递数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 前言:前段时间做的工程,自己一个人小打小闹的修改着,代码不完善之处请在评论指出,谢谢!

工程来源:github AndroidCharts:https://github.com/dacer/AndroidCharts

修改:使得BarView可以显示数值和颜色

我的需求:将每间教室的总座位数,空座位数显示在图上

效果图:

代码1: 修改后的BarView.java

package com.androidcharts;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;


/**
 * Created by Dacer on 11/11/13.
 */
public class BarView extends View {
    private ArrayList<Float> percentList;
    private ArrayList<Float> targetPercentList;
    private ArrayList<Float> AllpercentList;
    private ArrayList<Float> AlltargetPercentList;
    private Paint textPaint;
    private Paint BlankNumPaint;
    private Paint AllNumPaint;
    private Paint bgPaint;
    private Paint fgPaint;
    private Paint AllfgPaint;
    private Rect rect;
    private int barWidth;
//    private boolean showSideMargin = true;
    private int bottomTextDescent;
    private boolean autoSetWidth = true;
    private int topMargin;
    private int bottomTextHeight;
    
    private int clickarea;            //点击坐标轴上的区域的数值
    public boolean clickaarea = false; 
    public String clickroom = null;  
    
    private ArrayList<String> bottomTextList;
    private ArrayList<String> BlankSeatList;
    private ArrayList<String> AllSeatList;
    private final int MINI_BAR_WIDTH;
    private final int BAR_SIDE_MARGIN;
    private final int TEXT_TOP_MARGIN;
    private final int TEXT_COLOR = Color.parseColor("#9B9A9B");
    private final int NUM_COLOR = Color.parseColor("#1E90FF");
    private final int BACKGROUND_COLOR = Color.parseColor("#F6F6F6");
    private final int FOREGROUND_COLOR = Color.parseColor("#00FF7F");
    private final int AllFOREGROUND_COLOR = Color.parseColor("#AFEEEE");
    
    public interface DeliverRoomListener {
		public void DeliverRoom(String classname);
	}
	
	private DeliverRoomListener mDeliverRoomListener;
//	
	public void setRoomClickedListener(DeliverRoomListener listener){
		mDeliverRoomListener = listener;
    }
    
        
    private Runnable animator = new Runnable() {
        @Override
        public void run() {
                boolean needNewFrame = false;
                for (int i=0; i<targetPercentList.size();i++) {
                    if (percentList.get(i) < targetPercentList.get(i)) {
                        percentList.set(i,percentList.get(i)+0.02f);
                        needNewFrame = true;
                    } else if (percentList.get(i) > targetPercentList.get(i)){
                        percentList.set(i,percentList.get(i)-0.02f);
                        needNewFrame = true;
                    }
                    if(Math.abs(targetPercentList.get(i)-percentList.get(i))<0.02f){
                        percentList.set(i,targetPercentList.get(i));
                    }
                }
                if (needNewFrame) {
                    postDelayed(this, 20);
                }
                invalidate();
        }
    };
    /*
     * 座位总数
     */
    private Runnable Allanimator = new Runnable() {
        @Override
        public void run() {
                boolean needNewFrame = false;
                for (int i=0; i<AlltargetPercentList.size();i++) {
                    if (AllpercentList.get(i) < AlltargetPercentList.get(i)) {
                    	AllpercentList.set(i,AllpercentList.get(i)+0.02f);
                        needNewFrame = true;
                    } else if (AllpercentList.get(i) > AlltargetPercentList.get(i)){
                    	AllpercentList.set(i,AllpercentList.get(i)-0.02f);
                        needNewFrame = true;
                    }
                    if(Math.abs(AlltargetPercentList.get(i)-AllpercentList.get(i))<0.02f){
                    	AllpercentList.set(i,AlltargetPercentList.get(i));
                    }
                }
                if (needNewFrame) {
                    postDelayed(this, 20);
                }
                invalidate();
        }
    };

    public BarView(Context context){
        this(context,null);
    }
    public BarView(Context context, AttributeSet attrs){
        super(context, attrs);
        bgPaint = new Paint();
        bgPaint.setAntiAlias(true);
        bgPaint.setColor(BACKGROUND_COLOR);
        fgPaint = new Paint(bgPaint);
        fgPaint.setColor(FOREGROUND_COLOR);
        AllfgPaint = new Paint(bgPaint);
        AllfgPaint.setColor(AllFOREGROUND_COLOR);
        rect = new Rect();
        topMargin = MyUtils.dip2px(context, 5);
        int textSize = MyUtils.sp2px(context, 15);
        int numSize = MyUtils.sp2px(context, 13);
        barWidth = MyUtils.dip2px(context,22);
        MINI_BAR_WIDTH = MyUtils.dip2px(context,22);
        BAR_SIDE_MARGIN  = MyUtils.dip2px(context,22);
        TEXT_TOP_MARGIN = MyUtils.dip2px(context, 5);
        textPaint = new Paint();
        textPaint.setAntiAlias(true);
        textPaint.setColor(TEXT_COLOR);
        textPaint.setTextSize(textSize);
        textPaint.setTextAlign(Paint.Align.CENTER);
        BlankNumPaint = new Paint();
        BlankNumPaint.setAntiAlias(true);
        BlankNumPaint.setColor(NUM_COLOR);
        BlankNumPaint.setTextSize(numSize);
        BlankNumPaint.setTextAlign(Paint.Align.CENTER);
        AllNumPaint = new Paint();
        AllNumPaint.setAntiAlias(true);
        AllNumPaint.setColor(NUM_COLOR);
        AllNumPaint.setTextSize(numSize);
        AllNumPaint.setTextAlign(Paint.Align.CENTER);
        percentList = new ArrayList<Float>();
        AllpercentList = new ArrayList<Float>();
    }

    /**
     * dataList will be reset when called is method.
     * @param bottomStringList The String ArrayList in the bottom.
     */
    public void setBottomTextList(ArrayList<String> bottomStringList){
//        this.dataList = null;
        this.bottomTextList = bottomStringList;
        Rect r = new Rect();
        bottomTextDescent = 0;
        barWidth = MINI_BAR_WIDTH;
        for(String s:bottomTextList){
            textPaint.getTextBounds(s,0,s.length(),r);
            BlankNumPaint.getTextBounds(s,0,s.length(),r);
            AllNumPaint.getTextBounds(s,0,s.length(),r);
            if(bottomTextHeight<r.height()){
                bottomTextHeight = r.height();
            }
            if(autoSetWidth&&(barWidth<r.width())){
                barWidth = r.width();
            }
            if(bottomTextDescent<(Math.abs(r.bottom))){
                bottomTextDescent = Math.abs(r.bottom);
            }
        }
        setMinimumWidth(2);
        postInvalidate();
    }

    public void setBlankSeatList(ArrayList<String> BlankSeatStringList){
      this.BlankSeatList = BlankSeatStringList;
    }
    
    public void setAllSeatList(ArrayList<String> AllSeatStringList){
      this.AllSeatList = AllSeatStringList;
    }
    
    
    /**
     *
     * @param list The ArrayList of Integer with the range of [0-max].
     */
    public void setDataList(ArrayList<Integer> list, int max){
        targetPercentList = new ArrayList<Float>();
        if(max == 0) max = 1;

        for(Integer integer : list){
            targetPercentList.add(1-(float)integer/(float)max);
        }

        // Make sure percentList.size() == targetPercentList.size()
        if(percentList.isEmpty() || percentList.size()<targetPercentList.size()){
            int temp = targetPercentList.size()-percentList.size();
            for(int i=0; i<temp;i++){
                percentList.add(1f);
            }
        } else if (percentList.size()>targetPercentList.size()){
            int temp = percentList.size()-targetPercentList.size();
            for(int i=0; i<temp;i++){
                percentList.remove(percentList.size()-1);
            }
        }
        setMinimumWidth(2);
        removeCallbacks(animator);
        post(animator);
    }
    /*
     * 同理,将每个教室的座位总数也传进来
     */
    public void setAllDataList(ArrayList<Integer> list, int max){
    	AlltargetPercentList = new ArrayList<Float>();
        if(max == 0) max = 1;

        for(Integer integer : list){
        	AlltargetPercentList.add(1-(float)integer/(float)max);
        }

        // Make sure percentList.size() == targetPercentList.size()
        if(AllpercentList.isEmpty() || AllpercentList.size()<AlltargetPercentList.size()){
            int temp = AlltargetPercentList.size()-AllpercentList.size();
            for(int i=0; i<temp;i++){
            	AllpercentList.add(1f);
            }
        } else if (AllpercentList.size()>AlltargetPercentList.size()){
            int temp = AllpercentList.size()-AlltargetPercentList.size();
            for(int i=0; i<temp;i++){
            	AllpercentList.remove(AllpercentList.size()-1);
            }
        }
        setMinimumWidth(2);
        removeCallbacks(Allanimator);
        post(Allanimator);
    }
    

    @Override
    protected void onDraw(Canvas canvas) {
        int i = 1,j = 1,k = 1;
        if(percentList != null && !percentList.isEmpty()){
            for(Float f:percentList){
                rect.set(BAR_SIDE_MARGIN*i+barWidth*(i-1),
                        topMargin,
                        (BAR_SIDE_MARGIN+barWidth)* i,
                        getHeight()-bottomTextHeight-TEXT_TOP_MARGIN);
                canvas.drawRect(rect,bgPaint);
                rect.set(BAR_SIDE_MARGIN*i+barWidth*(i-1),
                        topMargin+(int)((getHeight()-topMargin)*AllpercentList.get(i-1)),
                        (BAR_SIDE_MARGIN+barWidth)* i,
                        getHeight()-bottomTextHeight-TEXT_TOP_MARGIN);
                canvas.drawRect(rect,AllfgPaint);
                rect.set(BAR_SIDE_MARGIN*i+barWidth*(i-1),
                        topMargin+(int)((getHeight()-topMargin)*percentList.get(i-1)),
                        (BAR_SIDE_MARGIN+barWidth)* i,
                        getHeight()-bottomTextHeight-TEXT_TOP_MARGIN);
                canvas.drawRect(rect,fgPaint);
                i++;
            }
        }

        if(bottomTextList != null && !bottomTextList.isEmpty()){
            i = 1;j = 1;k = 1;
            //底部数字
            for(String s:bottomTextList){
                canvas.drawText(s,BAR_SIDE_MARGIN*i+barWidth*(i-1)+barWidth/2,
                        getHeight()-bottomTextDescent,textPaint);
                i++;
            }
            //空座位数值
            for(String s:BlankSeatList){
            	float y=( topMargin+(int)((getHeight()-topMargin)*percentList.get(j-1)) + getHeight()-bottomTextHeight-TEXT_TOP_MARGIN)/2;
            	if (y> (getHeight()-bottomTextHeight-TEXT_TOP_MARGIN-topMargin-15))
            	   y=getHeight()-bottomTextHeight-TEXT_TOP_MARGIN-topMargin;
                canvas.drawText(s,BAR_SIDE_MARGIN*j+barWidth*(j-1)+barWidth/2,
                        y,BlankNumPaint);
                j++;
            }
            //总座位数值
            for(String s:AllSeatList){
            	float y=topMargin+(int)((getHeight()-topMargin)*AllpercentList.get(k-1));
                canvas.drawText(s,BAR_SIDE_MARGIN*k+barWidth*(k-1)+barWidth/2,
                        y,AllNumPaint);
                k++;
            }
        }
   
      
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mViewWidth = measureWidth(widthMeasureSpec);
        int mViewHeight = measureHeight(heightMeasureSpec);
        setMeasuredDimension(mViewWidth,mViewHeight);
    }

    private int measureWidth(int measureSpec){
        int preferred = 0;
        if(bottomTextList != null){
            preferred = bottomTextList.size()*(barWidth+BAR_SIDE_MARGIN);
        }
        return getMeasurement(measureSpec, preferred);
    }

    private int measureHeight(int measureSpec){
        int preferred = 222;
        return getMeasurement(measureSpec, preferred);
    }

    private int getMeasurement(int measureSpec, int preferred){
        int specSize = MeasureSpec.getSize(measureSpec);
        int measurement;
        switch(MeasureSpec.getMode(measureSpec)){
            case MeasureSpec.EXACTLY:
                measurement = specSize;
                break;
            case MeasureSpec.AT_MOST:
                measurement = Math.min(preferred, specSize);
                break;
            default:
                measurement = preferred;
                break;
        }
        return measurement;
    }
    
 //处理横轴标注的点击事件
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Point point = new Point();
        point.x = (int) event.getX();
        point.y = (int) event.getY();      
        Region rv = new Region();
        int a,b,c,d;

        if(bottomTextList != null || !bottomTextList.isEmpty()){
	       	        
	        for(int i=0;i<bottomTextList.size();i++)
	        {
	        	a=BAR_SIDE_MARGIN*(i+1)+barWidth*i-BAR_SIDE_MARGIN/2; //L
	        	b=a+BAR_SIDE_MARGIN+barWidth;                         //R
	        	c=getHeight()-bottomTextHeight-TEXT_TOP_MARGIN-20;    //T
	        	d=getHeight()+20;                                      //B
	        	rv.set(a,c,b,d);
	        	if (rv.contains(point.x,point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
                    clickarea = i;               
                }else if (event.getAction() == MotionEvent.ACTION_UP){
                    if (rv.contains(point.x,point.y)){
                        //把点击的教室名传进接口
                    	 clickroom = bottomTextList.get(clickarea); 
                         if (mDeliverRoomListener != null)
                         	mDeliverRoomListener.DeliverRoom(clickroom);   
                    	 System.out.println("click:"+clickarea);
                    }
                }
	        }
        }
        if (event.getAction() == MotionEvent.ACTION_DOWN ||
                event.getAction() == MotionEvent.ACTION_UP){
            postInvalidate();
        }
        return true;
    }
    
}

说明:

1.通过以下5个方法将数据传进BarView实例内:

    public void setBottomTextList(ArrayList<String> bottomStringList)            //底部横坐标数据

    public void setBlankSeatList(ArrayList<String> BlankSeatStringList)         //空座位个数 string  用来显示在图上

    public void setAllSeatList(ArrayList<String> AllSeatStringList)                    //总座位个数 string  用来显示在图上

    public void setDataList(ArrayList<Integer> list, int max)                              //空座位数据   int     用来转化成高度,画图

    public void setAllDataList(ArrayList<Integer> list, int max)                         //总座位数据   int     用来转化成高度,画图

    我比较懒,因为联网拿到的json就是string,所以直接将要显示在图上的数据给传进来了,同时通过setDataList将int类型的数据传进来,其实数据是一样的。大家可以自己修改一下。

    其中max这个参数是这组数据中最大的,用来确定BarView的高度,看过BarView源码的应该都清楚。

2. 在onDraw中 绘制,包括横坐标数据,两组数字,3组颜色

    这个根据大家的需求看着修改。

3. 代码中重载了onTouchEvent函数,旨在点击横轴坐标可以打开一个WebView,不需要的请注释掉这个函数,这里目的是向大家展示如果获取横轴坐标的数据的位置。


代码2:嵌入了BarView的 Activity 相关代码,主要是实例化BarView以及传数据

实例化:

		 final BarView barView = (BarView)this.findViewById(R.id.lib_bar_view);
		 barView.setRoomClickedListener(this);

传数据:

SetCurrentBlankNum(barView);

private void SetCurrentBlankNum(BarView barView){
	        int r = dataList.length;
	        int max = 0;
	        totalblanknum = 0;
	        bottomList.clear();
	        barDataList.clear();
	        BlankNumList.clear();
	        AllbarDataList.clear();
	        AllNumList.clear();
	        for (int i=0; i<r/3; i++){
	        	bottomList.add(dataList[i*3]);
	        	barDataList.add(Integer.parseInt(dataList[1+i*3]));
	        	BlankNumList.add(dataList[1+i*3]);
	        	totalblanknum = totalblanknum + Integer.parseInt(dataList[1+i*3]);
	        	//找到最大教室的座位个数
	        	max = (Integer.parseInt(dataList[2+i*3])>max) ? Integer.parseInt(dataList[2+i*3]) : max;
	        	AllbarDataList.add(Integer.parseInt(dataList[2+i*3]));
	        	AllNumList.add(dataList[2+i*3]);
	        }
	        barView.setBottomTextList(bottomList);   //横轴area名称
	        barView.setBlankSeatList(BlankNumList);	 //空座位数目 string
	        barView.setAllSeatList(AllNumList);	     //总座位数目 string
	        barView.setDataList(barDataList,max);   //绘制上层bar的数据 int
	        barView.setAllDataList(AllbarDataList,max+10);//绘制底层bar的数据 int
	    }

说明:

1. dataList:

     是一个 String[] 类型的数组,我是存放进过初步处理的json的。json格式:name1,blanknum1,totalnum1,name2,blanknum2,totalnum2,,,

     所以dataList数据也是这样的。

2.max的取值:

    max值传进BarView中确定了 绘制的Bar的高度,这里max+10 是因为总座位数的数据高度。


    如有错误或这需要改进的地方望指出。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值