5
\$\begingroup\$

When using openGL to build a UI for my prototype I find that that I am still required to use pixels to capture touch events. To make matters worse the Android Docs make this subject slightly confusing. http://developer.android.com/guide/practices/screens_support.html specifically states:

You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.

Yet

MotionEvent event = new MotionEvent();
event.getX();

returns pixels when used to locate the touchscreen event. http://developer.android.com/reference/android/view/MotionEvent.html#getX()

To make matters even more confusing,

public final float getRawX ()

Added in API level 1 Returns the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.

Seems to imply that there are alterations being made to adjust for the window and views when using

event.getX()

My last bit of confusion comes in when trying to tie both of these concepts together. I see all the moving parts I am just unable to make them connect.

  • How to convert openGL vertices into terms that work with pixels or dp.
  • How to program for dynamic touch events using MotionEvent when pixel location will change by scale according to device density.
\$\endgroup\$
  • \$\begingroup\$ Well I seemed to have discovered that even if I am unable to solve this problem, there is a still a solution \$\endgroup\$ – Justin Jul 31 '13 at 16:32
2
\$\begingroup\$

I solved this by creating a custom class that creates an object that handles the touch events. In case anyone is curious as to how to go about this:

  1. Step one is to design your touch events for a 160 dpi device. This translates into one actual pixel for every density independent pixel. I would also suggest using a very small screen size in order to understand exactly how big your touch event areas need to be.

  2. Step two is to set up your custom touch handler class to get the device screen density on instantiate and pass this into your constructor. Use:

    context.getResources().getDisplayMetrics().density
    

    This will return the devices density. For a 160 dpi screen it will be 1, for 480dpi it will be 1.5, etc.. refer to Android Developer for the whole list.

  3. Step three is where the magic happens. You take the points of your desired touch location that you designed in step one, and build them based on the actual devices screen density. You do this by taking your density independent numbers (step 1) and multiplying them by the dynamically obtained device density (step 2) at run time.

    private int Convert_To_Device_Pixel(int pixel)
    {
    pixel = (int)(pixel * density);
    
    return pixel;
    }
    

This will return the pixel translated based on the devices dpi. It works for both x and Y coordinates. At this point you now have everything you need to build your touch events that will scale across all devices. You can take your

MotionEvent.getX();
MotionEvent.getY();

... and compare them to your now converted numbers from step 1 to determine if the device has been touched in that area. Keep in mind that this results in a touch area that will not grow on bigger screens or shrink on smaller ones. It will always be the same relative size.

Kudos to rajarko.com for helping me see the light.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.