How To: Identify which pointer moved in Android

Heads up: When I say pointer in this article, I mean a finger or a stylus – anything in contact with the touchscreen.

Multi-touch in Android is a bit of a strange beast, although you could argue that it’s by necessity. With ACTION_DOWN (primary pointer in contact) or ACTION_POINTER_DOWN (non-primary pointer in contact), or even the corresponding ACTION_UP or ACTION_POINTER_UP events it’s fine. But when it comes to ACTION_MOVE events – you can’t just ask which finger moved, all you’re told is that A finger moved, and you have to figure out which one for yourself as far as I can tell.

This is what I’ve come up with to figure out which pointer has actually moved – it falls behind by one ACTION_MOVE event because there doesn’t seem to be a way to ask for the current X location of a pointer by its index location (that is, there’s no getX(pointerIndex), only a getHistoricalX(pointerIndex, historyPosition)) – so this code misses the very first move event when a pointer moves – BUT – moving your finger generates a large number of move events, so I’m thinking this might not be that much of an issue.

Update: I’d forgotten you can getX(pointerIndex) and as well as getHistoricalX(pointerIndex, historyLocation) – so I’ve modified the code below to do that, which means I don’t think we miss any move events anymore because we’re now comparing current location to historical(0) rather than historical(0) to historical(1).

Anyway, here’s my code which addresses this finicky problem:

As I’ve been playing around with this it seems to match up with what I’m doing very well without issue, for example:

Alternative Solution

Keep a sparse array of whatever you’re keeping track of – for example, let’s say we’ve got the world’s simplest Circle class:

Then in your class handling the onTouchEvent() method you could have something like this (in this particular example we have a view which responds to multi-touch events):

This technique doesn’t miss any ACTION_MOVE events because it looks them up by pointerId in the SparseArray – which is potentially a nicer solution. Go with whatever works for you.

How-To: Fix IntelliJ / Android Studio screen display corruption

With my NVidia 980M w/ Optimus graphics card, Android Studio (which is IntelliJ-based) would often get itself in a state and the screen would get corrupted, which was incredibly frustrating to work with. Luckily there seems to be a pretty simple solution:

1 – Find your user folder

If you want to make this change on a per-user basis, then you’ll need to create a vmoptions file in the relevant user-directory. I’m doing this fix on Windows running 64-bit Android Studio so I’ve created the file: %USERPROFILE%\.{FOLDER_NAME}\studio64.exe.vmoptions

Depending on your operating system, the filename and locations are:

Windows:
%USERPROFILE%\.{FOLDER_NAME}\studio.exe.vmoptions and/or %USERPROFILE%\.{FOLDER_NAME}\studio64.exe.vmoptions

Mac:
~/Library/Preferences/{FOLDER_NAME}/studio.vmoptions

Linux:
~/.{FOLDER_NAME}/studio.vmoptions and/or ~/.{FOLDER_NAME}/studio64.vmoptions

Where FOLDER_NAME is something like AndroidStudio1.5 or such.

If you want to make the change on a global basis (although the config file doesn’t recommend this), then you can modify the studio.exe.vmoptions configuration file in the bin folder located wherever Android Studio is installed (on Windows this is likely to be “Program Files” for 64-bit or “Program Files (x86)” for 32-bit Android Studio). So for me the ‘global’ config file is: C:\Program Files\Android\Android Studio\bin\studio64.exe.vmoptions

Source: http://tools.android.com/tech-docs/configuration

2 – Add this switch

Save the file then restart Android Studio and the display corruption should be fixed!

Source: http://stackoverflow.com/a/27768329.

Wrap up and secondary workaround

This worked fine for me in Windows, but as the settings affect Direct3D, I’m somewhat doubtful that it’ll work in Linux or Mac. However, I did read about a workaround technique where you go into the NVidia Settings panel, select your java runtime and force it to always work in maximum performance mode, thus bypassing any use of Optimus which may also be causing the screen corruption – so should the above fix not work for you, then perhaps the workaround will.

Cheers!