2011-01-17 9 views
6

Jako programista zazwyczaj najpierw programuję, a potem później. Próbowałem zaimplementować ekran, który obsługiwałby wiele wejść użytkownika. Zasadniczo zamapuj więcej niż jeden palec. Próbowałem dwóch rzeczy ..Android multitouch?

Miałem klasę aktywności, która zaimplementowała OnTouchListener. Tutaj miałem dwa oddzielne widoki podrzędne, które dodały aktywność jako ich słuchacze ontouch. I wtedy miałem drukowaną linię, która wydrukowała event.getPointerCount() i wydrukowała lokalizację każdego ze wskaźników.

Pobrałem go do telefonu i przetestowałem. Zauważyłem, że wskaźniki nigdy nie wzrosły powyżej dwóch. Zauważyłem nawet, że jeden palec znajdował się na jednym dziecku, a drugi na drugim, że tylko zdarzenia doprowadziły go do pierwszego elementu potomnego. Następnie próbowałem umieścić osobne detektory na każdym komponencie potomnym, aby sprawdzić, czy to zadziała, ale działało tak samo.

Wygląda więc na to, że Android obsługuje tylko dwa wejścia użytkownika, gdy ma do czynienia z wejściami od użytkownika dotykającego ekranu.

Czy to prawda? Wydaje się, że tak jest w przypadku testów i badań.

Czy ktoś wpadł na to ograniczenie. Każda sprytna praca wokół?

Dziękujemy za poświęcony czas i odpowiedzi.

dk

Odpowiedz

7

Liczba obsługiwanych punktów dotyku zależy od urządzenia. We wszystkich obecnie dostępnych wersjach Androida MotionEvent s są wysyłane do pojedynczego widoku celu i opisują stan wszystkich aktualnie aktywnych punktów dotyku. Widok docelowy jest określony przez miejsce pierwszego zdarzenia MotionEvent.ACTION_DOWN.

Zobacz post Making Sense of Multitouch na blogu programistów aplikacji na Androida, aby uzyskać szybki przegląd pracy z funkcjami multitouch na Androidzie.

+0

Dzięki za adres URL, to pomogło oczyść niektóre rzeczy. Ale musiałem to zobaczyć na własne oczy. Napisałem więc prostą aplikację, aby przetestować to, co zostało powiedziane w artykule. Doda kod do samodzielnej odpowiedzi na to pytanie. – dakira

3

Napisałem bardzo prostą aplikację do testowania wielu dotknięć na moim telefonie HTC Incredible. Zachowuję się prawie tak, jak myślałem i prawie podoba mi się adres URL podany przez Adampa. Moje wyniki są takie, że telefon mógł obsługiwać tylko dwa wejścia dla palców. Mam dla pola, z którego każdy ma swój własny OnTouchListener. Kiedy klikam każde pole, wydrukuję tekst dla każdego z nich. Kliknięcie każdego zdarzenia dotykowego, ale z moim palcem wskazującym, kliknąłem gdziekolwiek na ekranie, otrzymałem dwa wskaźniki. Z metody motionEvent event.getPointerCount. Nie ważne, gdzie wylądował drugi palec. Możliwe, że znajdował się poza oryginalnym widokiem, który otrzymał pierwsze zdarzenie typu "finger down". Tak czy inaczej tutaj jest kod, jeśli chcesz spróbować samemu.

Mam 7z całego projektu, ale nie sądzę, że mogę go dołączyć.

Oto główna czynność i xml dla układu.

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

    } 
} 

Układ:

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

Powodzenia, i jeśli spróbujesz to daj mi znać, jeśli masz jeszcze trzy wskaźniki !! instrukcje drukowania. Zastanawiam się, jakie telefony to obsługują.

Dzięki, dk

+0

Galaxy S obsługuje maksymalnie pięć liczników. Wykazane przez kogoś z innego forum za pomocą powyższego oprogramowania. – dakira

+0

Korzystanie z optymalizatora LG. Wykrywa tylko 1 licznik. – Brahadeesh

0

edytowany @dakira odpowiedź.Oto mój przykładowy kod:

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

tutaj jest kod 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; 
     } 
    } 
} 

nadzieję, że to rozwiąże problem, wiele osób :)

enter image description here

Powiązane problemy