Отключить или запретить мультитач в Activity

У меня есть несколько представлений о действии, к которым пользователь хочет быстро прикоснуться, и я фиксирую эти касания, используя TouchListener и обрабатывая MotionEvent.ACTION_DOWN. Однако, если пользователь использует две руки, весьма вероятно, что следующее представление будет «касаться» до того, как пользователь потянет предыдущий палец вверх. В этом сценарии для первого представления запускается MotionEvent.ACTION_MOVE, а не желаемое MotionEvent.ACTION_DOWN для второго представления.

Есть ли способ обойти или предотвратить такое поведение? Я попытался отправить новое событие с помощью MotionEvent.ACTION_UP, а также удалить прослушиватель событий, но ни один из них не работает.


person cachance7    schedule 20.12.2011    source источник


Ответы (9)


Самый простой способ, который я нашел для принудительного однократного касания во всем приложении, — установить его с помощью темы:

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

Манифест:

  <application
        android:label="@string/app_name"
        android:theme="@style/MyTheme" >
person Jeremie D    schedule 26.03.2014
comment
Просто для информации: android:splitMotionEvents требует уровня API 11 и выше. - person gjman2; 26.09.2015
comment
Работает у меня в Android 5.0.1. - person Shubham A.; 01.03.2016
comment
Отлично работает даже на Android 8. - person Pointer Null; 10.12.2018

если кто-то все еще ищет лучшее решение, поместите в xml следующий код:

android:splitMotionEvents = false 
person Oren Zakay    schedule 27.10.2015
comment
Он должен быть помещен внутри макета. - person Vic; 26.08.2018
comment
Да, это работает! Вставьте его в макет, где вам нужно отключить мультитач. - person Boris Karloff; 02.12.2018
comment
используйте его в родительском макете, и он выполнит свою работу - person Harvinder Singh; 18.09.2019
comment
используйте это в макете, в котором есть интерактивные элементы, не размещайте его в самом верхнем макете/корневом представлении. - person Daniyal Javaid; 22.02.2021

Я сделал это так:

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

Я думаю, вы можете переопределить onTouchEvent для любого представления.

person Pijetren    schedule 06.09.2012

Лучший способ обойти этот сценарий — использовать метод ViewGroup и реализовать метод onInterceptTouchEvent для ручной маршрутизации событий касания по своему усмотрению.

Первоначально на это был дан ответ здесь: Мультитач для Android! взломать кого-нибудь?

Код, реализующий это решение (найденный в разделе комментариев ответа на вопрос выше), находится здесь: http://pastebin.com/hiE1aTCw

person cachance7    schedule 04.01.2012

Я решил это, используя собственный метод, который я не хотел делать. Если кто-нибудь найдет лучший способ, я хотел бы услышать об этом. Спасибо:

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);
}
person Community    schedule 20.12.2011

Переопределите dispatchTouchEvent и перехватите там все касания, для всех мультитачей количество указателей больше единицы.

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

Это отменяет касания и очищает нажатое состояние кнопок без каких-либо дальнейших действий.

person chetna priyadarshini    schedule 27.02.2017
comment
Первый раз работает, второй раз, когда я делаю мультитач, затем я делаю одно касание, оно не определяется. - person Mimouni; 29.12.2020

Для меня это работало так. Я просто поместил эту строку во все активные стили в своем приложении.

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

мой стиль например

<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>
person AllanRibas    schedule 28.08.2020

int currentapiVersion = android.os.Build.VERSION.SDK_INT;

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

                horizentalLinearGridItem.setMotionEventSplittingEnabled(false);

            }

Здесь horizentalLinearGridItem — это представление parentLayout, куда мы вставляем дочерние представления. В моем коде это LinearLayout. В этом LinearLayout я добавил дочерние представления. Но когда я щелкнул два дочерних представления одновременно, оба получали события. Чтобы заблокировать это, я использовал приведенный выше код.

person Abhijit Kurane    schedule 29.01.2015

Я заставил его работать на меня, просто добавив код в метод OnTouchEvent,

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...
person mejariamol    schedule 27.09.2016