Android Rotating Rectangle and understanding the Canvas - android

I'm looking at making something that looks like the following:
Which is basically a rectangle shape on the top left thats been rotated, and then two underneath it, tiled like it is.
I've had a go at doing it but just can't get it done, basically I use:
int x = getWidth();
int y = getHeight();
canvas.save();
canvas.rotate(-45);
canvas.drawRect(x/2, y/2, x/2+100, y/2+40, paint);
canvas.restore();
And I've noticed that what should be a rectangle rotated near the centre of the screen is instead one that is to the top right of the screen. When I try doing something similar to (0,0, 100,100) I don't get any rectangle at all.
I guess I'm confused whether the coordinate system changes when the rotation of the canvas is done, and what would be the easiest way in looking into getting the image above on android (besides just creating it in photoshop and adding the png).

The single argument rotate(angle) will use 0,0 as the pivot point.
If you want to rotate about your object, you should calculate some point on it to rotate about and use the 3 argument rotate(angle, pivotX, pivotY), ie:
int x = getWidth();
int y = getHeight();
canvas.save();
canvas.rotate(-45, x / 2, y / 2);
canvas.drawRect(x / 2, y / 2, x / 2 + 100, y / 2 + 40, paint);
canvas.restore();
I made your design just for fun:
int x = getWidth();
canvas.rotate(-45);
canvas.drawRect(-x, 0, x, h, green);
canvas.drawRect(-x, h, 0, 2 * h, purple);
canvas.drawRect(0, h, x, 2 * h, blue);
Where h is the height of the rectangle.

Related

Android PorterDuff: Why doesn't PorterDuff.Mode.SRC_IN cut out the rest of the source?

I'm trying to use the PorterDuff library to trim a canvas circle and rectangle to form a quarter of a square in my custom view for my app, I managed to get it to work but not fully because it trims the square out but keeps the rest of the circle in, I'm using the SRC_IN mode which seems like the right mode to use from looking at the android documentation for it but it's not working as expected, this is a snippet of the onDraw method in my custom view class:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
canvas.drawCircle(width / 2, height / 2, (width + height) / 10, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Rect rectangle = new Rect(0, 0, width / 2, height / 2);
paint.setColor(Color.RED);
canvas.drawRect(rectangle, paint);
}
I'm drawing the circle in the center of the screen and then drawing the square in the top left of the screen and the PorterDuff mode should basically get the intersected part between the shapes but it just trims non-intersected square part out but doesn't do the same for the circle.
This is what it looks like:
I can't tell what i'm doing wrong here, hopefully someone can point it out.
the issue is with the source, the rectangle is the source in this context, draw the rectangle first then use PorterDuff.Mode.SRC_IN to cut the circle based on it.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int height = getHeight();
int width = getWidth();
Rect rectangle = new Rect(0, 0, width / 2, height / 2);
paint.setColor(Color.RED);
canvas.drawRect(rectangle, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawCircle(width / 2, height / 2, (width + height) / 10, paint);
}

How to make resizable triangle in android

I want to make resizable triangle like facility provide into paint or other software, may simple triangle draw and also move using coordinate but how I can resize this triangle I don’t know can anybody help me for this task.
i want like this
Making of the triangle into canvas is so easy here using this function may draw triangle into canvas
public void drawTriangle(Canvas canvas, Paint paint, int x, int y, int width) {
int halfWidth = width / 2;
Path path = new Path();
path.moveTo(x, y - halfWidth);
path.lineTo(x - halfWidth, y + halfWidth);
path.lineTo(x + halfWidth, y + halfWidth);
path.lineTo(x, y - halfWidth);
path.close();
canvas.drawPath(path, paint);
}

How do I find center of drawable for android canvas

I have a drawable resource that I need to draw on a canvas. I need to have the drawable centered at point (x,y). Right now if I do canvas.drawBitmap(mBitmap, x, y, mPaint), (x,y) represent (left,top). Does anyone know how I may get the center of my drawable so I can place it on the canvas correctly?
Get the width and height of the canvas.
Now, you need to draw it on width/2 and height/2.
To be more centered, you can subtract from width/2 half of the bitmap width, and from height/2 half of the bitmap height.
canvas.drawBitmap(mBitmap, width/2-mBitmap.getWidth()/2, height/2-mBitmap.getHeight()/2, mPaint);
A Simple math...
int centerX = drawable.getIntrinsicWidth() / 2;
int centerY = drawable.getIntrinsicHeight() / 2;

draw a curve line with arrow in android canvas

draw a curved line with arrow from point1(x1,y1) to point2(x2,y2) like this
I'm developing an application in android canvas.
automata like application and I'm having trouble drawing a curved line with an arrow at the end.
pointing the next circle.
can u give me a code or suggestion about this?
I think what You need is a mix out of draw on path and line drawing. Declare this method inside Your onDraw:
private void drawOvalAndArrow(Canvas canvas){
Paint circlePaint = new Paint();
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
circlePaint.setAntiAlias(true);
circlePaint.setStrokeWidth(2);
circlePaint.setColor(Color.CYAN);
float centerWidth = canvas.getWidth()/2; //get center x of display
float centerHeight = canvas.getHeight()/2; //get center y of display
float circleRadius = 20; //set radius
float circleDistance = 200; //set distance between both circles
//draw circles
canvas.drawCircle(centerWidth, centerHeight, circleRadius, circlePaint);
canvas.drawCircle(centerWidth+circleDistance, centerHeight, circleRadius, circlePaint);
//to draw an arrow, just lines needed, so style is only STROKE
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setColor(Color.RED);
//create a path to draw on
Path arrowPath = new Path();
//create an invisible oval. the oval is for "behind the scenes" ,to set the path´
//area. Imagine this is an egg behind your circles. the circles are in the middle of this egg
final RectF arrowOval = new RectF();
arrowOval.set(centerWidth,
centerHeight-80,
centerWidth + circleDistance,
centerHeight+80);
//add the oval to path
arrowPath.addArc(arrowOval,-180,180);
//draw path on canvas
canvas.drawPath(arrowPath, circlePaint);
//draw arrowhead on path start
arrowPath.moveTo(centerWidth,centerHeight ); //move to the center of first circle
arrowPath.lineTo(centerWidth-circleRadius, centerHeight-circleRadius);//draw the first arrowhead line to the left
arrowPath.moveTo(centerWidth,centerHeight );//move back to the center
arrowPath.lineTo(centerWidth+circleRadius, centerHeight-circleRadius);//draw the next arrowhead line to the right
//same as above on path end
arrowPath.moveTo(centerWidth+circleDistance,centerHeight );
arrowPath.lineTo((centerWidth+circleDistance)-circleRadius, centerHeight-circleRadius);
arrowPath.moveTo(centerWidth+circleDistance,centerHeight );
arrowPath.lineTo((centerWidth+circleDistance)+circleRadius, centerHeight-circleRadius);
//draw the path
canvas.drawPath(arrowPath,circlePaint);
}
This is just a poor example, but itshould show where to start with.
I know i should leave comment but the code in the comment is hard to read, so i put up another answer.
The answer Opiatefuchs it's basally right. but there's 1 thing you should notice, if you want to test his code.
float centerWidth = canvas.getWidth()/2; //get center x of display
float centerHeight = canvas.getHeight()/2; //get center y of display
the centerWidth and the centerHeight should be obtained like below, or nothing would painted to your screen.
and the circleDistance = 200 is a bit large for a regular phone's screen( as for my device samsung i9300, 200 is too large, the second circle positioned out of the screen range. you change it to a smaller value 80 for example.)
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerWidth = w / 2;
centerHeight = h / 2;
}
the screenshot.

Compass with bitmap is going everywhere in the screen

i want my compass to spin like this
but my result is that:
the compass is going everywhere in my screen...
where is my problem please?this is my compass.java code:
#Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.GRAY);
int w = canvas.getWidth();
int h = canvas.getHeight();
int cw = w / 2;
int ch = h / 2;
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass);
canvas.translate(cw, ch);
if (mValues != null) {
canvas.rotate(-mValues[0]);
}
int cx = (mWidth - myBitmap.getWidth()) / 2;
int cy = (mHeight - myBitmap.getHeight()) / 2;
canvas.drawBitmap(myBitmap, cx, cy, null);
}
p.s.: i m sorry for the bad pictures but i really dont know how to explain my problem in english!Thanks
Since you have already translated to the center of the canvas, you may only need to offset the compass with its half width/height to center it. Try:
int cx = -myBitmap.getWidth() / 2;
int cy = -myBitmap.getHeight() / 2;
canvas.drawBitmap(myBitmap, cx, cy, null);
Also to get a good hang of transformations (translate, rotate), read The OpenGL Red book chapter 3, specifically the part Thinking about Transformations. While this is about OpenGL, you can use the knowledge for non-OpenGL transforms too.
EDIT:
Think in turtle logic. Your first translation takes your pencil to the center of your canvas. The rotation rotates your pencil. So now you could draw the compass exactly where the pencil is (no offsets), except that drawing the compass image is done starting from its top-left corner instead of its center. Therefore you need a last translation of (-compassWidth/2, -compassHeight/2). Note that this translation already occurs on the rotated x & y axes. Also note that you may pass 0/0 for cx/cy in drawBitmap if you manually apply that translation to the canvas itself.
So the full sequence is: translate to canvas center, rotate, translate negated to image center.
Don't decode the Bitmap in onDraw - do it when the view is created and reuse the Bitmap.
Make a Matrix and matrix.postRotate(mValues[0], half_width_of_bitmap, half_height_of_bitmap); and matrix.postTranslate(cw, ch);
Draw the bitmap with canvas.drawBitmap(bitmap, matrix, null);

Categories

Resources