Odd problem matching sprite height to canvas

Hi,

I'm working on a complicated app that allows users to design woodworking joinery and send commands to a CNC once the design is completed. Measurements are taken by comparing sprite dimensions to the canvas they are on, so accuracy is sprite size and placement is important.

I have an issue where if I make a sprite the same height as the canvas, and make its y position 0, there is sometimes a gap at the bottom between the sprite and canvas, when they should be the exact same height. Playing further, this gap disappears if the canvas height is set to a number of pixels that is divisible by 4. I don't know why, but it seems to work correctly with any canvas height as long as it is divisible by 4.

I made simple project to demonstrate this. Please see below:

Canvas height set to number not evenly divisible by 4
403

Results in approximately 1 pixel difference between sprite and canvas in app

zoomed in showing difference
403 app zoom

Canvas height set to number evenly divisible by 4
404

No gap between sprite and canvas

pic for sprite I used
sprite

My workaround for this is just to make sure the height of the canvas is always divisible by 4. I just found the behavior odd and was wondering if there was a reason behind it.

Hello Rich

Given that you are only using integers, I'm also wondering why that is so. I also wonder if it is true with all types/makes of Android devices. What hardware are you testing?

Thanks for the reply. This problem appeared on a pixel 3a running on android 11. I just tried it on a n old kindle fire tablet and don't get mismatching heights.

Can you post your test project here? I'll try it on my Android 11 phone.

Try on different screen resolutions of your phone. You can find the resolution settings in the display settings.

The problem is occurring due to device density

in android height and width are set in the PX unit but we use the DP unit for flexibility so whenever we convert a value from DP to PX then thair is a possibility of lost some value because PX is int and density may be float.

2 Likes

You can also see this here

I think if we replace it with Math.round() then there is some possibility to reach near to solution but again I want to say this is not a perfect solution.

1 Like

If you want to check device Metrix then you can use this this extension
DeviceMetrics.aix (8.4 KB)

1 Like

test_canvas.aia (4.8 KB)

Thanks!

Hello again Rich

I think Parva has hit the nail on the head.
https://medium.com/analytics-vidhya/what-is-the-difference-between-px-dip-dp-and-sp-e4351fefa685#:~:text=dp%20or%20dip%20%20Density-independent,not%20necessarily%20in%20direct%20proportion.

dp or dip ( Density-independent Pixels) — an abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi screen, so one dp is one pixel on a 160 dpi screen. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion.

2 Likes

So, interesting thing - the test uses a height of 202 (not evenly divided by 4), so the expected result is a fail - but on my Huawei it is correct. :thinking:

I have tested fixed and responsive mode. The default is responsive and that is "allowed" to tweak sizes so that the GUI will fit as many device sizes and shapes as possible.

So, on the pixel 3a, set the Screen Property 'Sizing' to 'Fixed' - what do you get if the height is 202?

Thank you for trying it. The issue remains when I changed the sizing to 'fixed.' The issue also remains when I changed the screen size in settings. I have it working by just automatically readjust the canvas height to be divisible by 4. I may distribute the app in the future and would like to make it work universally for everyone that uses it.

Thank you all for helping me with this.

Parva, are you saying that appinventor when it builds the code for the apk converts from PX to DP/ vice versa when communicating with android? I'm not sure how I would account for this within app inventor.

@Rich_Want this problem also happened with android studio.

I uploaded extension for device metrix can you post data for your device metrix ? so that I can explain more.

app inventor use DP to PX conversation let me explain...

suppose you have one visible component so whenever you set height or width it takes DP value and then convert into PX and set to visible component.

1 Like

Thank you. Here are the results from the extension:

In Case of 404 :

DP = 404
PX = (int) (404 * 2.75) = 1111 (Actual value which set by android because 404 * 2.75 is int value there is no loss of value)

In Case of 403:

DP = 403
PX = 403 * 2.75 = 1108.25 ~= 1108(Actual value set by android because 1108.25 is float and PX always int.)

In this block see second block
SET ImageSprite1.Height to Canvas1.Height

Canvas1.Height = 1108 now convert it into DP

DP = 1108 / 2.75 = (int) 402.90 = 402

now you can see the difference between the actual Height of two different components you set 403 but you get 402 there is a loss of 1DP you can see this.

1 Like

@Rich_Want are you understand?

if no then check the app inventor source you will understand this logic.

Thank you very much for this explanation. It does make sense. I'd like to come up with a way of taking it into account within app inventor, but it doesn't seem like we can differentiate between int and float using blocks.

blocks

get value from these two block you will get your ans.
if loss not happen then you will get same result if losses happen then the result will not same.

Parva - what does not make sense is where two items are given the same dimensions but do not get drawn the same size. It should not matter if the units are pixels, millimeters or bananas, if I dimension two items to exactly the same value in the same units, they should be drawn the same size....

So I suspect there might be a difference along the way between the canvas and the sprites, perhaps something that should not be there but has not been noticed, because it doesn't matter for the purposes of Apps like games.

Another possibility is the Pixel 3a device itself has a firmware niggle. We need more people to test different devices but currently only the Pixel 3a exhibits the issue.

1 Like

@ChrisWard Actually what @preetvadaliya mentioned does explain this. The canvas and image sprite do not have the same height inspite of having same units as some information is lost when Canvas1.Height is called. Internally data is being transformed from one format to another hence the error. The call to Canvas1.Height rounds off PX to nearest integer. It is at this point that one off pixel error is introduced.

2 Likes