Android Question Problem with relating transparent panel touch coordinates to image underneath it

Danamo

Member
Licensed User
I understand the imageview doesn't have a touch event, but this can be simulated by creating a transparent panel over it and getting the touch event for the panel instead.

That's fine for simply being able to detect a touch event "on" the imageview, but I need the X and Y coordinates from the touch as well, to use with the underlying imageview.

My problem is that even though the panel and the imageview have the same top,left,width, and height, (in dip units,) the X/Y coordinates reported by the panel touch event don't correspond to the specified width/height of the panel but instead, it seems, are relative to the entire screen's dimensions?

In Windows Visual Basic one could get image-relative x/y coordinates with the picturebox mouse_down event. Is there no simple way to accomplish this with a touch event in B4A? If not, please add my name to the wish list for an imageview touch event :)
 

klaus

Expert
Licensed User
Longtime User
The coordinates in the Panel_Touch event are relative to the upper left corner of the Panel which has the coordinates 0, 0.
So, if you put the Panel exactly over the ImageView, the coordinates given in the Panel_Touch event are the same as the coordinates in the ImageView. These coordinates are in pixels.
These pixel coordinates are not the same as the original bitmap pixel coordinates, because the bitmap dimensions may be converted to the ImageView dimensions.

Another option could be to not use an ImageView but only a Panel with a Canvas and draw the bitmap directly onto the Panel.
 
Upvote 0

Danamo

Member
Licensed User
The coordinates in the Panel_Touch event are relative to the upper left corner of the Panel which has the coordinates 0, 0.
So, if you put the Panel exactly over the ImageView, the coordinates given in the Panel_Touch event are the same as the coordinates in the ImageView. These coordinates are in pixels.
These pixel coordinates are not the same as the original bitmap pixel coordinates, because the bitmap dimensions may be converted to the ImageView dimensions.

Another option could be to not use an ImageView but only a Panel with a Canvas and draw the bitmap directly onto the Panel.
Thanks for your response, Klaus.

The thing is, the panel IS exactly over the imageview - they have the same top and left coordinates in dip, and they are both the same size (300 dip wide and 30 dip high.) So I would expect that touching the panel near the center would give an X value of around 150, and touching it near the right edge would give an X of around 300. But instead, the X value reported by touching the panel near the right edge is around 480. NONE of the panel touch X coordinates are the same as the X coordinates of the underlying imageview.

The imageview is actually just a blank white rectangle. It doesn't have any "picture" in it to begin with. I am using bitmap creator to draw shapes into a new blank bitmap of the same size and then setting the bitmap to the imageview. So when I touch the panel at, say, x=100, y=15 I want to reference those same coordinates in the bitmap.

Is this perhaps not the correct way to do something like this? I should use a canvas instead of an imageview? I know I am not too smart, and I'm stuck in the old Visual Basic 6 way of drawing in picturebox, so all these new things with panels, canvases and bitmap creator, etc, are a bit confusing to me!
 
Upvote 0

Danamo

Member
Licensed User
It may be overkill for what you want but my ScaleImageView can report touch event co-ordinates.
https://www.b4x.com/android/forum/threads/scaleimageview-pan-and-zoom-large-images.102190/#content
Your ScaleImageView is quite excellent, and I thank you for taking the time to respond to my question. I know you devote a lot of your considerable talents to benefit this community and I appreciate that as well!

But, as you say, your ScaleImageView is overkill for what I want to do. I just want to touch the screen over an image or specific area on the screen and get the touch coordinates relative to that image area... where the image isn't a scaled-down bitmap of a whole country or anything like that, but just a simple blank rectangle the same size as the area which I'm going to draw on.

I was trying to apply drawing with Bitmap Creator to an imageview but Maybe as Klaus suggested I should be using drawing to Canvas instead for what I'm trying to do.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Your problem, as agraham already mentioned, is this: The dimensions of your views are: 300dip wide and 30dip high.
You are forgetting the scale of the dip.
That's the reason why I wrote in post#2: These coordinates are in pixels.
To get dip values you need to divide the X and Y values in the Touch event by GetDeviceValues.Scale.
But for me, this is for sure not a good solution.
If the scale is different from 1 what do you want to do with dip values.
Especially when the scale is 1.5! You have 3 pixels for 2 dips !?
Another question: Do you have AutoScale activated in the Designer? This changes the Width and the Height!
The Touch event provides also X and Y values outsides the Panel.
If the current touch is at the left and above, X and Y are negative.
So, if you want to treat only values insides the Panel you need to add a limit check.
 
Last edited:
Upvote 0

Danamo

Member
Licensed User
Maybe you are suffering a dip to absolute pixel scaling problem. See if there is a constant scaling between what you expect and what you see.

What's constant is that the X value reported by the touch is related to the screen's x coordinate, not the panel's. Whereas, the Y coordinate reported IS related (somewhat) to the panel.

I made a simple little activity to demonstrate the problem:
B4X:
Sub Globals
    Dim Panel1 As Panel
    Private ImageView1 As ImageView 'the image here is just a white box to show me the  area on the screen where the panel will be located and onto which bitmaps drawn later will be placed
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("TestPanel") 'The layout has only the ImageView1 located at 10,100 and width = 300, height = 30
End Sub

Sub Activity_Resume
    Panel1.Initialize("p1")
    Panel1.Color = Colors.Transparent
    Activity.AddView(Panel1,10dip,100dip, 300dip, 30dip)
End Sub

Sub p1_Touch(Action As Int, X As Float, Y As Float)
    Log("X = " & x & ", y = " & Y)
End Sub

Now, if I touch the panel in it's approximate center, it should log X as approximately 150, or if I touch near the right end, X should be around 300, right?

Instead, touching the panel near the center I get values like X = 233.48233032226563, y = 7.0416259765625 and if I touch the panel near the right edge I get
X = 434.064453125, y = 35.6397705078125.

X = 434 is WAY outside of the panel's width of 300!

Maybe my phone is just weird or messed up? But when I draw with Bitmap Creator and place the drawing into the imageview there's no problem with scaling???
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Now, if I touch the panel in it's approximate center, it should log X as approximately 150, or if I touch near the right end, X should be around 300, right?
No.
My device has a scale of 3.
So 200dip equals 600 pixels !!!
Look at my previous post.
Attached a very small test project showing my comments in post #7.
 

Attachments

  • TestTouch.zip
    8.9 KB · Views: 266
Upvote 0

Danamo

Member
Licensed User
Your problem, as agraham already mentioned, is this: The dimensions of your views are: 300dip wide and 30dip high.
You are forgetting the scale of the dip.
That's the reason why I wrote in post#2: These coordinates are in pixels.
To get dip values you need to divide the X and Y values in the Touch event by GetDeviceValues.Scale.
But for me, this is for sure not a good solution.
If the scale is different from 1 what do you want to do with dip values.
Especially when the scale is 1.5! You have 3 pixels for 2 dips !?
Another question: Do you have AutoScale activated in the Designer? This changes the Width and the Height!
The Touch event provides also X and Y values outsides the Panel.
If the current touch is at the left and above, X and Y are negative.
So, if you want to treat only values insides the Panel you need to add a limit check.

Ah, GetDeviceValues.Scale and use that to relate the touch coordinates to the image? I think I begin to see the light and that should work for what I'm trying to do! I don't mind a little rounding error for 1.5 pixels, as long as the value is at least in the ballpark it doesn't have to be exact. And yes, I do have AutoScaleAll in the designer. Thank you Klaus - and agraham - for helping me with this. What you've explained is a big help and I should be able to figure it out now. I'm a slow learner so I really appreciate that you took the time and patience to advise me!
 
Last edited:
Upvote 0

Danamo

Member
Licensed User
Ah, GetDeviceValues.Scale and use that to relate the touch coordinates to the image?
A really simple (maybe too simple) solution I came up with, thanks to Klaus and agraham tips about pixels and dips (and also something posted by Dominex years ago) is...
to get the scale = 100dip/100
and then divide the Panel Touch X value by that scale. This results in X values which are close enough for me! The Y value when doing this is logged as "infinity" ? but I'm only using the X coordinate anyway so I don't care about that.
 
Upvote 0
Top