2017-02-09 2 views
0

Все казалось отличным с моей навигационной системой мультитач в Android, пока я не обнаружил, что не всегда, но иногда, когда палец был выпущен, тогда это событие было не признанных в ядре приложения.getPointerCount() не всегда распознает, что указатель был выпущен

Я наложил на экран следы, и я понял, что во время поднятия пальца, в то время как другие пальцы не меняют свое положение (даже не одним пикселем в x или в y топор), тогда getPointerCount () не уменьшает его значение, как должно, но возвращает правильное значение, как только один из других пальцев слегка перемещается.

Bellow - это код, который имитирует этот эффект (завершенный, очень простой одноклассный проект), а APK также доступен для ручной установки (www.liknongames.com/apps/MultiTouch.apk). Пожалуйста, для вашей обратной связи, так как это проблема остановки для меня.

Приложение в apk сообщает в текстовом виде заголовка (textView [0]) активные указатели, текущее действие (замаскированное и не замаскированное) и счетчик вызовов метода onTouchEvent().

package com.example.moultitouch; 

import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.Display; 
import android.view.MotionEvent; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

public class MainActivity extends Activity 
{ 
    TextView[] textView = new TextView[6]; // 0:common metrics 1-5:finger details 
    int pointersCount = -1; 
    int action = 0; 
    int actionMasked = 0; 
    String actionString = "NOT INIT"; 
    Display display; 
    int iViewWidth = 0; 

    int motionsCounter = 0; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_motion_event); 
     display = getWindowManager().getDefaultDisplay(); 
     iViewWidth = display.getWidth(); 
     LinearLayout layout = new LinearLayout(this); 
     layout.setOrientation(LinearLayout.VERTICAL);  

     for (int i = 0; i < 6; i++) 
     { 
      textView[i] = new TextView(this); 
      textView[i].setWidth(iViewWidth); 
      textView[i].setTextSize(16); 
      textView[i].setTextColor(Color.WHITE); 
      textView[i].setBackgroundColor(Color.BLACK); 
      layout.addView(textView[i]); 
     } 
     textView[0].setText("Touch the screen to start"); 
     setContentView(layout); 
    } 

@Override 
public boolean onTouchEvent(MotionEvent event) 
{ 
    int i = 0; 
    pointersCount = event.getPointerCount(); 
    action = event.getAction() & MotionEvent.ACTION_MASK; 
    motionsCounter++; 
    actionMasked = event.getActionMasked(); 
    if (action == MotionEvent.ACTION_DOWN) 
     actionString = "DOWN"; 
    else if (action == MotionEvent.ACTION_POINTER_DOWN) 
     actionString = "POINTER DOWN"; 
    else if (action == MotionEvent.ACTION_POINTER_UP) 
     actionString = "POINTER UP"; 
    else if (action == MotionEvent.ACTION_MOVE) 
     actionString = "MOVE"; 
    else if (action == MotionEvent.ACTION_UP) 
    { 
     actionString = "ALL UP"; 
     pointersCount = 0; 
    } 
    else 
     actionString = "UNKNOWN(" + action + ")"; 

    textView[0].setText (pointersCount + " POINTERS. ACTION:[" + action +"] " + actionString + ". (MASKED:" + actionMasked +"). " + motionsCounter + " MOTIONS"); 

    for (i = 0; i < pointersCount; i++) 
    { 
     int x = (int) event.getX(i); 
     int y = (int) event.getY(i);    
     int id = event.getPointerId(i); 
     textView[i+1].setText("idx: " + i + " id: " + id + ". (" + x + "," + y +")"); 
    } 
    for (i = pointersCount; i < 5; i++) 
     textView[i+1].setText("- - - - - "); 
    return true; 
} 
} 

спасибо

ответ

0

наконец, я нашел его! Действительно, проблема с методом остается и всякий раз, когда пользователь помещает два пальца и поднимает один, сохраняя при этом другой абсолютно неподвижным на экране, тогда getPointerCount() все равно возвращает 2, а не 1, пока оставшийся палец слегка не изменит свое положение даже на делая небольшое изменение давления. Исправление, следовать этому алгоритму:

1: В каждом сенсорном случае, сохранить в массиве х/у координаты для всех указателей и для всех зарегистрированных графа указателей (не имеет значения, если это правильно или нет)

2: вызвать getActionIndex(), чтобы получить индекс указателя, который последний раз реагировал на экране.

3: в случае, если действие (в маске) ​​ACTION_POINTER_UP, сравните указатель с предыдущим значением. Если это то же самое, тогда это тот случай, когда «... вмешивайся, мы должны!» Итак, в этом случае, начиная с этого индекса, вытащите все элементы в массивы x/y с координатами по одному индексу.

  1. вручную, уменьшить на 1 переменную, которая хранит указатели.

Вопрос закрыт. Спасибо.

package com.example.moultitouch; 

import android.app.Activity; 
import android.graphics.Color; 
import android.os.Bundle; 
import android.view.Display; 
import android.view.MotionEvent; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

public class MainActivity extends Activity 
{ 
final static int MAX_SUPPORTED_POINTERS = 5; 

TextView[] textView = new TextView[MAX_SUPPORTED_POINTERS+1]; // 0:common metrics 1-5:finger details 
Display display; 

int pointersCount  = 0; 
int prevPointersCount = 0; 
int actionMasked   = 0; 
int iViewWidth   = 0; 
int lastLiftedPointerIdx = 0; 

// just for tracing reason. 
String actionString = "NOT INIT"; 
String sHeader = ""; 
String sAlarm = ""; 
int motionsCounter = 0; 

int[] touch_x = new int[MAX_SUPPORTED_POINTERS]; 
int[] touch_y = new int[MAX_SUPPORTED_POINTERS]; 
int[] pointerID = new int[MAX_SUPPORTED_POINTERS]; 

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_motion_event); 
    display = getWindowManager().getDefaultDisplay(); 
    iViewWidth = display.getWidth(); 
    LinearLayout layout = new LinearLayout(this); 
    layout.setOrientation(LinearLayout.VERTICAL);  

    for (int i = 0; i < MAX_SUPPORTED_POINTERS+1; i++) 
    { 
     textView[i] = new TextView(this); 
     textView[i].setWidth(iViewWidth); 
     textView[i].setTextSize(16); 
     textView[i].setTextColor(Color.WHITE); 
     textView[i].setBackgroundColor(Color.BLACK); 
     textView[i].setText("_"); 
     layout.addView(textView[i]); 
    } 
    textView[0].setText("Touch the screen to start"); 
    bThreadForDisplay = true; 
    setContentView(layout); 
} 


@Override 
public boolean onTouchEvent(MotionEvent event) 
{ 
     int i = 0, j = 0; 
     prevPointersCount = pointersCount; 
     pointersCount = event.getPointerCount(); 
     pointersCount = pointersCount > MAX_SUPPORTED_POINTERS ? MAX_SUPPORTED_POINTERS : pointersCount; 

     // for ACTION_POINTER_DOWN or ACTION_POINTER_UP as returned by getActionMasked(), 
     // returns the associated pointer index. 
     lastLiftedPointerIdx = event.getActionIndex(); 
     actionMasked = event.getActionMasked(); 

     for (i = 0; i < pointersCount; i++) 
{ 
     int x = (int) event.getX(i); 
     int y = (int) event.getY(i);   
     touch_x[i] = x; 
     touch_y[i] = y; 
} 

     motionsCounter++; 
     if (actionMasked == MotionEvent.ACTION_DOWN) 
      actionString = "DOWN"; 
     else if (actionMasked == MotionEvent.ACTION_POINTER_DOWN) 
      actionString = "POINTER DOWN"; 
     else if (actionMasked == MotionEvent.ACTION_POINTER_UP) 
     { 
      if (prevPointersCount == pointersCount) 
      { 
       sAlarm = " ALARM ON ID " + lastLiftedPointerIdx; 
       for (int k = lastLiftedPointerIdx; k < pointersCount-1; k++) // from that point, elevate everything by one position 
       { 
        touch_x[k] = touch_x[k+1]; 
        touch_y[k] = touch_y[k+1]; 
        pointerID[k] = pointerID[k+1]; 
       } 
       pointersCount--; // correct the counter. 
       prevPointersCount = pointersCount; 
      } // alarm case 
      actionString = "POINTER UP"; 
     } 
     else if (actionMasked == MotionEvent.ACTION_MOVE) 
      actionString = "MOVE"; 
     else if (actionMasked == MotionEvent.ACTION_UP) 
     { 
      actionString = "ALL UP"; 
      pointersCount = 0; 
     } 
     else actionString = "UNKNOWN(" + actionMasked + ")"; 

     sHeader = pointersCount + " POINTERS. ACTION:[" + actionMasked +"] " + actionString + ". " + motionsCounter + " MOTIONS. " + sAlarm; 
     if (actionMasked == MotionEvent.ACTION_POINTER_UP) 
      sHeader += sAlarm; 
     textView[0].setText (sHeader); 

     for (i = 0; i < pointersCount; i++) 
      textView[i+1].setText("IDX: " + i + " ID: " + pointerID[i] + ". (" + touch_x[i] + "," + touch_y[i] +")"); 
     for (i = pointersCount; i < MAX_SUPPORTED_POINTERS; i++) 
      textView[i+1].setText("- - - - - "); 

    return true; 
} 
} 
Смежные вопросы