cachance7
cachance7

Reputation: 943

Disable or prevent multitouch in Activity

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.

Upvotes: 42

Views: 44151

Answers (9)

AllanRibas
AllanRibas

Reputation: 1144

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>

Upvotes: 2

Chetna Priyadarshini
Chetna Priyadarshini

Reputation: 217

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.

Upvotes: 2

mejariamol
mejariamol

Reputation: 78

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...

Upvotes: 0

Oren Zakay
Oren Zakay

Reputation: 529

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

android:splitMotionEvents = false 

Upvotes: 29

Abhijit Kurane
Abhijit Kurane

Reputation: 844

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.

Upvotes: 0

Jeremie D
Jeremie D

Reputation: 4205

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" >

Upvotes: 91

Pijetren
Pijetren

Reputation: 159

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.

Upvotes: 7

cachance7
cachance7

Reputation: 943

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

Upvotes: 3

user647826
user647826

Reputation:

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);
}

Upvotes: 2

Related Questions