cropping the top of an image on the boundary of a circle - android

I am new to Android development and I need to create this layout.
Any suggestion on how to do the cropping of the top part of the image with the circle would be greatly appreciated.
Thank you!
Edit:
This not the same as the suggested duplicate as they are cropping the entire image into a circle and I only need the top part.

This almost a duplicate of the linked question, so you can start from its answer to do what you want.
The relevant part to update is
canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
bitmap.getWidth() / 2, paint);
If you read [the doc](http://developer.android.com/reference/android/graphics/Canvas.html#drawCircle(float, float, float, android.graphics.Paint)) of this method, you see that
the first param is the x coordinate of the center of the circle
the second param is the y coordinate of the center of the circle
the first coordinate is the radius of the circle
In the question above, the circle is drawn from the center of the bitmap. In your case, you want the center to be at e.g. 3/4 from the top.
Try this code instead
canvas.drawCircle(bitmap.getWidth() / 2, (bitmap.getHeight() / 4) * 3,
bitmap.getWidth() / 2, paint);
and let us know.

Related

Issue on scaling a Canvas in Android

I have a code to scale drawing canvas.
So i tried this code. i scale it but it moves down,
here is my code:
canvas.save();
scaleA = 1.1;
scaleB = 1.1;
canvas.scale(scaleA, scaleB);
canvas.restore();
the issue is even when i scale the Y coordinates move down, so i try to translate or reduce y coordinates but i still issue. any one knows how to properly scale a drawing canvas?
i tried like this:
canvas.save();
scaleA = 1.1;
scaleB = 1.1;
canvas.translate(scaleA, -scaleB);
canvas.scale(scaleA, scaleB);
canvas.restore();
You have to set the center of your image, if your image center is equal to the canvas(view) center
canvas.scale(sx, sy, canvas.getWidth() / 2, canvas.getHeight() / 2);
Or else, change the last two params to whatever center you want it to be, you don't need to translate

Android - Fill Path with color partially

I am trying to draw a heart shaped Canvas using Path in Android. The code is as follows :
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Fill the canvas with background color
canvas.drawColor(Color.WHITE);
// paint.setShader(null);
// Defining of the heart path starts
path.moveTo(left + WIDTH / 2, top + HEIGHT / 4); // Starting point
// Create a cubic Bezier cubic left path
path.cubicTo(left+WIDTH/5,top,
left+WIDTH/4,top+4*HEIGHT/5,
left+WIDTH/2, top+HEIGHT);
// This is right Bezier cubic path
path.cubicTo(left + 3 * WIDTH / 4, top + 4 * HEIGHT / 5,
left + 4 * WIDTH / 5, top,
left + WIDTH / 2, top + HEIGHT / 4);
paint.setShader(new LinearGradient(0, canvas.getHeight()/4, canvas.getWidth(), canvas.getHeight()/4, new int[]{Color.RED, Color.YELLOW, Color.GREEN}, new float[]{0, 0.6f, 1}, Shader.TileMode.CLAMP));
canvas.drawPath(path, paint);
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(4);
heart_outline_paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, heart_outline_paint);
}
I am able to draw heart without any issue and I am able to fill color inside the heart using the Fill option in Paint. But I should be able to fill the heart dynamically according to some data and it cannot be filled fully all the time. What I have achieved so far is as follows :
I have made an extensive search and came across a lot of things similar to this. Some of which includes :
Android fill in part of a path?
filling a circle gradually from bottom to top android
I also came across the concept of converting the canvas to bitmap and filling color inside the bitmap using Flood Fill Algorithm which lets users to fill colors inside the bitmap. However, I do not want the bitmap to fill the color while touching inside the heart but to fill while a button click action.
I thought that filling a circle gradually from bottom to top android
would give help me but it makes use of a circle and I am not well-versed in Canvas which makes me very weak in adapting the circle code to such a shape.
If anybody has some ideas or any insights on how to achieve this, it will be really helpful. Cheers. Thanks in advance.
P.S : I also tried some tricks using setShader in Paint but nothing would give me what I want.
EDIT :
I just stumbled upon a idea of drawing a rectangle over the heart with another color same as the background of the canvas so that it will look like its half filled !! I am still working on the idea and not sure how accurate this is gonna be for me. If someone has a better idea, you're most welcome.
I used clipPath function available in Canvas to achieve what I needed. I draw the heart by above method and draw a rectangle over it, and I use the clipPathfunction to clip out the region that is outside the heart.
public static double filled_amount = .90;
path.moveTo(left_x_moveto, left_y_moveto);
path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3);
path.cubicTo(right_x2, right_y2, right_x1, right_y1, left_x_moveto, left_y_moveto);
path.close();
Rect rect = new Rect((int)(canvas.getWidth()*.10),(int)(canvas.getHeight()*filled_amount),(int) canvas.getWidth(), (int) canvas.getHeight());
canvas.clipPath(path);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
canvas.drawRect(rect, rect_paint);
heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color
heart_outline_paint.setStrokeWidth(15);
heart_outline_paint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path, heart_outline_paint);
This will give me the desired result of filling the heart dynamically. Changing the value of filled_amount dynamically and calling invalidate() will make it look like the heart is being filled dynamically.
#Henry's answer might be a better one but this did the trick for me and I dont look deeply in to the edges so a bit of zig-zags here and there is all right.
You could use Bitmap Masking to get a partially filled Heart. What you ideally do here is use one bitmap to mask the other.
In your case you could have a filled rectangle in the canvas and you have then have the heart shape in a new bitmap to act as the mask. You could then dynamically change the filling of the heart by changing the height of the background rectangle.
Refer this: https://stackoverflow.com/a/33483600/4747587. This contains the implementation of partially filling a Star. The idea is the same.

How to create a resizable circle with user touch events?

I am trying to create a circle shape that will be resized on onTouchEvent.
I have followed resizable rectangle post, but I think due to lack of mathematics knowledge, I am not getting how to create resizeable circle.
I have tried changing
canvas.drawRect(
left + colorballs.get(0).getWidthOfBall() / 2,
top + colorballs.get(0).getWidthOfBall() / 2,
right + colorballs.get(2).getWidthOfBall() / 2,
bottom + colorballs.get(2).getWidthOfBall() / 2, paint);
to canvas.drawCircle(); it creates the circle but not quite what I wanted.
Can you please tell me is there any thing like this already implemented or what points should I follow to convert this rectangle example to resizable circle.
So, the center of circle will be:
float cx = (left + right) / 2f;
float cy = (top + bottom) / 2f;
-- quite obvious. Radius can be calculated using Math.hypot():
float radius = Math.hypot(top - bottom, right - left) / 2f;
Thus, we have center and radius to draw a circle:
drawCircle(cx, cy, radius, paint);

Android rotating one bitmap around another

Im making a 2d game where my character is controlled by a joystick and I rotate him using canvas.rotate(angel, x, y). My character shoots in the same direction he is heading, now I want to add fire coming out of his rifle when he shoots. The problem is, how do I rotate this fire-image around my character?
How I rotate My character:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
character.draw(canvas, controls.charPosition.x,controls.charPosition.y);
canvas.restore();
How I rotate the Fire:
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
As you probably know, drawing my fire like this will make it rotate around its own center, just like with my character. But I want it to rotate around my character so it looks like the fire is coming out of his gun.
Any ideas? If anything is unclear please let me know in a comment. Thanks!
I will try to tailor this answer so that it's more specific, but if I understand you correctly, you may not want to rotate the canvas to create the rotation of the fire. Instead you may want to describe it with a trig function relative to the character's location. So I think it will look something like your drawing of the character.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + charBitmap.getWidth() / 2, controls.charPosition.y + charBitmap.getHeight() / 2);
fire.draw(canvas, controls.charPosition.x+(fireRadius*cos(fireAngle)),controls.charPosition.y+(fireRadius*sin(fireAngle));
canvas.restore();
Where in this code, fireRadius is how far from the center of the character drawing you want the fire drawing to be and fireAngle is the angle of the fire from the center of the character. This won't be quite right because it will track the corner of the fire image, not the center. I think that can be fixed somewhat easily. If not, I will change soon.
You could use Canvas.translate(dx, dy). Idea is to move the fire a certain distance away from the gun, which can be directly along x -axis, and then rotate Canvas around gun center. This results fire to rotate given angle at given distance from the gun.
canvas.save();
canvas.rotate((float) controls.getAngle(), controls.charPosition.x + (fireBitmap.getWidth()) / 2, controls.charPosition.y + (fireBitmap.getHeight() / 2));
canvas.translate(distanceFromGun, 0);
fire.draw(canvas, controls.charPosition.x, controls.charPosition.y);
canvas.restore();
Please do note the order. Canvas matrix operations are pre multiplying and though translation is made later in the code.

Canvas clipping rect - right/bottom edge inclusive?

on Android, there's a Canvas class that represents a drawing surface. It has a clipping rect. Question - are the rect's right and bottom borders inclusive or exclusive? In other words - if the rect is (0, 0)-(10, 10), will the Canvas allow drawing in pixels at coordinates 10?
According to another StackOverflow question, right and bottom are exclusive, but top and left are inclusive.
As I say in my answer there (which I suppose is really a comment), this is consistent with other Java API, and has other benefits.
So, no, you won't be able to draw at ordinate 10. But it does mean that your Rect is a 10×10 pixel square.
Also, calculations are simpler, like:
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
Just for example, I know we have .getWidth() and .getHeight() methods.

Categories

Resources