Path . lineTo draws only half of length - android

Can somebody help me understand how does path.lineTo(x,y) actually work. I am trying to draw a simple straight line in a finger paint type of app. Here is an example I tried:
mPath.reset();
mPath.moveTo(0, 0);
mPath.lineTo(480, 800);
But the line goes only from 0,0 to 240, 400 - always only a half of distance as I move my finger over the screen. (the real programme has startX, startY and x,y touch coordinates instead of 0,0 & 480,800)

Maybe this piece of code will work for you:
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
Path mPath= new Path();
mPath.moveTo(0, 0);
mPath.lineTo(480, 800);
p.setColor(0xff800000);
canvas.drawPath(mPath,p);
Also, the (480, 800) coordinate, is it still inside your screen?

The Path commands work exactly how you expect them to work and the above command should draw a line from top left to bottom righ corners in a view fully covering a 480x800 screen .
Check the follwoing:
The view covers all screen
The is no other view overlaping it
The coordinates are relative to top left coordinate of view. Check that view top left is on top left of screen
Regards.

Thanks to Goz and others who helped me truobleshoot this, it came out that Paint was doing it with this settings:
mPaint.setPathEffect(new CornerPathEffect(1000))
When this is removed or set to null, lineTo goes all the way. One just did not expect at first that Paint would do this but this corner rounding effect can shorten a straight line.

Related

canvas.drawBitmap not working as expected

I am trying to add an image on top of another image. The one on the top is a blurred image. I am using the following code to try and achieve this.
//First image as a background(full size)
mCanvas.drawBitmap(canvasBackImage, 0, 0, null); //draws fine
Rect rectangle = new Rect(0,0,200,200);
//Second image on top blurred 200px x 200px rectangle
mCanvas.drawBitmap(blurBuilder.blur(appContext, canvasBackImage, mX, mY), null, rectangle, null);
The image is drawn fine with the above code at coordinate 0,0 of the canvas however, if I modify the above code's line three to the following, it doesn't add the image at the 100,100 coordinate of the canvas.
Rect rectangle = new Rect(100,100,200,200);
I also tried it with 50,50 coordnate and it works. So Changing it the following works too.
Rect rectangle = new Rect(50,50,200,200);
I have no idea why this is not working as I expect it to. Am I doing something wrong?
My ultimate objective is to blur the image at the exact location that the user touched. So if user touched in the middle of the screen then that part of the image will be blurred out.
I moved the above code in onDraw method and it seems to be working as expected now.
Before I had it in a different method which was being called manually on a button click.

Open PopupWindow and drawing from RightTop to LeftBottom, instead of LeftTop to RightBottom

I know I can use:
myPopup.showAtLocation(layout, Gravity.NO_GRAVITY, x, y);
// OR
myPopup.showAtLocation(layout, Gravity.TOP|Gravity.LEFT, x, y);
To open a PopupWindow that's drawn from [x, y] as the Top-Left of the PopupWindow, drawn towards to Bottom-Right.
What I want instead however, is to draw from [x, y] as the Top-Right of the PopupWindow, drawn towards the Bottom-Left.
Here is a picture to make it more clear (The dot is my [x, y] position and the rectangle is my PopupWindow. The first picture shows how it's normally done, and the second is what I want to achieve.):
So how do I correctly calculate the x and y of the second picture's gray point's location, while knowing the black point's location? I know the y can stay the same, but the x should be changed to something like:
x minus PopupWindow-width
The problem is that the PopupWindow's width and height are both set to wrap_content, so I don't know the size until after I draw it.
Does this mean I have to draw it (but make it invisible at first), then calculate the new x with the PopupWindow's MeasuredWidth in it's ViewTreeObserver's OnGlobalLayoutListener (to know when it's done rendering and the MeasuredWidth is known), then apply this new x and then make it Visible? Or is there an easier way to just let it draw at the correct position?
PS: I've also changed Gravity.NO_GRAVITY to Gravity.TOP|Gravity.RIGHT, if the PopupWindow is out of the screen it will automatically place it at the border of the Right/Top side (whichever side it's out of the screen).
You could get the size of your popup window by overriding the onMeasure method of the popup window (note that you have to subclass a View in order to do this). After that, you can calculate the offset of the x and y coordinates. Hope this helps.

Why is drawLine offset by 1 pixel?

This is probably an easy one for Android experts. I am trying to draw into a Bitmap via a Canvas. I want exact colors, no anti-aliasing, and lines located at exact absolute coordinates within the Bitmap. Sometimes the lines are in the correct position and sometimes they are offset by 1 pixel. I have a feeling this has something to do with scaling. But I'm not sure. Here's the code:
Paint mPaint = new Paint();
mPaint.setColor(Paint.WHITE);
mPaint.setStrokeWidth(0);
mPaint.setAntiAlias(false);
mPaint.setDither(false);
mPaint.setStyle(Paint.Style.STROKE);
drawingContext.mycanvas.drawLine(20, 0, 10, 10, mPaint);
This actually draws a line from (19,0) to (10,9). Why?
I'll answer. I had to give up on this and write a Bresenham algorithm, setting pixels one by one. That works OK for what I'm doing. I suspect a drawLine bug when drawing left to right, bottom to top lines.

Android Rect not working

I have been trying to work on a simple code for two days now. I have tried all alterations but none seems to be working.
I am trying to draw vertical rectangles with different colors.
In the first one, I am using only one Rect variable and moving the coordinates. Here is the relevant part of the code.
Rect myRect1=new Rect();
Random colorMe=new Random();
for(int j=0;j<5;j++){
myRect1.set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
paint.setColor(Color.rgb(colorMe.nextInt(255), colorMe.nextInt(255), colorMe.nextInt(255)));
myCanvas.drawRect(myRect1, paint);
}
Other alteration which I tried was through an array.
Here is the code.
Rect[] myRect=new Rect[5];
Random colorMe=new Random();
for(int j=0;j<5;j++){
myRect[j].set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
paint.setColor(Color.rgb(colorMe.nextInt(255), colorMe.nextInt(255), colorMe.nextInt(255)));
myCanvas.drawRect(myRect[j], paint);
}
Can somebody please help me what is the problem actually there?
The first thing that seems obviously wrong (there might be more):
The minimum x-coordinate of your rectangle is myCanvas.getWidth()/5*j
The maximum x-coordinate of your rectangle is myCanvas.getWidth()/5*j
They are both the same value, so your rectangle is degenerate.
Offtopic, but very relevant: whenever you run into a problem like this, you need to break it down into smaller parts until you get it to do something. This will help you understand what's wrong:
Extract all subexpressions (like the color, and the generated x/y values) into local variables so you can easily inspect them in the debugger
Replace the random color by a predefined color (COLOR.YELLOW), to rule out the random element
Replace the caclulated rectangle by a fixed rectangle (say (10,10) - (20,20)) to rule out the coordinate calculations.
Replace the loop, to rule out the loop.
Your rect has a width of 0px. The parameters of the set() function are, in order, left/top/right/bottom. You use the same value for left and right, so the width is (right-left)=0.
Let's see your coordinates, first:
myRect1.set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());
Top left corner has the same x coordinate as the bottom right corner, so you are drawing a rectangle with 0 width.
Add this line
myRect[j] = new Rect()
before
myRect[j].set(myCanvas.getWidth()/5*j, 0, myCanvas.getWidth()/5*j, myCanvas.getHeight());

Android screen coordinate system : how to set (0,0) at the bottom left side of android screen as first quadrent of xy plane

how to set the screen coordinate system of android screen as first Quadrant of the XY plane
,iwant the (0,0) position to be at bottom left , and i wanna know if i can use the trignometric equation on android screen as Android XY plane is not like the Xy plane
I don't think there's a way to do it that would affect the entire system, such as the XML layout files. But if you just want to draw with a Canvas, you can use translate() and scale().
First use translate() to slide the canvas down so 0,0 is at the bottom. Now the top of the screen would be a negative number, so call scale() to flip it around. Now 0,0 is still at the bottom, and the top of the screen is a positive number.
I'm working with information from this answer and its comments. Use something like:
canvas.save(); // need to restore after drawing
canvas.translate(0, canvas.getHeight()); // reset where 0,0 is located
canvas.scale(1, -1); // invert
... // draw to canvas here
canvas.restore(); // restore to normal
And yes, you can use normal 2D trigonometric functions with the XY coords. You can do it even if they're not translated, you just have to think it through more carefully.
I don't know that you're going to have much luck changing where (0,0) is located, but you could set a constant that accounts for such. myY = y minus screenHeight so (x, myY) adjusts y to the bottom of the screen and works from there +/-.
look up canvas.scale(xs,ys,xp,yp)
xp and yp are the new coordinates that you set for your (0,0) point.

Categories

Resources