获取点在AndroidPlot中的正确位置

亦余心之所善兮,虽九死其犹未悔。这篇文章主要讲述获取点在AndroidPlot中的正确位置相关的知识,希望能为你提供帮助。
我正在尝试获取我的androidPlot中值的像素位置,但无法使其正常工作。想法是将光标按特定术语放置在绘图上显示的确切点上。你们中有人遇到过类似的问题吗?
关于杰斯珀
答案我不知道是否有更好的内置解决方案,但这是一种手动方法。下面的代码将光标置于用户触摸屏幕的X坐标和绘图的第一个数据序列的相应Y坐标。

//NOTE about XYPlotZoomPan: when an OnTouchListener is set, zooming is disabled. Subclass to avoid it. mPlot.setOnTouchListener(new View.OnTouchListener(){ @Override public boolean onTouch(View v, MotionEvent me) { float touchX = me.getX(); float touchY = me.getY(); XYGraphWidget widget = mPlot.getGraphWidget(); RectF gridRect = widget.getGridRect(); if(gridRect.contains(touchX, touchY)){ //Check the touch event is in the grid XYSeries xyData = https://www.songbingjia.com/android/mPlot.getSeriesSet().iterator().next(); long targetValX = Math.round(widget.getXVal(touchX)); Log.d(TAG,"Touched at " + touchX + ", " + touchY + ". Target val X: " + targetValX); Long targetValY = null; Long prevValX = null; if(mPlot.getSeriesSet().size() > 1){ Log.w(TAG, "More than one series in plot. Using only the first one"); } for(int i = 0; i < xyData.size(); ++i){ long currValX = xyData.getX(i).longValue(); long currValY = xyData.getY(i).longValue(); //Calculate the range value of the closest domain value (assumes xyData is sorted in ascending X order) if(currValX > = targetValX){ long currDiff = currValX - targetValX; if(prevValX != null & & (targetValX - prevValX) < currDiff){ targetValY = xyData.getY(i-1).longValue(); }else{ targetValY = currValY; } break; } prevValX = currValX; } if(targetValY != null){ long maxValY = mPlot.getCalculatedMaxY().longValue(); long minValY = mPlot.getCalculatedMinY().longValue(); float pixelPosY = gridRect.top + ValPixConverter.valToPix( (double)targetValY, (double)minValY, (double)maxValY, (float)gridRect.height(), true); widget.setRangeCursorPosition(pixelPosY); widget.setDomainCursorPosition(touchX); Log.d(TAG, String.format("Domain cursor set at Y %.2f, val %.2f = %d, min-maxValY (%d, %d)", pixelPosY, widget.getRangeCursorVal(), targetValY, minValY, maxValY)); }else{ Log.w(TAG, "Couldn't find the closest range to the selected domain coordinate"); } mPlot.invalidate(); }else{ Log.d(TAG, "Touched outside the plot grid"); }return false; } });

另一答案我找到了解决方案。我的目的是找到给定像素的值(例如,通过点击绘图,我想要代表值)。因此,经过一番搜索,我发现了助手类ValPixConverter。它提供了一些适合我需求的方法。不幸的是,没有方法的文档,但是我找到了解决方法:
private float pixelToValueY(float y) { //Parameters: 1=input y-value, 2=minmal y-value that is shown,3=maximal y-value that is shown, 4=Hight of the view, 5=flip return (float) ValPixConverter.pixToVal(y, minXY.y, maxXY.y, mySimpleXYPlot.getHeight(), false); }private float pixelToValueX(float x) { //Parameters: 1=input y-value, 2=minmal y-value that is shown,3=maximal y-value that is shown, 4=Hight of the view, 5=flip return (float) ValPixConverter.pixToVal(x, minXY.x, maxXY.x, mySimpleXYPlot.getWidth(), false); }

【获取点在AndroidPlot中的正确位置】您需要另一种方式。方法valToPix()将执行此操作。然后,它与上面的代码非常相似。
另一答案更新的解决方案[我试图遵循rbarriuso的方法,但是我发现它已经过时并且过于复杂。
使用rbarriuso答案作为指导,我想到了以下内容:
private void placeMarkerOnGraph(XYPlot plot, XYSeries plotSeries, XValueMarker xMarker, YValueMarker yMarker, float touchX, float touchY) { if(plot.getRegistry().getSeriesList().contains(plotSeries)) { if (plot.getGraph().getGridRect().contains(touchX, touchY)) { int targetValX = plot.screenToSeriesX(touchX).intValue(); int targetValY = plot.screenToSeriesY(touchY).intValue(); int threshold = (int)(plot.getBounds().getHeight().intValue() * 0.1f); //How close to a trace does the user have to click to move the markers?if (plotSeries.getY(targetValX).intValue() - targetValY < threshold) { Log.w(TAG, "Touched within threshold to trace line"); xMarker.setValue(targetValX); yMarker.setValue(plotSeries.getY(targetValX).intValue()); } } else { Log.w(TAG, "Touched outside graph"); } } else { Log.w(TAG, "Plot does not contain series provided"); } }

如何运作步骤1.检查您是否确实触摸了图形内部
步骤2.从触摸线转换为屏幕图形坐标
步骤3.取X值(已转换为图形坐标)并找到其Y值
步骤4.如果您触摸得足够近,则移动标记/光标
其他提示
  • 我在我的示例中使用标记而不是光标,因为绘图可以有多少个标记没有限制,但是您只能有一个光标。
  • 此功能仅更改标记的位置,您必须选择格式化并首先将标记添加到绘图中。
  • XYSeries现在使用数字,因此请使用必要的值,例如:如果您的系列从0.0f1.0f,请使用.floatValue()
  • 除非您使用plot.redraw()
  • 阈值是要考虑缩放的绘图总高度的百分比
更高级的解决方案第一种解决方案对于不是很陡的图形来说可以正常工作,但是否则它的准确性就不高,因为它没有考虑不在用户触摸图形下方的数据点。
下面,我添加了一个更强大的解决方案,该解决方案依赖于for循环,但更加准确。其工作原理与第一个解决方案非常相似。
private void placeMarkerOnGraph(XYPlot plot, XYSeries plotSeries, XValueMarker xMarker, YValueMarker yMarker, float touchX, float touchY) { if(plot.getRegistry().getSeriesList().contains(plotSeries)) { if (plot.getGraph().getGridRect().contains(touchX, touchY)) { int targetValX = plot.screenToSeriesX(touchX).intValue(); int targetValY = plot.screenToSeriesY(touchY).intValue(); int threshold = (int)(plot.getBounds().getWidth().intValue() * 0.1f); //How close to a trace does the user have to click to move the markers? Integer closestValue = https://www.songbingjia.com/android/null; Integer xPos = null; Integer yPos = null; for(int i = targetValX - threshold; i < targetValX + threshold; i++){ //If the user touches near either end of the graph we need to make sure we don't go out of the arrays bounds if(i > 0 & & i < graphSize) { int closeness = Math.abs(Math.abs(plotSeries.getY(i).intValue() - targetValY) + Math.abs(i - targetValX)); Log.d(TAG,"Distance to nearest trace: " + closeness); if ((closestValue != null & & closeness < closestValue) || (closestValue =https://www.songbingjia.com/android/= null & & closeness < threshold)) { closestValue = closeness; xPos = i; yPos = plotSeries.getY(i).intValue(); } } }if (xPos != null) { Log.d(TAG,"Touched within threshold"); xMarker.setValue(xPos); yMarker.setValue(yPos); } else { Log.d(TAG, "Touched outside threshold"); } } else { Log.w(TAG, "Touched outside graph"); } } else { Log.w(TAG, "Plot does not contain series provided"); } }


    推荐阅读