41

I have several Views on an Activity which a user wants to touch quickly in succession and I capture these touches using a TouchListener and handling MotionEvent.ACTION_DOWN. However, if the user is using two hands, it's very likely that the next View will be 'Touch'ed before the user pulls the previous finger up. In this scenario, a MotionEvent.ACTION_MOVE is fired for the first view rather than the desired MotionEvent.ACTION_DOWN for the second view.

Is there any way to work around or prevent this behavior? I've tried dispatching a new event with MotionEvent.ACTION_UP and also removing the event listener but neither seem to work.

kameny
  • 2,372
  • 4
  • 30
  • 40
cachance7
  • 903
  • 1
  • 10
  • 23

9 Answers9

88

The easiest way I found to force single touch across an entire app is to set it using a theme:

<style name="MyTheme" parent="@android:style/Theme.Holo.Light">
    <item name="android:windowEnableSplitTouch">false</item>
    <item name="android:splitMotionEvents">false</item>
</style>

Manifest:

  <application
        android:label="@string/app_name"
        android:theme="@style/MyTheme" >
Jeremie D
  • 4,145
  • 1
  • 35
  • 41
29

if someone still searching for best solution, put in the xml the following code :

android:splitMotionEvents = false 
Oren Zakay
  • 519
  • 8
  • 17
7

I did it like this :

@Override
public boolean onTouchEvent(MotionEvent event) {
    // TODO Auto-generated method stub

    if(event.getPointerCount() > 1) {
        System.out.println("Multitouch detected!");
        return true;
    }
    else
        return super.onTouchEvent(event);
}

I think you can override onTouchEvent for any view.

Pijetren
  • 159
  • 1
  • 9
3

The best way to work around this scenario is to use a ViewGroup and implement the onInterceptTouchEvent method to manually route the touch events as you see fit.

This was originally answered here: Android multitouch! hack anyone?

Code implementing this solution (found in the comments section of the answer to the above question) is found here: http://pastebin.com/hiE1aTCw

Community
  • 1
  • 1
cachance7
  • 903
  • 1
  • 10
  • 23
2

Override dispatchTouchEvent and intercept all touches there, for all multi touches the pointercount is more than one.

 if(ev.getPointerCount() > 1)
  {
     Log.d("Multitouch detected!");
     ev.setAction(MotionEvent.ACTION_CANCEL);
  }

This cancels the touches and clears the pressed state of the buttons without taking any further action.

  • First time it work, second time when I make multitouch then I make one touch it's not detected. – Mimouni Dec 29 '20 at 17:21
2

I have solved this using a custom method - which I did not want to do If anyone finds a better way I'd like to hear about it Thanks:

public static void setViewGroupEnebled(ViewGroup view, boolean enabled)
{
    int childern = view.getChildCount();

    for (int i = 0; i< childern ; i++)
    {
        View child = view.getChildAt(i);
        if (child instanceof ViewGroup)
        {
            setViewGroupEnebled((ViewGroup) child,enabled);
        }
        child.setEnabled(enabled);
    }
    view.setEnabled(enabled);
}
1

For me it worked like this. I just put this line in all active styles in my app

<item name="android:splitMotionEvents">false</item>

my style for example

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
      <item name="android:splitMotionEvents">false</item>
</style>

<style name="AppTheme.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
      <item name="android:splitMotionEvents">false</item>
</style>
AllanRibas
  • 678
  • 5
  • 14
0
int currentapiVersion = android.os.Build.VERSION.SDK_INT;

            if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {

                horizentalLinearGridItem.setMotionEventSplittingEnabled(false);

            }

Here horizentalLinearGridItem is parentLayout view where we insert child views. In my code its LinearLayout. In this LinearLayout I added child views. But when I clicked two child views simultaneously, both were getting the events. To block that I used the above code.

Abhijit Kurane
  • 834
  • 15
  • 20
0

I got it to work for me by just adding some code in OnTouchEvent method,

boolean action_down_required = false;

@Override
public boolean onTouchEvent(MotionEvent event) {

    int action = event.getAction();

    if(event.getPointerCount() > 1){
        action_down_required = true;
        return true;
    }

    if(action_down_required){
        action = MotionEvent.ACTION_DOWN;
    }

    switch (action) {
        case MotionEvent.ACTION_DOWN:

            // your code goes here...

            action_down_required = false;
            break;

        // Other events...
mejariamol
  • 78
  • 5