MPAndroidChart中极限线的自定义视图 [英] Custom view of Limit Line in MPAndroidChart

查看:78
本文介绍了MPAndroidChart中极限线的自定义视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以用自定义布局替换LimitLine?所以看起来像这样:

Is it possible to replace LimitLine with custom layout? So it looks something like this:

我看到的解决方案很少:

I see few solutions for that:

  1. 也许库中有这样的用于自定义的方法,有没有?
  2. 获取存储值的TextView坐标,并在该位置添加自定义布局.但是我怎么能到达这个TextView?
  1. Perhaps there're methods inside library for customizations like this, are there any?
  2. Get coordinates of TextView where the value is stored and add custom layout on that place. But how can I reach this TextView?

也许有人遇到了这个问题.请分享您的经验.

最新的部分解决方案

在长期寻找解决方案之后,我想出了通过极限线的坐标以编程方式添加自定义视图的方法.

After long searching of solution I came up to adding custom view programmatically by coordinates of Limit Line.

屏幕的总体布局如下:

坐标的计算非常简单.从图表坐标和Y可以知道X:

Coordinates are calculated pretty straightforward. X is known from Chart coordinates and Y:

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

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

因此,在这一点上,我基本上知道我需要的职位了.尽管由于父ScrollView我不确定这是否正确.

So at this point I basically know the position I need. Although I'm not sure it's right due to parent ScrollView.

下一步是在这些坐标(x, y)

这是新的问题.我试图将视图添加到顶部RelativeLayout.它已添加,但不会与ScrollView一起移动.因此,需要将其准确地添加到图表上.看看我是如何做到这一点的:

And here comes the new problem. I tried to add view to top RelativeLayout. It is added but it doesn't move together with ScrollView. Therefore its needed to add that view exactly on Chart. Look how I tried to achieve this:

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的父级布局,然后在此处填充我的自定义布局.但是如何?

Perhaps I should reach the parent layout of Chart and inflate my custom layout there. But how?

在图表上添加了自定义视图,但由于滚动视图而找不到正确的位置

现在情况看起来像这样:

Now the situation looks like that :

也许我在计算中出了点问题.但是,至少View从未改变过正确的位置,而是以新的价值改变了自己的立场.

Perhaps I'm somewhere wrong in calculations. But at least that View changes its position with the new value although it never hits at right coordinations.

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();
        }
    });
}

推荐答案

这不是一个好方法.我通过扩展实际绘制标签的YAxisRenderer.java文件来完成此操作.它们不是视图,而是在画布上绘制的.这是我的标签代码:

This is not a good way of doing it. I've done it by extending the YAxisRenderer.java file where the labels are actually drawn. They are not views, they are drawn on canvas. Here is my code for the labels:

`

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值转换为像素.

Please note that you must use mTrans.pointValuesToPixel(pts) to convert your Y values to pixels.

这篇关于MPAndroidChart中极限线的自定义视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆