I have two lines where one line is drawn at the same point every time and the other line is rotated by a certain degree every time the view is invalidated.
The code is as shown below :
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
int centerx = width/2;
int centery = height/2;
canvas.drawLine(centerx, 0, centerx, height, paint);
canvas.drawLine(0, centery, width, centery, paint);
if (angle_in_degrees!= null)
canvas.rotate(angle_in_degrees, centerx, centery);
paint.setColor(0xff0000ff);
canvas.drawLine(centerx, -1000, centerx, +1000, paint);
canvas.drawLine(-1000, centery, 1000, centery, paint);
paint.setColor(0xff00ff00);
}
Everything works fine, but I want to fill the space between the two lines by a different color. How do I do that? Thanks.
The accepted answer to this question sounds as if it would apply just as well to your situation. Essentially, the author uses a Path object to connect the dots between all points that need to be filled, before finally called canvas.drawPath() to fill the area inside.
In your case, this would probably look something like:
Path path = new Path();
path.lineTo(centerX, 0);
path.lineTo(centerX, height);
path.lineTo(0, centerY);
//etc. Essentially mirroring what your line does, but in one dimension (x,y) points.
canvas.drawPath(path, paint);
Edit: You would also need to make sure the Paint object you use has a FILL style:
paint.setStyle(Paint.Style.FILL);
Related
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);
}
I would like to draw a rectangle and insert some text.
Then I need to rotate it by degree 90.
I create a DrawView which looks like this
public class DrawView extends View
{
public DrawView(Context context, int w, int h)
{
...
}
#Override
protected void onDraw(Canvas canvas)
{
Point p = new Point();
Point p2 = new Point();
...
super.onDraw(canvas);
// draw a rectangle
canvas.drawRect(0, top, 0, top+100, p);
canvas.drawText(str, width / 2, textBaseY, p2);
canvas.rotate(-90.0f,...);
}
}
I have tried many times but the text doesn't rotate as I expected.
Can anyone give me some hint?
Thanks so much
Try:
canvas.rotate(-90.0f, x, y);
canvas.drawRect(0, top, 0, top+100, p);
canvas.drawText(str, width / 2, textBaseY, p2);
If you want to restore the canvas to normal (so that it doesn't remain rotated by 90 degrees for future draws), you can do this:
canvas.save();
canvas.rotate(-90.0f, x, y);
canvas.drawRect(0, top, 0, top+100, p);
canvas.drawText(str, width / 2, textBaseY, p2);
canvas.restore();
how to make that text was written vertically? how to rotate text 90 degrees?
Write each letter individually is stupid, but now ,i don't know another way.
Paint paint = new Paint();
public DrawView(Context context, double arr[])
{
super(context);
paint.setColor(Color.BLACK);
}
#Override
public void onDraw(Canvas canvas)
{
canvas.drawText("Test",50, 50, paint);
}
Simply rotating text (or anything else) is easy: Use the rotate() method to rotate the canvas (afterwards it is rotated back, otherwise everything you draw becomes rotated):
canvas.save();
canvas.rotate(90f, 50, 50);
canvas.drawText("Text",50, 50, paint);
canvas.restore();
The save() and restore()methods respectively save the state of the canvas and restores it. So the rest of your drawn elements are not rotated. If you only want to paint the text these two methods are not necessary.
If you want to put the characters of the string under each other, you need to process each character separately. First you'd need to obtain the font height and when drawing each character you need to increase the y-coordinate with this height over and over again.
int y = 50;
int fontHeight = 12; // I am (currently) too lazy to properly request the fontHeight and it does not matter for this example :P
for(char c: "Text".toCharArray()) {
canvas.drawText(c, 50, y, paint);
y += fontHeight;
}
Correct version is :
Canvas canvas_front = new Canvas(bitmap_front);
Paint paint = new Paint();
paint.setColor(Color.rgb(140, 0, 0));
paint.setAlpha(80);
paint.setStrokeWidth(2);
canvas_front.drawLine(0, (float) (frontIV.getHeight() * 0.9),frontIV.getWidth(), (float) (frontIV.getHeight() * 0.9), paint);
canvas_front.save();
canvas_front.rotate((float) 90 , 50, 50);
canvas_front.drawText("Text",50, 50, paint);
canvas_front.restore();
frontIV.setImageBitmap(bitmap_front);
I'm using a Custom View where I created a Circle:
canvas.drawCircle(width/2, width/2, radius, paint1);
Now, I want to empty the circle from inside, something like a ring.
Drawing another smaller white circle will raise another problem. I'm planning to make my view listen to user clicks. I want to listen to the clicks on the ring only!
Is there a way to exclude some part of the canvas?
In order to draw a ring (i.e., a circle that is NOT filled in but just has a border, with the area inside transparent) do this:
Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
myPaint.setStyle(Paint.Style.STROKE);
int strokeWidth=4; // or whatever
myPaint.setStrokeWidth(strokeWidth);
myPaint.setColor(0xffff0000); //color.RED
float radius=(float) (0.5*(w+h)*0.5);
canvas.drawCircle((float)0.5*w, (float)0.5*h, radius, myPaint);
The call to drawCircle can also be replaced by drawArc like the code below. Either approach will work. The secret sauce is to set the paint style to Paint.Style.STROKE.
RectF oval = new RectF(w/2 - radius, w/2 - radius, w/2 + radius, w/2 + radius);
canvas.drawArc(oval, 0, 360, false, myPaint);
To draw a ring, use drawArc :
RectF oval = new RectF(width/2 - radius, width/2 - radius, width/2 + radius, width/2 + radius);
canvas.drawArc(oval, 0, 360, false, paint1);
I worked around the problem by drawing an inner white circle and filtering the clicks based on the two radius lengths I had.
So, you can't draw an empty circle but you can make a circle to behave like an empty one.
Thanks.
this solution works:
Paint paintPath;
int circleRadius = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources()
.getDisplayMetrics());
paintPath = new Paint();
paintPath.setStrokeWidth(circleRadius);
paintPath.setColor(Color.WHITE);
paintPath.setStyle(Paint.Style.FILL_AND_STROKE);
paintPath.setAntiAlias(true);
paintPath.setPathEffect(null);
paintPath.setRasterizer(null);
inside on draw
RectF rectF = new RectF(centerx - radius, centery - radius,
centerx + radius, centery + radius);
Path myPath = new Path();
for (int i = 0; i <= 360; i += 1)
{
myPath.addArc(rectF, i, 1);
}
canvas.drawPath(myPath, paintPath);
More short way:
draw = function() {
ctx.globalCompositeOperation = "lighter";
ctx.beginPath();
// ctx.fillStyle = "green";
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
// ctx.fill();
ctx.strokeStyle = "yellow";
ctx.stroke();
ctx.closePath();
}
I'm trying to draw on a canvas a text and below another text that is the mirror of this text (that looks like shadow)
I'm using it in the "onDraw" method
Is there a simple way to do it?
Thanks in advance,
Lior
sure can. You will need to scale the canvas first. Try this out:
paint.setTextSize(44);
int cx = this.getMeasuredWidth() / 2;
int cy = this.getMeasuredHeight() / 2;
paint.setColor(Color.RED);
canvas.drawText("Hello", cx, cy, paint);
canvas.save();
canvas.scale(1f, -0.5f, cx, cy);
paint.setColor(Color.GRAY);
canvas.drawText("Hello", cx, cy, paint);
super.onDraw(canvas);
canvas.restore();
Try different values for the scale Y value to get effect you want.