问题
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