2011-01-17 15 views
6

Como desarrollador, tiendo a programar primero y luego a investigar más tarde. Estaba tratando de implementar una pantalla que manejaría múltiples entradas de usuario. Básicamente mapee más de un dedo. Intenté dos cosas ...Android multitouch?

Tuve una clase de actividad que implementó OnTouchListener. Aquí tuve dos vistas secundarias separadas que agregaban la actividad como sus oyentes directos. Y luego tuve una línea de impresión que imprimió event.getPointerCount() e imprimí la ubicación de cada uno de los punteros.

Lo descargué en el teléfono y lo probé. Noté que los punteros nunca crecieron más que dos. Incluso noté que si un dedo estaba en un niño y otro dedo en el otro niño ven que los eventos solo llegaron al primer componente infantil. Luego traté de poner detectores por separado en cada uno de los componentes secundarios para ver si eso funcionaría pero actuó de la misma manera.

Por lo tanto, parece que el android solo admite un total de dos entradas de usuario cuando se trata de entradas del usuario que toca la pantalla.

¿Es esto cierto? Parece de las pruebas e investigaciones que este es el caso.

Alguien ha encontrado esta limitación. ¿Alguna solución inteligente?

Gracias por su tiempo y respuestas.

dk

Respuesta

7

El número de puntos de contacto soportado es dependiente en el dispositivo. En todas las versiones actualmente disponibles de Android MotionEvent s se envían a una única vista de destino y describen el estado de todos los puntos de contacto actualmente activos. La vista de destino está determinada por dónde se produce el primer evento MotionEvent.ACTION_DOWN.

Ver el post Making Sense of Multitouch en el blog de Desarrolladores de Android para obtener una visión general rápida del trabajo con eventos multitouch en Android.

+0

Gracias por la URL, que ayudó aclarar algunas cosas. Pero tenía que verlo por mí mismo. Entonces, escribí una aplicación simple para probar lo que se dijo en el artículo. Agregará el código a la respuesta automática a esta pregunta. – dakira

3

Escribí una aplicación muy simple para probar el toque múltiple en mi teléfono HTC Incredible. Me comporto más o menos como pensé y me gusta mucho la URL dada por adamp. Mi resultado es que el teléfono solo podía manejar dos entradas de dedo. Tengo para caja que cada uno tiene su propio OnTouchListener. Cuando hago clic en cada cuadro, imprimo un texto para cada uno. Al hacer clic en cada evento táctil, pero con mi dedo índice hice clic en cualquier parte de la pantalla, recibí dos punteros. Desde el método MotionEvent event.getPointerCount. No importaba dónde el segundo dedo aterrizó. Podría haber estado fuera de la vista original que recibió el evento de primer dedo hacia abajo. De todos modos aquí está el código si te gusta probarlo tú mismo.

Tengo un 7z de todo el proyecto, pero no creo que pueda adjuntarlo.

Por lo tanto, aquí está la actividad principal y el xml para el diseño.

package com.multitouch; 

import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 
import android.widget.LinearLayout; 
import android.widget.TextView; 

public class MultiTouch extends Activity { 
    protected LinearLayout sq1; 
    protected LinearLayout sq2; 
    protected LinearLayout sq3; 
    protected LinearLayout sq4; 

    protected String sqText = new String(); 
    protected String sq1Text = new String(); 
    protected String sq2Text = new String(); 
    protected String sq3Text = new String(); 

    private Handler handler = new Handler(); 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     setViews(); 
     handler.postDelayed(mUpdateUITimerTask, 5000); 
    } 

    private final Runnable mUpdateUITimerTask = new Runnable() { 
     public void run() { 
      // do whatever you want to change here, like: 
      updateTextField(); 
     } 
    }; 

    private void updateTextField() { 
     TextView view1 = (TextView) this.findViewById(R.id.logView); 
     TextView view2 = (TextView) this.findViewById(R.id.logView1); 
     TextView view3 = (TextView) this.findViewById(R.id.logView2); 
     TextView view4 = (TextView) this.findViewById(R.id.logView3); 


     //view1.append(sqText + "\n"); 
     view1.setText(sqText); 
     view2.setText(sq1Text); 
     view3.setText(sq2Text); 
     view4.setText(sq3Text); 

     handler.post(mUpdateUITimerTask); 
    } 

    private void setViews() { 
     sq1 = (LinearLayout) this.findViewById(R.id.square1); 
     sq2 = (LinearLayout) this.findViewById(R.id.square2); 
     sq3 = (LinearLayout) this.findViewById(R.id.square3); 
     sq4 = (LinearLayout) this.findViewById(R.id.square4); 

     sq1.setOnTouchListener(new TouchListener()); 
     sq2.setOnTouchListener(new TouchListener()); 
     sq3.setOnTouchListener(new TouchListener()); 
     sq4.setOnTouchListener(new TouchListener());   
    } 

    private class TouchListener implements OnTouchListener { 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      if(event.getPointerCount()>2) { 
       sq1Text = "GOT THREE POINTERS!!"; 
       sq2Text = "GOT THREE POINTERS!!"; 
       sq3Text = "GOT THREE POINTERS!!"; 
       sqText = "GOT THREE POINTERS!!"; 
      } 

      if(event.getAction() == MotionEvent.ACTION_DOWN){ 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 Pressed::Pointer count = " + String.valueOf(event.getPointerCount()); 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 Pressed::Pointer count = " + String.valueOf(event.getPointerCount()); 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 Pressed::Pointer count = " + String.valueOf(event.getPointerCount()); 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 Pressed::Pointer count = " + String.valueOf(event.getPointerCount()); 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_POINTER_DOWN || 
         event.getAction() == MotionEvent.ACTION_POINTER_UP) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 Pointer Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 Pointer Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 Pointer Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 Pointer Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_POINTER_1_DOWN) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 Pointer1Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 Pointer1Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 Pointer1Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 Pointer1Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_POINTER_2_DOWN) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 Pointer2Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 Pointer2Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 Pointer2Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 Pointer2Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 Pointer3Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 Pointer3Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 Pointer3Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 Pointer3Down::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_UP) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 UP::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 UP::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 UP::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 UP::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } else if(event.getAction() == MotionEvent.ACTION_MOVE) { 
       switch(v.getId()) { 
        case R.id.square1: 
         sqText = "Square 1 MOVE::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square2: 
         sq1Text = "Square 2 MOVE::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square3: 
         sq2Text = "Square 3 MOVE::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
        case R.id.square4: 
         sq3Text = "Square 4 MOVE::Pointer count = " + String.valueOf(event.getPointerCount()) + "\n"; 
        break; 
       } 
      } 


      // TODO Auto-generated method stub 
      return true; 
     } 

    } 
} 

Diseño:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:gravity="center_horizontal" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:id="@+id/MainLay" > 

    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical" 
     android:gravity="center_horizontal" android:padding="10dip"> 


     <TableRow android:gravity="center_horizontal" android:padding="10dip"> 
      <LinearLayout android:background="#FFFF00" android:id="@+id/square1" android:padding="10px" android:layout_width="125px" android:layout_height="125px"/> 
      <LinearLayout android:background="#FF00FF" android:id="@+id/square2" android:padding="10px" android:layout_width="125px" android:layout_height="125px"/> 
     </TableRow> 

     <TableRow android:gravity="center_horizontal" android:padding="10dip"> 
      <LinearLayout android:background="#00FFFF" android:id="@+id/square3" android:padding="10px" android:layout_width="125px" android:layout_height="125px"/> 
      <LinearLayout android:background="#eeeeee" android:id="@+id/square4" android:padding="10px" android:layout_width="125px" android:layout_height="125px"/> 
     </TableRow>  


      <TextView android:id="@+id/logView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 
      <TextView android:id="@+id/logView1" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 
      <TextView android:id="@+id/logView2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 
      <TextView android:id="@+id/logView3" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 



    </TableLayout> 

</LinearLayout> 

Buena suerte, y si se intenta Avísame si obtiene el GOT triples !! imprimir declaraciones Me pregunto qué teléfonos lo admiten.

gracias, dk

+0

Galaxy S parece admitir hasta cinco contadores. Demostrado por alguien de un foro diferente utilizando el software anterior. – dakira

+0

Uso de un LG optimus. Detecta solo 1 contador – Brahadeesh

0

que editan @dakira respuesta.Aquí está el código de mi muestra:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/MainLay" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:gravity="center_horizontal" 
    android:orientation="vertical"> 


    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content"> 

     <TextView 
      android:id="@+id/tvHeader" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:gravity="center" 
      android:padding="4dp" 
      android:text="Place Your Finger on Squire" 
      android:textColor="#000" 
      android:textSize="20sp" /> 

     <LinearLayout 
      android:id="@+id/llStatusHolder" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_below="@+id/tvHeader" 
      android:orientation="vertical" 
      android:weightSum="2"> 

      <LinearLayout 
       android:layout_width="match_parent" 
       android:layout_height="wrap_content" 
       android:orientation="horizontal" 
       android:padding="8dp" 
       android:weightSum="2"> 

       <TextView 
        android:id="@+id/tvBox1" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:layout_weight="1" 
        android:background="#FFFF00" 
        android:gravity="center" 
        android:padding="4dp" 
        android:text="Finger : 0" 
        android:textColor="#000" 
        android:textSize="28sp" /> 

      </LinearLayout> 

     </LinearLayout> 


     <LinearLayout 
      android:id="@+id/square1" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_margin="4dp" 
      android:layout_below="@+id/llStatusHolder" 
      android:layout_weight="1" 
      android:background="#FFFF00" 
      android:orientation="horizontal" 
      android:padding="10dp"> 

     </LinearLayout> 

     </RelativeLayout> 
    </LinearLayout> 

Aquí está el código de Java:

import android.app.Activity; 
import android.os.Bundle; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.View.OnTouchListener; 
import android.widget.LinearLayout; 
import android.widget.TextView; 


public class MultiTouchTestActivity extends Activity { 
    protected LinearLayout sq1; 

    TextView tvBox1; 
    int counter1 = 0; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_multi_touch_test); 
     setViews(); 
    } 

    private void updateTextField() { 

     tvBox1.setText("Finger : " + counter1); 

    } 

    private void setViews() { 
     tvBox1 = (TextView) findViewById(R.id.tvBox1); 
     sq1 = (LinearLayout) this.findViewById(R.id.square1); 

     sq1.setOnTouchListener(new TouchListener()); 

    } 

    private class TouchListener implements OnTouchListener { 

     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      if (event.getAction() == 1) { 
       setCounterValue(1, 0); 
      }else if (event.getAction() == MotionEvent.ACTION_DOWN) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_POINTER_DOWN || 
        event.getAction() == MotionEvent.ACTION_POINTER_UP) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_POINTER_1_DOWN) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_POINTER_2_DOWN) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_POINTER_3_DOWN) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_UP) { 
       setCounterValue(1, event.getPointerCount()); 
      } else if (event.getAction() == MotionEvent.ACTION_MOVE) { 
       setCounterValue(1, event.getPointerCount()); 
      }else if (event.getAction() == MotionEvent.ACTION_BUTTON_RELEASE) { 
       setCounterValue(1, 0); 
      } 
      updateTextField(); 
      return true; 
     } 
    } 

    void setCounterValue(int hasvalue, int value) { 
     switch (hasvalue) { 
      case 1: 
       counter1 = value; 
       break; 
     } 
    } 
} 

Hope esto va a resolver muchos problemas personas :)

enter image description here

Cuestiones relacionadas