Reputation: 943
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
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
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
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
Reputation: 529
if someone still searching for best solution, put in the xml the following code :
android:splitMotionEvents = false
Upvotes: 29
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
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
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
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
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