MPAndroidChart中限制线的自定义视图

11
是否可以用自定义布局替换LimitLine?这样它看起来像这样:enter image description here。我看到了一些解决方案:
  1. 也许库中有类似这样的自定义方法,有吗?
  2. 获取存储值的TextView的坐标,并在该位置添加自定义布局。但是我怎样可以找到这个TextView呢?
或许有人遇到过这个问题,请分享你的经验。
编辑:最新部分解决方案

经过长时间的寻找解决方案,我得出了通过Limit Line坐标添加自定义视图的结论。

屏幕的通用布局如下:

enter image description here

坐标计算非常简单。X从图表坐标中已知且Y为:

Y = ((max - lastValue) * height) / ((max + min) + y)

因此,我基本上知道我需要的位置。虽然由于父级ScrollView,我不确定它是否正确。

下一步是在这些坐标(x,y)处添加自定义布局。

enter image description here

这里出现了新的问题。我试图将视图添加到顶部的RelativeLayout中。它被添加了,但它不会随着ScrollView一起移动。因此,需要将该视图添加到图表上。看看我如何实现它:

private void addCustomLayoutOnLimitLine(final double lastValue) {

    mChart.post(new Runnable() { //check location when view is created
        public void run() {
            int[] chartLocationOnScreen = new int[2];
            mChart.getLocationOnScreen(chartLocationOnScreen);

            int x = chartLocationOnScreen[0];
            int y = chartLocationOnScreen[1];

            int width = mChart.getWidth();
            int height = mChart.getHeight();


            double max = mChart.getYMax();
            double min = mChart.getYMin();

            int limitXPoint = x + width;
            int limitYPoint = (int) ((((max - lastValue) * height) / (max + min))+ y);



            LayoutInflater inflater = (LayoutInflater)   getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            RelativeLayout rlValue = (RelativeLayout) inflater.inflate(R.layout.item_chart_value, null);
            TextView tvValue = (TextView) rlValue.findViewById(R.id.tv_value);
            tvValue.setText(String.valueOf(lastValue));

            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(50, 50);
            params.leftMargin = limitXPoint - 100;
            params.topMargin = limitYPoint;
            mChart.addView(rlValue, params); //this doesn't seem to be working
            rlValue.bringToFront();
        }
    });
}

也许我应该到Chart的父布局中去查找并填充自定义布局。但是如何做到呢


编辑2:在图表上添加了自定义视图,但由于滚动视图找不到合适的位置

现在情况看起来像这样:

enter image description here

也许我的计算有误。但至少该视图随着新值而改变其位置,尽管它从未到达正确的坐标。

private void addCustomLayoutOnLimitLine() {
    if (mChart == null){
        return;
    }

    mChart.post(new Runnable() { //check location when view is created
        public void run() {
            int[] chartLocationOnScreen = new int[2];
            mChart.getLocationOnScreen(chartLocationOnScreen);

            int xChart = chartLocationOnScreen[0];
            int yChart = chartLocationOnScreen[1];

            int chartWidth = mChart.getWidth();
            int chartHeight = mChart.getHeight();

            int rootWidth = rlSvContent.getWidth();
            int rootHeight = rlSvContent.getHeight(); //this is height of ScrollView

            int infoWidth = llInfoWrapper.getWidth(); //width of info panel ABOVE chart
            int infoHeight = llInfoWrapper.getHeight();

            double lastValue = mSingleAsset.getGraph().get(mSingleAsset.getGraph().size() - 1).getValue();
            double maxValue = mChart.getYMax();
            double minValue = mChart.getYMin();

            int limitXPoint = (rootWidth - chartWidth) / 2 + chartWidth;
            int limitYPoint = (int) ((maxValue - lastValue) * chartHeight/(maxValue - minValue)) + yChart;

            tvCustomValue.setText(SingleAsset.round((float) lastValue, 2).toString()); //display last value on custom view

            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.leftMargin = limitXPoint - xChart - 50; //move custom view. xChart = right margin value and 50 is taken to count values bar to the right of chart
            params.topMargin = limitYPoint;
            rlCustomValue.setLayoutParams(params);
            rlCustomValue.bringToFront();
            rlCustomValue.invalidate();
        }
    });
}
2个回答

4
这并不是一个好的做法。我通过扩展YAxisRenderer.java文件来完成它,标签实际上是在画布上绘制的,而不是视图。这是我的标签代码:
protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) {

    // draw labels
    for (int i = 0; i < mYAxis.mEntryCount; i++) {

        String text = mYAxis.getFormattedLabel(i);

        if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1)
            return;

        c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint);
    }

    // limitline labels

    List<LimitLine> limitLines = mYAxis.getLimitLines();
    float[] pts = new float[2];
    for (LimitLine l : limitLines) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(l.getTextColor());

        Paint textPaint = mAxisLabelPaint;
        textPaint.setColor(l.getLineLabelTextColor());
        textPaint.setTextSize(mAxisLabelPaint.getTextSize());
        textPaint.setPathEffect(null);
        textPaint.setTypeface(l.getTypeface());
        textPaint.setStrokeWidth(0.5f);
        textPaint.setStyle(l.getTextStyle());

        pts[1] = l.getLimit();
        mTrans.pointValuesToPixel(pts);
        float paddingVert = Utils.convertDpToPixel(3);
        float paddingHoriz = Utils.convertDpToPixel(5);
        float height = Utils.calcTextHeight(textPaint, l.getLabel());
        float width = Utils.calcTextWidth(textPaint, l.getLabel());
        float posY = pts[1] + height / 2;

        c.drawRect(fixedPosition - paddingHoriz, posY - height - paddingVert, fixedPosition + width + paddingHoriz*2, posY + paddingVert, paint);
        c.drawText(l.getLabel(), fixedPosition, posY, textPaint);
    }

}

请注意,您必须使用mTrans.pointValuesToPixel(pts)将您的Y值转换为像素。

谢谢回复。你能展示一下这个方法的使用示例吗? - AnZ
2
我发布的代码是对mpandroidchart本身的修改。在修改后,您只需在应用程序中添加限制线,此代码将为您添加的每个限制线放置一个标签,并使用与您设置的限制线颜色相同的颜色。创建您的线:ll = new LimitLine(limit, label); ll.setLineColor(...); yourChart.getAxisRight().addLimitLine(ll); - Stefan Bushev

4
<ScrollView>

    <LinearLayout/>

    <FrameLayout>

        <Chart/>
        <TextView/>

    <FrameLauyout>

</ScrollView>

使用ViewPortHandler获取图表的偏移量。
    float offsetTop = mChart.getViewPortHandler().offsetTop();
    float offsetLeft = mChart.getViewPortHandler().offsetLeft();
    float offsetRight = mChart.getViewPortHandler().offsetRight();
    float chartHeight = mChart.getViewPortHandler().contentHeight();

谢谢,这是有用的信息。将有助于将视图定位在精确的位置End\Right。但是Top\Down分配的问题仍然存在。 - AnZ
为什么?你可以获取偏移量的顶部和底部。 - tiny sunlight
我稍后会尝试并留下反馈。 - AnZ
offsetTop() 返回0,因为图表被包含在父布局中。不管怎样,你的回答很有帮助,赏金归你了。 - AnZ
浮点数 chartHeight = mChart.getViewPortHandler().contentHeight(); 而不是 mChart.getHeight()。同时,mChart.getHeight() - mChart.getViewPortHandler().offsetBottom()。 - tiny sunlight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接