Android多点触控?

时间:2011-01-17 03:31:44

标签: android multi-touch ontouchlistener

作为开发人员,我倾向于先编程,然后再进行研究。我试图实现一个可以处理多个用户输入的屏幕。基本上不只是一个手指映射。我尝试了两件事......

我有一个实现OnTouchListener的Activity类。在这里,我有两个独立的子视图,将Activity添加为ontouch侦听器。然后我有一个打印出来的event.getPointerCount()并打印出每个指针的位置。

将其下载到手机并进行测试。我注意到指针从未超过两个。我甚至注意到,如果一个手指放在一个孩子身上,另一个手指放在另一个孩子身上,那么事件只会发生在第一个子组件上。接下来,我尝试在每个子组件上放置单独的侦听器,看看它是否有效,但它的行为是相同的。

因此,在处理触摸屏幕的用户输入时,似乎android只支持两个用户输入。

这是真的吗?从测试和研究来看,似乎就是这种情况。

是否有人遇到此限制。任何聪明的工作?

感谢您的时间和回复。

DK

3 个答案:

答案 0 :(得分:7)

支持的触摸点数取决于设备。在所有当前可用的Android MotionEvent版本中,都会发送到单个目标视图,并描述所有当前活动的触摸点的状态。目标视图由第一个MotionEvent.ACTION_DOWN事件发生的位置决定。

请参阅Android开发者博客上的帖子Making Sense of Multitouch,以快速了解如何在Android上使用多点触控事件。

答案 1 :(得分:3)

我写了一个非常简单的应用程序来测试我的HTC Incredible手机的多点触控。我表现得非常像我想的那样,非常像adamp给出的URL。我的结果是手机只能处理两个手指输入。我有盒子,每个都有自己的OnTouchListener。当我点击每个框时,我会为每个框打印一个文本。点击每个获取触摸事件,但用我的食指我点击屏幕上的任何地方我有两个指针。来自MotionEvent event.getPointerCount方法。没关系,第二根手指落在哪里。可能已经接收到第一个手指向下事件的原始视图之外。无论如何,这里是代码,如果你想自己尝试。

我有整个项目的7z,但我认为我不能附上它。

因此,这是布局的主要活动和xml。

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

    }
}

布局:

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

祝你好运,如果你尝试了,请告诉我你是否得到了GOT三个指针!打印报表。我想知道手机支持它。

感谢, DK

答案 2 :(得分:0)

我编辑了@dakira的答案。这是我的示例代码:

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

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

希望这能解决很多人的问题:)

enter image description here