android 图标控件的实现(二)

来源:互联网 发布:矩阵的微分运算法则 编辑:程序博客网 时间:2024/06/16 11:15

在这篇博客中,将实现混合柱状图
这里写图片描述

在上一篇博客中讲到过,所有的图表类都只要重载
abstract protected void startContent(Canvas canvas);//绘制图表内容
abstract protected void drawXaxis(Canvas canvas);//绘制X轴
abstract protected void drawYaxis(Canvas canvas);//绘制Y轴
接下来就看看柱状图的这三个方法的具体实现

  @Override    public void drawXaxis(Canvas canvas) {        XaxisData xaxisData=dataManager.getxData();//从管理器中取出描述X轴的实体类        int width=canvas.getWidth();        Paint paint=getPaint(xaxisData.getLineWidth(),xaxisData.getLineColor());        canvas.drawLine(originPoint.x,originPoint.y,width,originPoint.y,paint);//从原点开始绘制一条直线作为X轴        Paint textpaint=getPaint(3,xaxisData.getLineColor());        textpaint.setTextSize(xaxisData.getTextsize());        List<Integer> xvaluesRelaticeX=getXvaluesRelativeX(xaxisData,canvas,textpaint);//取得每个柱状图中心点的X坐标          //接下来是绘制每个柱状图在X轴上的描述,就是“1月”,“2月”。。。那些文字描述        Paint rectPaint=new Paint();        rectPaint.setStrokeJoin(Paint.Join.ROUND);        rectPaint.setTextSize(xaxisData.getTextsize());        for(int i=0;i<xvaluesRelaticeX.size();i++){        //先绘制一个圆角矩形,再绘制文字            textpaint.setColor(xaxisData.getXdataList().get(i).getColor());            rectPaint.setColor(xaxisData.getXdataList().get(i).getBackgroundColor());         //   矩形两边留出10,作为矩形的padding            int left=xvaluesRelaticeX.get(i)-10;           //头部偏移20是矩形和X轴之间留出空隙            int top=originPoint.y+20;            int right= (int) (xvaluesRelaticeX.get(i)+textpaint.measureText(xaxisData.getXdataList().get(i).getText())+10);            int bottom=top+xaxisData.getTextsize()+15;            canvas.drawRoundRect(new RectF(left,top,right,bottom),10,10,rectPaint);             //文字居中Y坐标计算参考http://blog.csdn.net/doctorzhong/article/details/53079511            int centerY= (int) ((top+bottom)/2-(textpaint.ascent()+textpaint.descent())/2);            canvas.drawText(xaxisData.getXdataList().get(i).getText(),xvaluesRelaticeX.get(i),centerY,textpaint);        }    }

Y轴的绘制函数

 @Override    public void drawYaxis(Canvas canvas) {        int rangNum=dataManager.getRangeNum();     //获取Y轴要分成几段        int maxValue=dataManager.getMaxValues();   //Y轴能表示的最大数据            int yaxisLength=getYaxisLength();         //Y轴的长度        Paint yaxisLinePait=getPaint(dataManager.getYaxisLineWidth(),dataManager.getYaxisLineColor());        canvas.drawLine(originPoint.x,originPoint.y,originPoint.x,originPoint.y-yaxisLength-30,yaxisLinePait);//绘制Y轴        Paint paint=getPaint(20, Color.GRAY);         int rangeHeight=yaxisLength/rangNum; //计算Y轴分段后每一段的高度         int rangeValues=maxValue/rangNum;    //计算每一段表示的数值大小           yaxisLinePait.setTextSize(dataManager.getYaxisTextsize());        yaxisLinePait.setColor(dataManager.getYaxisTextColor());        int xaxisLength=getXaxisLength(canvas);        Paint xuxianPaint=new Paint();//绘制虚线的画笔        xuxianPaint.setColor(Color.GRAY);        xuxianPaint.setStyle(Paint.Style.STROKE);//一定要设置这个属性,不然绘制不出虚线        for(int i=0;i<=rangNum;i++){              int yvalues=i*rangeValues;              int yaxis=i*rangeHeight;              int textwidth= (int) yaxisLinePait.measureText(yvalues+"");              int x=originPoint.x-textwidth-10;              int y=originPoint.y-yaxis;              canvas.drawText(yvalues+"",x,y,yaxisLinePait);               if(i!=0){                   Path path = new Path();                   path.moveTo(originPoint.x, y);                   path.lineTo(originPoint.x+xaxisLength,y);                   PathEffect effects = new DashPathEffect(new float[]{5,5},5);                   xuxianPaint.setPathEffect(effects);                   canvas.drawPath(path, xuxianPaint);               }          }    }

最后是绘制图表的内容,就是那些柱状矩形,提示的泡泡

  @Override    public void startContent(Canvas canvas) {           allRectangel.clear();        List<YaxisData> ydataSet=dataManager.getyDataSet();//获取Y轴数据集合        List<Integer> xrelativeValue=getXvaluesRelativeCenterX(dataManager.getxData(),canvas);//获取每个柱状图中心点的坐标        for(int i=0;i<ydataSet.size();i++){            YaxisData yaxisData=ydataSet.get(i);            List<Integer> yrelativeValus=getYvaluesRelativeHeight(ydataSet.get(i));    //获取某个种类每个Y轴坐标对应的高度            Paint rectPaint=getPaint(5,yaxisData.getColor());            for(int j=0;j<xrelativeValue.size();j++){                int x=xrelativeValue.get(j);                int y=yrelativeValus.get(j);                int left=x-rectangleWidth/2;                int top=y;                int right=x+rectangleWidth/2;                int bottom=originPoint.y;                Rect r=new Rect(left,top,right,bottom);                canvas.drawRect(r,rectPaint);                if(i==0){                    allRectangel.add(r);//把每个最高的矩形存起来,后面有大作用,我们公司的业务定好了第一层数据就是最大的,所以取i==0时的矩形就行                }            }        }    }

到这里这个柱状图就绘制完了,还差一步,点击某个柱状图的时候,矩形顶部出现该柱状图详情数据的泡泡
先看看触摸事件这里的处理

   @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:              selectValues=drawUtil.getInformationByEventMotion(event);//获取触摸点的信息,selectValues封装了摸出到的矩形位置,该矩形的顶部坐标等信息,一会再详细介绍这个函数,如果触摸到矩形的话,selectValues就不为null,然后就是更新数据了,重新绘制View                 if(selectValues!=null){                     XaxisData xaxisData=chartDataManager.getxData();                     int size=xaxisData.getXdataList().size();                     for(int i=0;i<size;i++){                         chartDataManager.getxData().getXdataList().get(i).setColor(Color.BLACK);                         chartDataManager.getxData().getXdataList().get(i).setBackgroundColor(Color.WHITE);                     }                     chartDataManager.getxData().getXdataList().get(selectValues.getPosition()).setColor(Color.WHITE);                     chartDataManager.getxData().getXdataList().get(selectValues.getPosition()).setBackgroundColor(Color.GREEN);                     invalidate();                 }                break;        }        return false;    }

这里再介绍一下getInformationByEventMotion(event)方法

    public RectTouchInformation getInformationByEventMotion(MotionEvent event){        RectTouchInformation selectYvalues=new RectTouchInformation();        int position=0;        boolean flag=false;        //遍历上面绘制图表矩形时存起来的矩形集合,判断手指触摸的是哪个矩形        for(int i=0;i<allRectangel.size();i++){            Rect r=allRectangel.get(i);           if(r.contains((int)event.getX(),(int)event.getY())){               position=i;               flag=true;               break;           }        }        if(!flag){            return  null;        }        //获取选中的每个柱状图的信息      selectYvalues.setPosition(position);       int size=dataManager.getyDataSet().size();        List<YaxisData> allYaxisData=dataManager.getyDataSet();        List<Yvalues> selectYpoint=new ArrayList<>();        for(int i=0;i<size;i++){            YaxisData yaxisData=allYaxisData.get(i);            Yvalues yvalues=yaxisData.getYdataList().get(position);            yvalues.setDescription(yaxisData.getDescription());            selectYpoint.add(yvalues);        }    //把选中矩形顶部中心的坐标封装进selectValues      Rect rect=allRectangel.get(position);      Point point=new Point(rect.left+rect.width()/2,rect.top);        selectYvalues.setRectTopLineCenter(point);        selectYvalues.setSelectValues(selectYpoint);        return  selectYvalues;    }

接下来是看看如何把泡泡绘制出来的

public void drawSelectImage(Context context,Canvas canvas, RectTouchInformation selectRectInfor){        Point point=selectRectInfor.getRectTopLineCenter();        LinearLayout layout=new LinearLayout(context);        layout.setBackgroundColor(Color.WHITE);        layout.setOrientation(LinearLayout.VERTICAL);        int size=selectRectInfor.getSelectValues().size();        for(int i=0;i<size;i++){            Yvalues yvalues=selectRectInfor.getSelectValues().get(i);            TextView textView=new TextView(context);            textView.setText(yvalues.getDescription()+":"+yvalues.getValue());            LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);            textView.setPadding(10,2,10,2);            textView.setTextSize(10);            textView.setLayoutParams(params);            layout.addView(textView);        }       //泡泡的内容首先是把它展示在View上,然后从这个View上获取到bitmap,然后绘制这个Bitmap就行,如果还是使用绘制矩形和文字的方法来实在是太麻烦了,绘制一行一行的文字就愁死人了       Bitmap selectBitmap=convertViewToBitmap(layout);        int width=selectBitmap.getWidth();        int height=selectBitmap.getHeight();        int x=point.x-width/2;        int y=point.y-height-20;        Paint paint=new Paint();        paint.setAntiAlias(true);        paint.setDither(true);        paint.setColor(dataManager.getyDataSet().get(0).getColor());        paint.setStrokeJoin(Paint.Join.ROUND);        paint.setStrokeWidth(2);        paint.setStyle(Paint.Style.STROKE);        RectF rectF=new RectF(x-2,y-2,x+width+2,y+height+2);        //这里是给泡泡设置偏移量,以防泡泡过长超出控件了        if(rectF.left<originPoint.x){            int offset= (int) (originPoint.x-rectF.left+30);            x+=offset;            rectF.left=rectF.left+offset;            rectF.right=rectF.right+offset;        }else if(rectF.right>canvas.getWidth()){            int offset= (int) (rectF.right-canvas.getWidth()+30);            x-=offset;            rectF.left=rectF.left-offset;            rectF.right=rectF.right-offset;        }        //最后是绘制出指示箭头        canvas.drawRoundRect(rectF,10,10,paint);        canvas.drawLine(point.x,point.y,point.x-10,rectF.bottom,paint);        canvas.drawLine(point.x,point.y,point.x+10,rectF.bottom,paint);        paint.setColor(Color.WHITE);        canvas.drawLine(point.x,rectF.bottom,point.x-10,rectF.bottom,paint);        canvas.drawLine(point.x,rectF.bottom,point.x+10,rectF.bottom,paint);        canvas.drawBitmap(selectBitmap,x,y,new Paint());    }
原创粉丝点击