android MarkerView在图表上的最后一个点处退出图表

ezykj2lf  于 2023-03-06  发布在  Android
关注(0)|答案(8)|浏览(142)

我正在使用MarkerView类来显示图表中的标记视图。我创建的标记视图布局包含两个文本视图,一个在另一个的下面。
我面临的问题是图表上最后一个点的标记视图一半在图表内,一半在图表外。下面两张图清楚地说明了这个问题:
第一个图像显示了图表中心点的标记视图,显示没有任何问题:

第二个图像(如下所示)显示图表最后一个点的标记视图,该点位于图表内的一半。

如何调整此标记视图,使其显示在图表区域中。
维客没有声明标记视图的任何自定义设置。是否还有其他自定义设置?
另外,在多折线图的情况下,如果我只点击其中一个折线点,标记视图就不会出现问题。但是如果我点击另一条折线上的任何一个点,应用程序就会失败。知道为什么会发生这种情况吗?
markerview类的代码如下所示:

public class TooltipView extends MarkerView {

private BaseGraphMetadata mBaseGraphMetadata;

private TextView mTooltipDate, mTooltipValue;

public TooltipView(Context context, int layoutResource, BaseGraphMetadata baseGraphMetadata) {
    super(context, layoutResource);
    mTooltipDate = (TextView)findViewById(R.id.tooltip_date);
    mTooltipValue = (TextView)findViewById(R.id.tooltip_value);
    mBaseGraphMetadata = baseGraphMetadata;
}

@Override
public void refreshContent(Entry entry, int i) {
    List<DrillDownInfo> drillDownInfoList = (List<DrillDownInfo>) entry.getData();
    DrillDownInfo drillDownInfo = drillDownInfoList.get(i);
    Map<String, String> group = drillDownInfo.getGroupByNameVsGroupByValue();
    Iterator iterator = group.entrySet().iterator();
    while (iterator.hasNext()) {
        Map.Entry pair = (Map.Entry)iterator.next();
        if(pair.getKey()!=null && pair.getValue()!=null) {
            String key = (String) pair.getKey();
            key = key.toUpperCase();
            Double value = Double.parseDouble((String) pair.getValue());
            String formattedValue = mBaseGraphMetadata.getDataFormatter().getFormattedValue(value);
            mTooltipDate.setText(key + " : " + formattedValue);
        }
        iterator.remove();
    }
    mTooltipValue.setText(String.valueOf("VALUE : "+entry.getVal()));
}

@Override
public int getXOffset() {
    return -(getWidth() / 2);
}

@Override
public int getYOffset() {
    return -getHeight();
}
}
9nvpjoqh

9nvpjoqh1#

我已经找到了一个简单的解决这个问题的方法。你需要在你的自定义标记视图中设置图表如下:

setChartView(chart);

..并覆盖绘制方法,如下所示:

@Override
public void draw(Canvas canvas, float posX, float posY) {
    super.draw(canvas, posX, posY);
    getOffsetForDrawingAtPoint(posX, posY);
}
n53p2ov0

n53p2ov02#

android:clipChildren="false"
android:clipToPadding="false"

我没有工作,我结束了创建3个不同的绘图。根据条目索引,我使用一个或另一个。而且,为了保持箭头居中,XOffset相应地改变。我猜这是一个非常具体的解决方案,但这个想法是可导出的

@Override
  public void refreshContent(Entry e, int dataSetIndex) {
    if (e.getXIndex() < 4) {
      xOffsetMultiplier = 3.2f;
      tvContent.setBackgroundResource(R.drawable.stats_marker_left_side);
    } else if (e.getXIndex() > mTimestamps.length - 6) {
      //timestamps is an array containing xValues timestamps
      xOffsetMultiplier = 1.12f;
      tvContent.setBackgroundResource(R.drawable.stats_marker_right_side);
    } else {
      xOffsetMultiplier = 2;
      tvContent.setBackgroundResource(R.drawable.stats_marker);
    }

    tvContent.setText(createMarkerViewText(e));
  }

  @Override
  public int getXOffset() {
    // this will center the marker-view horizontally
    return (int) -(getWidth() / xOffsetMultiplier);
  }

这就是结果
第一个c0d1x第一个c1d1x第一个c2d1x
可绘制对象是从MPEandroidChart示例中复制的,转换为9.patch并根据我的需要进行了调整。
第一个第三个第一个第四个第一个第五个第一个

slhcrj9b

slhcrj9b3#

有点晚了,但这里是我对这个问题的简单解决方案。
您需要Override自定义MarkerViewdraw方法。
你只需要控制你的posx不会从你的一个边界关闭(从右边的0到位置取决于你的屏幕大小,作为一个例子300为我自己的屏幕)。
举个简单的例子:

@Override
        public void draw(Canvas canvas, float posx, float posy)
        {
            // take offsets into consideration
            posx += getXOffset();
            posy=0;

            // AVOID OFFSCREEN
            if(posx<45)
                posx=45;
            if(posx>265)
                posx=265;

            // translate to the correct position and draw
            canvas.translate(posx, posy);
            draw(canvas);
            canvas.translate(-posx, -posy);
        }

在这里,我可以控制我的x位置,同时确保标记始终保持在图形的顶部(如果不需要,请使用p osy += getYOffset();

3hvapo4f

3hvapo4f4#

只要在MarkerView中加入一些逻辑,如果最后一个值被突出显示,getXOffset()方法应该返回不同的结果。
返回的内容在refreshContent(...)方法中计算。
此外,您还可以查看以下xml属性:

android:clipChildren="false"
android:clipToPadding="false"

应该为图表视图设置。

wko9yo5t

wko9yo5t5#

我遇到了同样的问题,我通过创建自己的customMarkerview类来纠正它,特别是下面的方法:

@Override
public int getXOffset(float xpos) {

    // this will center the marker-view horizontally
   int min_offset = 50;
    if (xpos < min_offset)
        return 0;

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    DisplayMetrics metrics = new DisplayMetrics();
    wm.getDefaultDisplay().getMetrics(metrics);
    //For right hand side
    if (metrics.widthPixels - xpos < min_offset)
        return -getWidth();
            //For left hand side
    else if (metrics.widthPixels - xpos < 0)
        return -getWidth();
    return -(getWidth() / 2);
}
mzmfm0qo

mzmfm0qo6#

试试这个:

private val uiScreenWidth = resources.displayMetrics.widthPixels

    override fun draw(canvas: Canvas?, posX: Float, posY: Float) {
        var newPosX = posX
        if (uiScreenWidth - posX < width) {
            newPosX -= width
        }
        super.draw(canvas, newPosX, posY)
    }
hk8txs48

hk8txs487#

您可以通过添加chart.setDragOffsetX(50);来纠正此问题。这将在x轴上添加填充。从而为要显示的标记视图提供空间。

guicsvcw

guicsvcw8#

最好的答案在于库本身。检查MarkerView中的getOffsetForDrawingAtPoint()方法。它定义了计算偏移量的完美方法。使用该逻辑并在自定义标记的onDraw方法中使用如下:

@Override
    public void draw(Canvas canvas, float posX, float posY) {
        // take offsets into consideration
        int lineChartWidth = 0;
        float offsetX = getOffset().getX();
        posY=0;//fix at top
        float width = getWidth();

        if(lineChart != null) {
            lineChartWidth = lineChart.getWidth();
        }
        if(posX + offsetX < 0) {
            offsetX = - posX;
        } else if(posX + width + offsetX > lineChartWidth) {
            offsetX = lineChartWidth - posX - width;
        }
        posX += offsetX;
        // translate to the correct position and draw
        canvas.translate(posX, posY);
        draw(canvas);
        canvas.translate(-posX, -posY);
    }

相关问题