I am trying to draw objects on a canvas in Android. For instance, for a filled triangle, I define the values for the triangle in one class and using a button click, I would like to call the canvas from another class with the triangle displayed on it.
My issue is that I am having a hard time passing the values from the class to the onDraw(Canvas canvas) method. I am thinking of overloading the method. Has anyone done this before?
Thanks.
"Re-edited based on the responses below!!"
This is the code that I am calling when I click the button from another class. However,despite the fact that the triangle values are called, the onDraw() method is not being called. Where am I going wrong?
public class MyView extends View{
Path path = new Path();
Paint paint = new Paint();
public MyView(Context context) {
super(context);
}
public void setPath(Point a, Point b, Point c){
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(a.x, b.y);
Log.d("MYVIEW","pointA" +a.x);
Log.d("MYVIEW","pointB" +b.y);
path.lineTo(b.x, b.y);
path.lineTo(c.x, c.y);
path.lineTo(a.x, a.y);
path.close();
postInvalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(2);
paint.setColor(android.graphics.Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
Log.d("ONDRAW","inside onDraw");开发者_开发技巧
canvas.drawPath(path, paint);
}
}
"How I am calling the MyView Class"
Point pointA = new Point();
pointA.set(x, y);
Point pointB = new Point();
pointB.set(m, n);
Point pointC = new Point();
pointC.set(b, c);
MyView view = new MyView(this.context);
view.setPath(pointA, pointB, pointC);
I think that the idea of calling an onDraw()
method yourself directly is flawed in the first place, because onDraw()
is the method that the system calls when it wants to render your View, passing it the Canvas
to do so. Telling the system that you want the View to be re-rendered is done by calling invalidate()
on that View (or postInvalidate()
from a non-UI thread) and then the system will eventually call that View's onDraw()
.
What you should be doing is either providing your custom View with a reference to an object that holds the data that will affect what's drawn, or alternatively create some 'setter' methods in your custom View so that the View itself is the object that holds that specific data. It really all depends on your application. Then you'd call invalidate()
on that View.
Extremely simplistic examples of the above:
Triangle mTriangle = new Triangle( ... vertices here ... );
mCustomView.setTriangle(mTriangle);
mCustomView.invalidate();
Or:
mCustomView.setTriangle( ... vertices here ... );
mCustomView.invalidate();
You could perform the invalidate()
in the setter method as well if you like to simplify it still. This is probably how a TextView
's setText()
method works: it sets the text into a variable, and then calls invalidate()
.
This is a way to do this:
public class yourDrawingView extends View{
//bla bla bla
int triangle_detail1;
int triangle_detail2; //and all you need to draw the triangle
public void setTriangle(int d1,int d1){ //etc give the function the parameters she needs
triangle_detail1 = d1;
triangle_detail2 = d2;
//ETC
//finally
invalidate();
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
//draw your triangle
}
The buffer of a custom view is not persistant, you have to draw everything for each frame, while SurfaceView is persistant but it has two buffers which complicates things.
You can easily do what you want if you would draw all your objects to a bitmap and then draw that bitmap on the view's canvas. Then you can created overloaded methods for your objects.
Another way to do it which is good for undo feature is to make each object a class as Trevor sugggested and then add these objects into an ArrayList.
When onDraw just iterate through the ArrayList and draw all objects. You can then easily add or remove objects.
An example:
class Triangle{
public PointF p1;
public PointF p2;
public PointF p3;
public boolean filled;
public int tColor;
public boolean remove;
Triangle(PointF p1,PointF p2, PointF p3, boolean filled, int tColor){
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.filled = filled;
this tColor = tColor;
}
}
Create a triangle and add it to an arraylist:
ArrayList<Triangle> triangles = new ArrayList<Triangle>();
Triangle triangle = new Triangle(new PointF(1,1),new PointF(2.2f,2.2f),new PointF(3.3f,3.3f), true, Color.BLUE);
triangles.add(triangle);
in onDraw(Canvas canvas) for the view:
for (int i = triangles.size() - 1; i >= 0; i--) {
Triangle triangle = triangles.get(i);
if (trinagle.remove){
triangles.remove(i); //remove object if condition met
}else{
drawTriangle(triangle, canvas);
}
}
Then you in drawTriangle method you just draw the lines etc on the passed canvas.. I hope this gives you some ideas.
精彩评论