Android Animated Bar Chart (invalidate())

爷,独闯天下 提交于 2019-12-24 13:26:24

问题


I am very novice in android drawing and animation on android. I have a bar chart and I want to animate the bars (bottom-up drawing). I know that invalidate() within onDraw() is a good manner to do it but until now I fails to do it...

import android.graphics.Path; import android.graphics.Region;

public class Bar {

private int color;
private String name;
private float value;
private Path path;
private Region region;

public int getColor() {
    return color;
}

public void setColor(int color) {
    this.color = color;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public float getValue() {
    return value;
}

public void setValue(float value) {
    this.value = value;
}

public Path getPath() {
    return path;
}

public void setPath(Path path) {
    this.path = path;
}

public Region getRegion() {
    return region;
}

public void setRegion(Region region) {
    this.region = region;
}

}

import java.text.DecimalFormat;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class BarGraph extends View {

    private ArrayList<Bar> bars = new ArrayList<Bar>();
    private Paint p = new Paint();
    private Path path = new Path();
    private Rect r;
    private boolean showBarText = true;
    private int indexSelected = -1;
    private OnBarClickedListener listener;
    private Bitmap fullImage;
    private boolean shouldUpdate = false;
    private String unit = "";
    private DecimalFormat df = new DecimalFormat("#.#");
    private Boolean append = false;
    private Rect r2 = new Rect();
    private Rect r3 = new Rect();



    private boolean shouldCacheToBitmap;

    public BarGraph(Context context) {
        super(context);
    }

    public BarGraph(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setShowBarText(boolean show) {
        showBarText = show;
    }

    public void setBars(ArrayList<Bar> bars) {
        this.bars = bars;
        postInvalidate();
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public String getUnit() {
        return this.unit;
    }

    public void appendUnit(Boolean doAppend) {
        this.append = doAppend;
    }

    public Boolean isAppended() {
        return this.append;
    }

    public ArrayList<Bar> getBars() {
        return this.bars;
    }

    public void drawToCanvas(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT);
        NinePatchDrawable popup = (NinePatchDrawable) this.getResources()
                .getDrawable(R.drawable.popup_black);

        float maxValue = 0;
        float padding = 7;
        int selectPadding = 4;
        float bottomPadding = 40;

        float usableHeight;
        if (showBarText) {
            this.p.setTextSize(40);
            this.p.getTextBounds("$", 0, 1, r3);
            usableHeight = getHeight() - bottomPadding
                    - Math.abs(r3.top - r3.bottom) - 26;
        } else {
            usableHeight = getHeight() - bottomPadding;
        }

        p.setColor(Color.BLACK);
        p.setStrokeWidth(2);
        p.setAlpha(50);
        p.setAntiAlias(true);

        canvas.drawLine(0, getHeight() - bottomPadding + 10, getWidth(),
                getHeight() - bottomPadding + 10, p);

        float barWidth = (getWidth() - (padding * 2) * getBars().size())
                / getBars().size();

        for (Bar p : getBars()) {
            maxValue = Math.max(maxValue, p.getValue());
        }

        r = new Rect();

        // path.reset();

        int count = 0;
        for (Bar p : getBars()) {
            r.set((int) ((padding * 2) * count + padding + barWidth * count),
                    (int) (getHeight() - bottomPadding - (usableHeight * (p
                            .getValue() / maxValue))), (int) ((padding * 2)
                            * count + padding + barWidth * (count + 1)),
                    (int) (getHeight() - bottomPadding));

            // path.addRect(new RectF(r.left - selectPadding, r.top -
            // selectPadding, r.right + selectPadding, r.bottom +
            // selectPadding), Path.Direction.CW);
            // p.setPath(path);
            // p.setRegion(new Region(r.left - selectPadding, r.top -
            // selectPadding, r.right + selectPadding, r.bottom +
            // selectPadding));

            this.p.setColor(p.getColor());
            this.p.setAlpha(255);
            canvas.drawRect(r, this.p);
            this.p.setStyle(Paint.Style.STROKE);
            this.p.setStrokeWidth(2);
            this.p.setColor(Util.getStrokeColor(p.getColor()));
            canvas.drawRect(r, this.p);
            this.p.setStyle(Paint.Style.FILL);
            this.p.setStrokeWidth(0);
            this.p.setColor(p.getColor());
            this.p.setTextSize(Util.dipToPixels(getContext(), 11));
            canvas.drawText(p.getName(),
                    (int) (((r.left + r.right) / 2) - (this.p.measureText(p
                            .getName()) / 2)), getHeight() - 5, this.p);
            if (showBarText) {
                this.p.setTextSize(16);
                this.p.setColor(Color.WHITE);
                this.p.getTextBounds(unit + df.format(p.getValue()), 0, 1, r2);
                if (popup != null)
                    popup.setBounds(
                            (int) (((r.left + r.right) / 2) - (this.p
                                    .measureText(unit + df.format(p.getValue())) / 2)) - 14,
                            r.top + (r2.top - r2.bottom) - 26,
                            (int) (((r.left + r.right) / 2) + (this.p
                                    .measureText(unit + df.format(p.getValue())) / 2)) + 14,
                            r.top);
                popup.draw(canvas);
                if (isAppended())
                    canvas.drawText(
                            df.format(p.getValue()) + unit,
                            (int) (((r.left + r.right) / 2) - (this.p
                                    .measureText(unit + df.format(p.getValue())) / 2)),
                            r.top - 20, this.p);
                else
                    canvas.drawText(
                            unit + df.format(p.getValue()),
                            (int) (((r.left + r.right) / 2) - (this.p
                                    .measureText(unit + df.format(p.getValue())) / 2)),
                            r.top - 20, this.p);
            }
            count++;
        }

    }

    @Override
    public void onDraw(Canvas ca) {
        if (!shouldCacheToBitmap) {
            drawToCanvas(ca);
            return;
        }
        if (fullImage == null || shouldUpdate) {
            fullImage = Bitmap.createBitmap(getWidth(), getHeight(),
                    Config.ARGB_8888);
            Canvas canvas = new Canvas(fullImage);
            drawToCanvas(canvas);

            shouldUpdate = false;

        }

        ca.drawBitmap(fullImage, 0, 0, null);
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return true;
    }

    public void setOnBarClickedListener(OnBarClickedListener listener) {
        this.listener = listener;
    }

    public boolean isShouldCacheToBitmap() {
        return shouldCacheToBitmap;
    }

    public void setShouldCacheToBitmap(boolean shouldCacheToBitmap) {
        this.shouldCacheToBitmap = shouldCacheToBitmap;
    }

    public interface OnBarClickedListener {
        abstract void onClick(int index);
    }
}

来源:https://stackoverflow.com/questions/20811964/android-animated-bar-chart-invalidate

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