Menu and a ContextMenu for a aChartengine chart

后端 未结 3 1007
甜味超标
甜味超标 2021-01-26 12:59

Is it possible? have anyone been doing this before? I don\'t know where to start.

I mostly need the menu, not the context menu.

My \"BudgetPieChart\" class

相关标签:
3条回答
  • 2021-01-26 13:07

    To get a menu you need only 1 thing. You have to use GraphicalView on your own activity. In order to do that you'll need:

    Former BudgetPieChart class

    public class ExpByCatPieChartHelper extends AbstractChart{
    
        private DataToArray dta;
    
        @Override
        public String getName() {
            return MyApplication.getContext().getString(R.string.ExpensesByCategoriesPieChartName);
        }
    
        @Override
        public String getDesc() {
            return "The budget per project for this year (pie chart)";      
        }
    
    
        public GraphicalView createView(Context context) {
    
                dta = new DataToArray();
                String[] categories = dta.expenseByCategoriesToArray();
                double[] values = dta.expensesValuesByCategoriesToArray();      
                int[] colors = dta.getColorsArray(categories.length);           
    
                DefaultRenderer renderer = buildCategoryRenderer(colors);           
                renderer.setZoomButtonsVisible(true);
                renderer.setZoomEnabled(true);
                renderer.setChartTitleTextSize(20);
    
                return ChartFactory.getPieChartView(context, buildCategoryDataset("Wydatki kategoriami", categories, values), renderer);
            }
    
        @Override
        public Intent execute(Context context) {
            return null;
        }
    
    
    }
    

    Additional class with activity of your own:

    public class ExpByCatPieChart extends Activity{
    
        private IACharts pieChart = new ExpByCatPieChartHelper();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            GraphicalView mGraphicalView = new ExpByCatPieChartHelper().createView(this);
            setContentView(mGraphicalView);
            super.onCreate(savedInstanceState);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.chart_settings_menu, menu);
            return true;
        }
    
        @Override
        public boolean onMenuItemSelected(int featureId, MenuItem item) {
            switch(item.getItemId()) {
            case R.id.chart_settings:
                Intent i = new Intent(this, PieChartSettings.class);
                startActivityForResult(i, 0); 
                return true;
            case R.id.home:
                finish();
                return true;
            }
            return super.onMenuItemSelected(featureId, item);
        }
    
    
    
    }
    

    And this is pretty much everything. You get a default achart view and seit it as a content of a new activity. Viola :)

    0 讨论(0)
  • 2021-01-26 13:14

    OK so here it is. In my case CustomGraphicalView extends org.achartengine.GraphicalView but you can extend whatever class you need.

     private CustomGraphicalView mGraphicalView = new BudgetPieChart().createView(this); // you edit the createView() with your input data for the graph
     private RelativeLayout chart_layout = (RelativeLayout) findViewById(R.id.chart_layout);
     android.widget.RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(width, height);   
     chart_layout.setGravity(Gravity.CENTER);
     chart_layout.addView(mGraphicalView, param);
    

     public CustomGraphicalView createView(Context context) {
        double[] values = new double[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; //your desired values
        int[] colors = new int[] { // Color.BLUE, Color.GREEN, Color.MAGENTA, Color.YELLOW, Color.CYAN (your desired colors)
        Color.parseColor("#ff3399ff"), Color.parseColor("#ff0066cc"), Color.parseColor("#ff613592"), Color.parseColor("#ff7d3493"), Color.parseColor("#ffe81f53"), Color.parseColor("#ffeb5531"), Color.parseColor("#fff6bb2d"), Color.parseColor("#fff39f2f"), Color.parseColor("#ffe0d347"), Color.parseColor("#ff78c200") };
        // remember to have enough colors to match the number of elements from the data array for each pie slice
        DefaultRenderer renderer = buildCategoryRenderer(colors);
        renderer.setZoomButtonsVisible(false);
        renderer.setZoomEnabled(false);
        renderer.setChartTitleTextSize(20);
        renderer.setAntialiasing(true);
        renderer.setApplyBackgroundColor(false);
        renderer.setBackgroundColor(Color.TRANSPARENT);
        renderer.setPanEnabled(false);
        renderer.setShowLabels(false);
        renderer.setShowLegend(false);
    
        return CustomChartFactory.getPieChartView(context, buildCategoryDataset("Project budget", values), renderer);
    }
    
    @Override
    public Intent execute(Context arg0) {
        // NOT USED
        return null;
    }
    

    public class CustomChartFactory {
    /** The key for the chart data. */
    public static final String CHART = "chart";
    
    /** The key for the chart graphical activity title. */
    public static final String TITLE = "title";
    
    private CustomChartFactory() {
        // empty for now
    }
    
    /**
     * Creates a pie chart intent that can be used to start the graphical view activity.
     * 
     * @param context
     *            the context
     * @param dataset
     *            the category series dataset (cannot be null)
     * @param renderer
     *            the series renderer (cannot be null)
     * @return a pie chart view
     * @throws IllegalArgumentException
     *             if dataset is null or renderer is null or if the dataset number of items is different than the number of series renderers
     */
    public static final CustomGraphicalView getPieChartView(Context context, CategorySeries dataset, DefaultRenderer renderer) {
        checkParameters(dataset, renderer);
        CustomPieChart chart = new CustomPieChart(dataset, renderer);
        return new CustomGraphicalView(context, chart);
    }
    
    /**
     * Checks the validity of the dataset and renderer parameters.
     * 
     * @param dataset
     *            the category series dataset (cannot be null)
     * @param renderer
     *            the series renderer (cannot be null)
     * @throws IllegalArgumentException
     *             if dataset is null or renderer is null or if the dataset number of items is different than the number of series renderers
     */
    private static void checkParameters(CategorySeries dataset, DefaultRenderer renderer) {
        if (dataset == null || renderer == null || dataset.getItemCount() != renderer.getSeriesRendererCount()) {
            throw new IllegalArgumentException("Dataset and renderer should be not null and the dataset number of items should be equal to the number of series renderers");
        }
    }
    }
    

    This should get you going further with your project :) Good luck!


    public class CustomGraphicalView extends org.achartengine.GraphicalView {
    /** The chart to be drawn. */
    private final AbstractChart mChart;
    
    /** The chart renderer. */
    private DefaultRenderer mRenderer;
    
    /** The view bounds. */
    private final Rect mRect = new Rect();
    
    /** The user interface thread handler. */
    private final Handler mHandler;
    
    /** The zoom buttons rectangle. */
    private final RectF mZoomR = new RectF();
    
    /** The zoom in icon. */
    private Bitmap zoomInImage;
    
    /** The zoom out icon. */
    private Bitmap zoomOutImage;
    
    /** The fit zoom icon. */
    private Bitmap fitZoomImage;
    
    /** The zoom area size. */
    private final int zoomSize = 50;
    
    /** The zoom buttons background color. */
    private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);
    
    /** The zoom in tool. */
    private Zoom mZoomIn;
    
    /** The zoom out tool. */
    private Zoom mZoomOut;
    
    /** The fit zoom tool. */
    private FitZoom mFitZoom;
    
    /** The paint to be used when drawing the chart. */
    private final Paint mPaint = new Paint();
    
    /** The touch handler. */
    private ITouchHandler mTouchHandler;
    
    /** The old x coordinate. */
    private float oldX;
    
    /** The old y coordinate. */
    private float oldY;
    
    public boolean isRotating;
    
    private float mX1, mY1, pY1, pX1, mX2, mY2, py, px, lastAngle, angle_rotation, rotation;
    
    /**
     * Creates a new graphical view.
     * 
     * @param context
     *            the context
     * @param chart
     *            the chart to be drawn
     */
    public CustomGraphicalView(Context context, AbstractChart chart) {
        super(context, chart);
        setOnTouchListener(this);
        mChart = chart;
        mHandler = new Handler();
        if (mChart instanceof XYChart) {
            mRenderer = ((XYChart) mChart).getRenderer();
        } else {
            mRenderer = ((RoundChart) mChart).getRenderer();
        }
        if (mRenderer.isZoomButtonsVisible()) {
            zoomInImage = BitmapFactory.decodeStream(CustomGraphicalView.class.getResourceAsStream("image/zoom_in.png"));
            zoomOutImage = BitmapFactory.decodeStream(CustomGraphicalView.class.getResourceAsStream("image/zoom_out.png"));
            fitZoomImage = BitmapFactory.decodeStream(CustomGraphicalView.class.getResourceAsStream("image/zoom-1.png"));
        }
    
        if ((mRenderer instanceof XYMultipleSeriesRenderer) && (((XYMultipleSeriesRenderer) mRenderer).getMarginsColor() == XYMultipleSeriesRenderer.NO_COLOR)) {
            ((XYMultipleSeriesRenderer) mRenderer).setMarginsColor(mPaint.getColor());
        }
        if ((mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) || mRenderer.isExternalZoomEnabled()) {
            mZoomIn = new Zoom(mChart, true, mRenderer.getZoomRate());
            mZoomOut = new Zoom(mChart, false, mRenderer.getZoomRate());
            mFitZoom = new FitZoom(mChart);
        }
        int version = 7;
        try {
            version = Integer.valueOf(Build.VERSION.SDK);
        } catch (Exception e) {
            // do nothing
        }
        if (version < 7) {
            mTouchHandler = new TouchHandlerOld(this, mChart);
        } else {
            mTouchHandler = new TouchHandler(this, mChart);
        }
    }
    
    /**
     * Returns the current series selection object.
     * 
     * @return the series selection
     */
    @Override
    public SeriesSelection getCurrentSeriesAndPoint() {
        return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));
    }
    
    /**
     * Transforms the currently selected screen point to a real point.
     * 
     * @param scale
     *            the scale
     * @return the currently selected real point
     */
    @Override
    public double[] toRealPoint(int scale) {
        if (mChart instanceof XYChart) {
            XYChart chart = (XYChart) mChart;
            return chart.toRealPoint(oldX, oldY, scale);
        }
        return null;
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        // super.onDraw(canvas);
        canvas.save();
        canvas.getClipBounds(mRect);
        int top = mRect.top;
        int left = mRect.left;
        int width = mRect.width();
        int height = mRect.height();
        if (mRenderer.isInScroll()) {
            top = 0;
            left = 0;
            width = getMeasuredWidth();
            height = getMeasuredHeight();
        }
        mChart.draw(canvas, left, top, width, height, mPaint);
        if ((mRenderer != null) && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {
            mPaint.setColor(ZOOM_BUTTONS_COLOR);
            // zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);
            mZoomR.set((left + width) - (zoomSize * 3), (top + height) - (zoomSize * 0.775f), left + width, top + height);
            canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);
            float buttonY = (top + height) - (zoomSize * 0.625f);
            canvas.drawBitmap(zoomInImage, (left + width) - (zoomSize * 2.75f), buttonY, null);
            canvas.drawBitmap(zoomOutImage, (left + width) - (zoomSize * 1.75f), buttonY, null);
            canvas.drawBitmap(fitZoomImage, (left + width) - (zoomSize * 0.75f), buttonY, null);
        }
        canvas.restore();
    }
    
    /**
     * Sets the zoom rate.
     * 
     * @param rate
     *            the zoom rate
     */
    @Override
    public void setZoomRate(float rate) {
        if ((mZoomIn != null) && (mZoomOut != null)) {
            mZoomIn.setZoomRate(rate);
            mZoomOut.setZoomRate(rate);
        }
    }
    
    /**
     * Do a chart zoom in.
     */
    @Override
    public void zoomIn() {
        if (mZoomIn != null) {
            mZoomIn.apply();
            repaint();
        }
    }
    
    /**
     * Do a chart zoom out.
     */
    @Override
    public void zoomOut() {
        if (mZoomOut != null) {
            mZoomOut.apply();
            repaint();
        }
    }
    
    /**
     * Do a chart zoom reset / fit zoom.
     */
    @Override
    public void zoomReset() {
        if (mFitZoom != null) {
            mFitZoom.apply();
            mZoomIn.notifyZoomResetListeners();
            repaint();
        }
    }
    
    /**
     * Adds a new zoom listener.
     * 
     * @param listener
     *            zoom listener
     */
    @Override
    public void addZoomListener(ZoomListener listener, boolean onButtons, boolean onPinch) {
        if (onButtons) {
            if (mZoomIn != null) {
                mZoomIn.addZoomListener(listener);
                mZoomOut.addZoomListener(listener);
            }
            if (onPinch) {
                mTouchHandler.addZoomListener(listener);
            }
        }
    }
    
    /**
     * Removes a zoom listener.
     * 
     * @param listener
     *            zoom listener
     */
    @Override
    public synchronized void removeZoomListener(ZoomListener listener) {
        if (mZoomIn != null) {
            mZoomIn.removeZoomListener(listener);
            mZoomOut.removeZoomListener(listener);
        }
        mTouchHandler.removeZoomListener(listener);
    }
    
    /**
     * Adds a new pan listener.
     * 
     * @param listener
     *            pan listener
     */
    @Override
    public void addPanListener(PanListener listener) {
        mTouchHandler.addPanListener(listener);
    }
    
    /**
     * Removes a pan listener.
     * 
     * @param listener
     *            pan listener
     */
    @Override
    public void removePanListener(PanListener listener) {
        mTouchHandler.removePanListener(listener);
    }
    
    @Override
    protected RectF getZoomRectangle() {
        return mZoomR;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // save the x and y so they can be used in the click and long press
            // listeners
            oldX = event.getX();
            oldY = event.getY();
        }
        if ((mRenderer != null) && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {
            if (mTouchHandler.handleTouch(event)) {
                return true;
            }
        }
        return super.onTouchEvent(event);
    }
    
    /**
     * Schedule a view content repaint.
     */
    @Override
    public void repaint() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                invalidate();
            }
        });
    }
    
    /**
     * Schedule a view content repaint, in the specified rectangle area.
     * 
     * @param left
     *            the left position of the area to be repainted
     * @param top
     *            the top position of the area to be repainted
     * @param right
     *            the right position of the area to be repainted
     * @param bottom
     *            the bottom position of the area to be repainted
     */
    @Override
    public void repaint(final int left, final int top, final int right, final int bottom) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                invalidate(left, top, right, bottom);
            }
        });
    }
    
    /**
     * Saves the content of the graphical view to a bitmap.
     * 
     * @return the bitmap
     */
    @Override
    public Bitmap toBitmap() {
        setDrawingCacheEnabled(false);
        if (!isDrawingCacheEnabled()) {
            setDrawingCacheEnabled(true);
        }
        if (mRenderer.isApplyBackgroundColor()) {
            setDrawingCacheBackgroundColor(mRenderer.getBackgroundColor());
        }
        setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
        return getDrawingCache(true);
    }
    
    }
    

    public class CustomPieChart extends RoundChart {
    public static int radius = 115;
    
    float currentAngle;
    
    /** Handles returning values when tapping on PieChart. */
    private final PieMapper mPieMapper;
    
    /**
     * Builds a new pie chart instance.
     * 
     * @param dataset
     *            the series dataset
     * @param renderer
     *            the series renderer
     */
    public CustomPieChart(CategorySeries dataset, DefaultRenderer renderer) {
        super(dataset, renderer);
        mPieMapper = new PieMapper();
    }
    
    /**
     * The graphical representation of the pie chart.
     * 
     * @param canvas
     *            the canvas to paint to
     * @param x
     *            the top left x value of the view to draw to
     * @param y
     *            the top left y value of the view to draw to
     * @param width
     *            the width of the view to draw to
     * @param height
     *            the height of the view to draw to
     * @param paint
     *            the paint
     */
    @Override
    public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {
        // paint.setAntiAlias(mRenderer.isAntialiasing());
        paint.setAntiAlias(true);
        paint.setStyle(Style.FILL);
        paint.setTextSize(mRenderer.getLabelsTextSize());
        int legendSize = getLegendSize(mRenderer, height / 5, 0);
        int left = x;
        int top = y;
        int right = x + width;
        int sLength = mDataset.getItemCount();
        double total = 0;
        String[] titles = new String[sLength];
        for (int i = 0; i < sLength; i++) {
            total += mDataset.getValue(i);
            titles[i] = mDataset.getCategory(i);
        }
        if (mRenderer.isFitLegend()) {
            legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, true);
        }
        int bottom = y + height - legendSize;
        drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);
    
        currentAngle = 0;
        int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
    
        // radius = (int) (mRadius * 0.35 * mRenderer.getScale());
        if (mCenterX == NO_VALUE) {
            mCenterX = (left + right) / 2;
        }
        if (mCenterY == NO_VALUE) {
            mCenterY = (bottom + top) / 2;
        }
    
        // Hook in clip detection after center has been calculated
        mPieMapper.setDimensions(mRadius, mCenterX, mCenterY);
        boolean loadPieCfg = !mPieMapper.areAllSegmentPresent(sLength);
        if (loadPieCfg) {
            mPieMapper.clearPieSegments();
        }
    
        // float shortRadius = radius * 0.9f;
        // float longRadius = radius * 1.1f;
    
        RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);
        // List<RectF> prevLabelsBounds = new ArrayList<RectF>();
    
        for (int i = 0; i < sLength; i++) {
            paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());
            float value = (float) mDataset.getValue(i);
            float angle = (float) (value / total * 360);
            canvas.drawArc(oval, currentAngle, angle, true, paint);
            // drawLabel(canvas, mDataset.getCategory(i), mRenderer, prevLabelsBounds, mCenterX, mCenterY,
            // shortRadius, longRadius, currentAngle, angle, left, right, paint);
    
            // Save details for getSeries functionality
            if (loadPieCfg) {
                mPieMapper.addPieSegment(i, value, currentAngle, angle);
            }
            currentAngle += angle;
        }
        // prevLabelsBounds.clear();
        // drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);
        // drawTitle(canvas, x, y, width, paint);
    
    }
    
    public static int getRadius() {
        return radius;
    }
    
    @Override
    public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {
        return mPieMapper.getSeriesAndPointForScreenCoordinate(screenPoint);
    }
    
    }
    
    0 讨论(0)
  • 2021-01-26 13:16

    I found the solution to create a context menu here. Once the renderer (XYMultipleSeriesRenderer) is setClickEnabled(true); you can use onCreateContextMenuListener in the usual way.

    0 讨论(0)
提交回复
热议问题