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

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

慢慢看源码吧~

  • 关于AChartEnging的事件,使用这个组件时大致有一下几个设置:
    renderer.setPanEnabled(true, false);//表盘移动

    renderer.setPanEnabled(true, false);//表盘缩放

    renderer.setClickEnabled(true);//是否可点击

    renderer.setSelectableBuffer(20);//点击区域大小

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

 

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

 

class ChartViewClick implements View.OnClickListener {

    @Override
    public void onClick(View v) {
      GraphicalView graphicalView = (GraphicalView) v;
     
      //获取当前点击点
      SeriesSelection seriesSelection = graphicalView.getCurrentSeriesAndPoint();
      
      if (seriesSelection == null) {
        return;
      }
      int x = (int) seriesSelection.getXValue();
      Toast.makeText(context, "第几个点" + x, Toast.LENGTH_SHORT).show();
    }
  }

 

  public SeriesSelection getCurrentSeriesAndPoint() {
    return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));
  }

 

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

 

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
      // save the x and y so they can be used in the click and long press
      // listeners
      oldX = event.getX();
      oldY = event.getY();
    }
    if (mRenderer != null && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {
      if (mTouchHandler.handleTouch(event)) {
        return true;
      }
    }
    return super.onTouchEvent(event);
  }
 

 

 

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

 

public SeriesSelection getSeriesAndPointForScreenCoordinate(final Point screenPoint) {
    if (clickableAreas != null)
      for (int seriesIndex = clickableAreas.size() - 1; seriesIndex >= 0; seriesIndex--) {
        // series 0 is drawn first. Then series 1 is drawn on top, and series 2
        // on top of that.
        // we want to know what the user clicked on, so traverse them in the
        // order they appear on the screen.
        int pointIndex = 0;
        if (clickableAreas.get(seriesIndex) != null) {
          RectF rectangle;
          for (ClickableArea area : clickableAreas.get(seriesIndex)) {
            rectangle = area.getRect();
            if (rectangle != null && rectangle.contains(screenPoint.getX(), screenPoint.getY())) {
              return new SeriesSelection(seriesIndex, pointIndex, area.getX(), area.getY());
            }
            pointIndex++;
          }
        }
      }
    return super.getSeriesAndPointForScreenCoordinate(screenPoint);
  }

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

 

... 
 clickableAreas = new HashMap<Integer, List<ClickableArea>>();
 
//sLength = series.size();遍历几条线
    for (int i = 0; i < sLength; i++) {
...

    //遍历线中的每个点
    for (Entry<Double, Double> value : range.entrySet()) {
    ...
      values.add(value.getKey());
        values.add(value.getValue());
     //把坐标值转换成屏幕中像素坐标
        if (!isNullValue(yValue)) {
          points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));
          points.add((float) (bottom - yPixelsPerUnit[scale] * (yValue - minY[scale])));
     ...

     //关键的来了,生成点击区域
     ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(
                MathHelper.getFloats(points), MathHelper.getDoubles(values), yAxisValue, i,
                startIndex);
     ...
    }
      clickableAreas.put(i, clickableArea); //clickableAreas是一个域,保存所有可点击系列
}
}
 

 

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

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

 

 

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

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(achartengine)