AChartEngine (一) 事件处理 添加坐标/标签 点击效果

来源:互联网 发布:移民 知乎 编辑:程序博客网 时间:2024/04/30 16:45

由于项目需要,需要对图表中的label设置点击事件,可是google给的包没有实现这功能。看来得靠自己了!

慢慢看源码吧~

  • 关于AChartEnging的事件,使用这个组件时大致有一下几个设置:
Java代码  收藏代码
  1. renderer.setPanEnabled(truefalse);//表盘移动  
  2.   
  3. renderer.setPanEnabled(truefalse);//表盘缩放  
  4.   
  5. renderer.setClickEnabled(true);//是否可点击  
  6.   
  7. renderer.setSelectableBuffer(20);//点击区域大小  

用起来是很方便的,但在源码中实现还是比较复杂的,特别是移动和缩放功能,先暂不讨论。

 

下面是在XYChart中点击某个点,触发事件的使用方法:

 

Java代码  收藏代码
  1. class ChartViewClick implements View.OnClickListener {  
  2.   
  3.     @Override  
  4.     public void onClick(View v) {  
  5.       GraphicalView graphicalView = (GraphicalView) v;  
  6.        
  7.       //获取当前点击点  
  8.       SeriesSelection seriesSelection = graphicalView.getCurrentSeriesAndPoint();  
  9.         
  10.       if (seriesSelection == null) {  
  11.         return;  
  12.       }  
  13.       int x = (int) seriesSelection.getXValue();  
  14.       Toast.makeText(context, "第几个点" + x, Toast.LENGTH_SHORT).show();  
  15.     }  
  16.   }  

 

Java代码  收藏代码
  1. public SeriesSelection getCurrentSeriesAndPoint() {  
  2.   return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));  
  3. }  

 

 oldx,oldy应该就是触控事件中获取的

 

Java代码  收藏代码
  1. @Override  
  2. public boolean onTouchEvent(MotionEvent event) {  
  3.   if (event.getAction() == MotionEvent.ACTION_DOWN) {  
  4.     // save the x and y so they can be used in the click and long press  
  5.     // listeners  
  6.     oldX = event.getX();  
  7.     oldY = event.getY();  
  8.   }  
  9.   if (mRenderer != null && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {  
  10.     if (mTouchHandler.handleTouch(event)) {  
  11.       return true;  
  12.     }  
  13.   }  
  14.   return super.onTouchEvent(event);  
  15. }  
 

 

 

 查看源码,发现getCurrentSeriesAndPoint()在抽象类AbstractChart.java中,XYChart重写了:

 

Java代码  收藏代码
  1. public SeriesSelection getSeriesAndPointForScreenCoordinate(final Point screenPoint) {  
  2.     if (clickableAreas != null)  
  3.       for (int seriesIndex = clickableAreas.size() - 1; seriesIndex >= 0; seriesIndex--) {  
  4.         // series 0 is drawn first. Then series 1 is drawn on top, and series 2  
  5.         // on top of that.  
  6.         // we want to know what the user clicked on, so traverse them in the  
  7.         // order they appear on the screen.  
  8.         int pointIndex = 0;  
  9.         if (clickableAreas.get(seriesIndex) != null) {  
  10.           RectF rectangle;  
  11.           for (ClickableArea area : clickableAreas.get(seriesIndex)) {  
  12.             rectangle = area.getRect();  
  13.             if (rectangle != null && rectangle.contains(screenPoint.getX(), screenPoint.getY())) {  
  14.               return new SeriesSelection(seriesIndex, pointIndex, area.getX(), area.getY());  
  15.             }  
  16.             pointIndex++;  
  17.           }  
  18.         }  
  19.       }  
  20.     return super.getSeriesAndPointForScreenCoordinate(screenPoint);  
  21.   }  

 看来,关键在于clickableAreas的构造了。这在XYChart的onDraw方法中,差不多有100行

 

Java代码  收藏代码
  1. ...   
  2.  clickableAreas = new HashMap<Integer, List<ClickableArea>>();  
  3.    
  4. //sLength = series.size();遍历几条线  
  5.     for (int i = 0; i < sLength; i++) {  
  6. ...  
  7.   
  8.     //遍历线中的每个点  
  9.     for (Entry<Double, Double> value : range.entrySet()) {  
  10.     ...  
  11.       values.add(value.getKey());  
  12.         values.add(value.getValue());  
  13.      //把坐标值转换成屏幕中像素坐标  
  14.         if (!isNullValue(yValue)) {  
  15.           points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));  
  16.           points.add((float) (bottom - yPixelsPerUnit[scale] * (yValue - minY[scale])));  
  17.      ...  
  18.   
  19.      //关键的来了,生成点击区域  
  20.      ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(  
  21.                 MathHelper.getFloats(points), MathHelper.getDoubles(values), yAxisValue, i,  
  22.                 startIndex);  
  23.      ...  
  24.     }  
  25.       clickableAreas.put(i, clickableArea); //clickableAreas是一个域,保存所有可点击系列  
  26. }  
  27. }  
 

 

查看上面clickableAreasForPoints方法,发现其实就是在坐标像素点处建一个变长为render.getSelectableBuffer()的矩形。

由此很容易想到解决方案:

 

 

  • 在x轴标签处创建相应的可点击矩形,添加到clickableAreas中即可

 

这样解决的方法就有很多了,比较简单的方法就是在y轴最小值下面添加一项。。。。。(由于我的图标不用提供缩放和移动,并且最小值固定为0),只要 vYalues = -5d,添加一项即可。

原创粉丝点击