I created a custom view called CanvasView
. I can use this view to draw stuff on it outside of the onDraw
method. Which means I can add lines, circles, whatever I want to the canvas anywhere in my code.
I want to draw a random line on the canvas view in the onCreate
method. I want the starting point to be in the left half of the view and the ending point in the right half. However, when I measure the width of the view using getWidth
, it returns 0! And then I pass this number into Random.nextInt
with some more calculations. And resulting in a negative number. An IllegalArgumentException
occurs as expected.
I just want to ask why my view's width is 0? And how can I get the correct width?
Here is the CanvasView
class: (methods other than addShape
and onDraw
are irrelevant, I think)
public class CanvasView extends View {
/**
* Stores all the shapes that the view will draw in its {@code onDraw()}
* method
*/
private ArrayList<Shape> shapes;
/**
* Represents a standard {@code Paint} object that should be used when
* drawing on this {@code CanvasView}.
*/
private Paint paint;
public CanvasView(Context c) {
super (c);
init ();
}
public CanvasView(Context context, AttributeSet attrs) {
super (context, attrs);
init ();
}
public CanvasView(Context context, AttributeSet attrs, int defStyleAttr) {
super (context, attrs, defStyleAttr);
init ();
}
/**
* Initializes the view, called by the constructor.
*/
private void init() {
shapes = new ArrayList<> ();
paint = new Paint ();
paint.setStrokeWidth (5);
paint.setColor (Color.BLACK);
}
@Override
public void setOnTouchListener(final OnTouchListener listener) {
final OnTouchListener baseListener = new OnTouchListener () {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction () == MotionEvent.ACTION_DOWN) {
float x = event.getX ();
float y = event.getY ();
Log.d ("My App", "X: " + x);
Log.d ("My App", "Y: " + y);
//check whether the point touched is in bounds
if (x < 18 || x > getWidth () - 18 || y < 18 ||
y > getHeight () - 18)
return false;
else
return true;
}
return false;
}
};
super.setOnTouchListener (new OnTouchListener () {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (baseListener.onTouch (v, event)) {
if (listener != null) {
return listener.onTouch (v, event);
} else {
return true;
}
}
return false;
}
});
}
@Override
protected void onDraw(Canvas c) {
super.onDraw (c);
for (Shape s : shapes) {
s.draw (c);
}
//draw the border.
c.drawLine (3, 3, getWidth () - 3, 3, paint);
c.drawLine (3, getHeight () - 3, getWidth () - 3, getHeight () - 3, paint);
c.drawLine (3, 3, 3, getHeight () - 3, paint);
c.drawLine (getWidth () - 3, 3, getWidth () - 3, getHeight () - 3, paint);
//draw the inner border
c.drawLine (18, 18, getWidth () - 18, 18, paint);
c.drawLine (18, getHeight () - 18, getWidth () - 18, getHeight () - 18, paint);
c.drawLine (18, 18, 18, getHeight () - 18, paint);
c.drawLine (getWidth () - 18, 18, getWidth () - 18, getHeight () - 18, paint);
}
/**
* Adds a shape to the {@code CanvasView} so that it can be drawn
* in its {@code onDraw()} method.
*
* @param s
*/
public void addShape(Shape s) {
shapes.add (s);
invalidate ();
}
/**
* Clears all the shapes on the {@code CanvasView}.
*/
public void clear() {
shapes.clear ();
}
}
There is a Shape
interface that I created, which only has this method:
void draw (Canvas c);
Here is how I draw a random line, this snippt is in a method that is called in onCreate
:
Random r = new Random ();
final int width = canvas.getWidth () - 30;
final int height = canvas.getHeight () - 30;
final Paint p = paint;
final int startX = r.nextInt ((width - 30) / 2) + 30;
final int startY = r.nextInt (height - 30) + 30;
final int stopX = r.nextInt ((width - 30) / 2) + width / 2 + 30;
final int stopY = r.nextInt (height - 30) + 30;
float adjSide = Math.abs (stopX - startX);
float oppSide = Math.abs (stopY - startY);
lineAngle = (float)Math.atan (oppSide / adjSide);
canvas.addShape (new Shape () {
@Override
public void draw(Canvas c) {
c.drawLine (startX, startY, stopX, stopY, p);
}
});
Aucun commentaire:
Enregistrer un commentaire