Custom view of Limit Line in MPAndroidChart

回眸只為那壹抹淺笑 提交于 2019-12-17 16:29:16

问题


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

I see few solutions for that:

  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?

Perhaps someone faced that problem. Please share your experience.


EDIT: latest partial solution

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

General layout of screen as follows:

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

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

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

The next step is to add custom layout at those coordinates (x, y)

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

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


EDIT 2: added custom view over chart but can't find proper location due to scroll view

Now the situation looks like that :

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

回答1:


<ScrollView>

    <LinearLayout/>

    <FrameLayout>

        <Chart/>
        <TextView/>

    <FrameLauyout>

</ScrollView>

Use ViewPortHandler to get offset of chart

    float offsetTop = mChart.getViewPortHandler().offsetTop();
    float offsetLeft = mChart.getViewPortHandler().offsetLeft();
    float offsetRight = mChart.getViewPortHandler().offsetRight();
    float chartHeight = mChart.getViewPortHandler().contentHeight();



回答2:


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

}

`

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



来源:https://stackoverflow.com/questions/36083802/custom-view-of-limit-line-in-mpandroidchart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!