android - 优化 Androidplot

标签 android graph androidplot

Androidplot (androidplot.com) 网站/论坛似乎已关闭,所以我会尝试在这里提出这个问题。

我有多点触控缩放和滚动。与 http://mlepicki.com/2012/03/androidplot-multitouch-zoom-scroll/ 类似的代码除了我有一个条形图。然而,对于 100 个数据点,它有明显的滞后。即使有 10 个柱线也只是显示。听起来像是它的绘图/计算/等等所有的酒吧。

关于如何优化它的任何想法?

我无法使用硬件渲染,因为我想支持 Android 2.1,但库不支持它(它中断了)。

最佳答案

我制作了一个自定义渲染器来解决我的滞后问题。似乎顺畅了许多。此代码基于版本 0.5。不知道它是否适用于 v0.51。

import android.graphics.*;
import com.androidplot.exception.PlotRenderException;
import com.androidplot.series.XYSeries;
import com.androidplot.util.ValPixConverter;
import com.androidplot.xy.BarFormatter;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeriesRenderer;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Renders a point as a Bar
 */
public class OptimisedBarRenderer extends XYSeriesRenderer<BarFormatter> {

    private BarWidthStyle style = BarWidthStyle.FIXED_WIDTH;
    private float barWidth = 5;

    public OptimisedBarRenderer(XYPlot plot) {
        super(plot);
    }

    /**
     * Sets the width of the bars draw.
     * @param barWidth
     */
    public void setBarWidth(float barWidth) {
        this.barWidth = barWidth;
    }

    private final TreeMap<Number, XYSeries> tempSeriesMap = new TreeMap<Number, XYSeries>();

    @Override
    public void onRender(Canvas canvas, RectF plotArea) throws PlotRenderException {
        int longest = getLongestSeries();
        if(longest == 0) {
            return;  // no data, nothing to do.
        }
        tempSeriesMap.clear();

        for(int i = 0; i < longest; i++) {
            tempSeriesMap.clear();
            List<XYSeries> seriesList = getPlot().getSeriesListForRenderer(this.getClass());
            for(XYSeries series : seriesList) {
                if(i < series.size()) {
                    tempSeriesMap.put(series.getY(i), series);
                }
            }
            drawBars(canvas, plotArea, tempSeriesMap, i);
        }
    }

    @Override
    public void doDrawLegendIcon(Canvas canvas, RectF rect, BarFormatter formatter) {
        canvas.drawRect(rect, formatter.getFillPaint());
        canvas.drawRect(rect, formatter.getBorderPaint());
    }

    private int getLongestSeries() {
        int longest = 0;
        List<XYSeries> seriesList = getPlot().getSeriesListForRenderer(this.getClass());

        if(seriesList == null)
            return 0;

        for(XYSeries series :seriesList) {
            int seriesSize = series.size();
            if(seriesSize > longest) {
                longest = seriesSize;
            }
        }
        return longest;
    }

    private void drawBars(Canvas canvas, RectF plotArea, TreeMap<Number, XYSeries> seriesMap, int x) {
//        Paint p = new Paint();
//        p.setColor(Color.RED);

        Object[] oa = seriesMap.entrySet().toArray();
        Map.Entry<Number, XYSeries> entry;
        Number yVal = null;
        Number xVal = null;

        float halfWidth = barWidth * 0.5f;

        for(int i = oa.length-1; i >= 0; i--) {
            entry = (Map.Entry<Number, XYSeries>) oa[i];
            XYSeries tempEntry = entry.getValue();

            if(tempEntry != null) {
                yVal = tempEntry.getY(x);
                xVal = tempEntry.getX(x);

                if (yVal != null && xVal != null) {  // make sure there's a real value to draw
                    switch (style) {
                        case FIXED_WIDTH:
                            float pixX = ValPixConverter.valToPix(xVal.doubleValue(), getPlot().getCalculatedMinX().doubleValue(), getPlot().getCalculatedMaxX().doubleValue(), plotArea.width(), false) + plotArea.left;

                            float left = pixX - halfWidth;
                            float right = pixX + halfWidth;

                            boolean offScreen = left > plotArea.right || right < plotArea.left;

                            if(!offScreen){
                                float pixY = ValPixConverter.valToPix(yVal.doubleValue(), getPlot().getCalculatedMinY().doubleValue(), getPlot().getCalculatedMaxY().doubleValue(), plotArea.height(), true) + plotArea.top;

                                BarFormatter formatter = getFormatter(tempEntry);
                                if(Math.abs (left - right) > 1f){//Don't draw as it will be hidden anyway.
                                    canvas.drawRect(left, pixY, right, plotArea.bottom, formatter.getFillPaint());
                                }
                                canvas.drawRect(left, pixY, right, plotArea.bottom, formatter.getBorderPaint());

                            }
                            break;
                        default:
                            throw new UnsupportedOperationException("Not yet implemented.");
                    }
                }
            }
        }
    }
}

关于android - 优化 Androidplot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10132885/

相关文章:

java - AndroidPlot 和 RectRegion 行为

android - Kotlin 根据内部列表中的参数对列表列表进行排序

algorithm - 最小化动态 'metric' 的生成树

graph - 如何使用 Julia 图阻止网格自动缩放

jquery - flot 根据时间戳显示 flot 中的日期

android - 如何使用 AndroidPlot 绘制圆角(平滑)线

android - 从 android 上的 IP 摄像机接收视频流

java - Android 分水岭 OpenCV

android - 语言资源在单独的 APK 中?

Android 在 x 角度上绘制固定值