如何在android中正确处理触摸事件?

| 项目范围 当用户用两根手指触摸Android屏幕时,请在每个触摸位置绘制一个“框架”,并为每个框架绘制一个“光标”。每帧都是一个自定义滑块,光标将上下移动。一路向上将是100%,中线将是0%,一路向下将是-100%。这将用于控制小型马达,类似于油箱转向,每次触摸都会控制一个单独的马达(通过蓝牙发送信号)。两次触摸并绘制完所有内容后,我希望能够提起任一根手指,但将光标保持在其最后的位置,而另一根手指则可以自由移动其光标。抬起最后一根手指时,所有内容都会“隐藏”并重置为0%。 想要的功能 在两指触摸下,在触摸位置下方绘制单独的.png 绘制框架和光标之后,请跟踪它们相对于框架的位置,以确定百分比。 如果将一根手指提起,则使该手指的光标停留在最后一个已知的位置,但是另一只手指可以移动它的光标。同样,如果将手指放回原处,它应该能够再次移动其光标。 如果将两只手指抬离屏幕,请隐藏所有内容并将百分比重置为0% 获得功能 我可以在多点触控上绘制框架和光标 职位和百分比工作正常 光标确实移动正确 什么不起作用 我不确定是否应该有一个处理两个触摸事件的自定义类,或者我是否应该有两个自定义类的实例分别处理它们自己的触摸事件(我已经尝试过这两个,这是我获得任何“真实”功能的唯一方法)与1个自定义类一起处理两个触摸事件,而另一种方法则无法正常工作) 当我只有1个自定义类时,它很好用,但是如果两只手指都不在屏幕上,我就会把它“隐藏”起来,有时android注册我已经将手指从屏幕上抬了下来,这使我很忙隐藏框架然后重新出现在其他位置时的问题 当我使用2个自定义类时,我触摸每个自定义类都会有自己的touch事件,并且如果我在屏幕之间平均划分类,则不必担心多点触摸。事实并非如此,仍然需要处理多点触控 有人可以向我解释android如何处理其触摸事件。从我所做的事情来看,如果我放下手指1,手指2,则似乎第一根手指将记录\“ ACTION_DOWN \”,而第二根手指将记录\\“ ACTION_POINTER_2_DOWN \”,但是如果我以第一根手指为生,我的第二根手指是\“ demoted \”,现在我的第二根手指记录的所有事件都与\“ ACTION_POINTER_2 \”不相关,而将是\“ ACTION_DOWN,ACTION_UP等”。它是否正确? TouchUI.java
    package com.robota.android;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.widget.ImageView;

public class TouchUI extends ImageView {

public static final String LEFT_TOUCHUI = \"com.robota.android:id/leftTouchUI\";
public static final String RIGHT_TOUCHUI = \"com.robota.android:id/rightTouchUI\";
private String whoAmI = new String();
private MyPoints framePts = new MyPoints();
private MyPoints cursorPts = new MyPoints();
private Bitmap frame;
private Bitmap cursor;
private int frameWidth;
private int frameHeight;
private int cursorHeight;
private boolean pointerDown = false;
private int dy;

public TouchUI(final Context context, final AttributeSet as){
    super(context, as);
    Log.d(\"TouchUI\", getResources().getResourceName(this.getId()));
    whoAmI = new String(getResources().getResourceName(this.getId()));
    if(whoAmI.equals(LEFT_TOUCHUI)){
        frame = BitmapFactory.decodeResource(getResources(), R.drawable.tank_left);
    }else if(whoAmI.equals(RIGHT_TOUCHUI)){
        frame = BitmapFactory.decodeResource(getResources(), R.drawable.tank_right);
    }
    cursor = BitmapFactory.decodeResource(getResources(), R.drawable.cursor);
    frameWidth = frame.getWidth();
    frameHeight = frame.getHeight();
    cursorHeight = cursor.getHeight();
}

public void determinePointers(int x, int y){
        framePts.setOrigin(x-frameWidth/2, y-frameHeight/2);
        cursorPts.setOrigin(x-frameWidth/2, y-frameHeight/2);
}

@Override
public boolean onTouchEvent(MotionEvent e){
    int x = 0;
    int y = 0;
    Log.d(\"TouchUI\", \">>>>> \" + whoAmI);
    if(e.getAction() == MotionEvent.ACTION_DOWN){
        determinePointers(x,y);
        pointerDown = true;
    }else if(e.getAction() == MotionEvent.ACTION_UP){
        pointerDown = false;
    }else if(e.getAction() == MotionEvent.ACTION_MOVE){
        dy = (int)e.getY()-framePts.getY();
        if(dy <= 0){
            dy=0;
        }else if(dy+cursorHeight/2 >= frameHeight){
            dy=frameHeight;
        }
        sendMotorSpeed(dy);
    }
    return true;
}

public void sendMotorSpeed(int dy){
    float motor = dy;
    motor-=frameHeight;
    motor*=-1;

    motor = (motor/frameHeight)*255;

    PacketController.updateMotorSpeeds(whoAmI, (int)motor);
}

public void onDraw(Canvas canvas){
    if(pointerDown){//twoDown){
        canvas.drawBitmap(frame, framePts.getX(), framePts.getY(), null);
        canvas.drawBitmap(cursor, cursorPts.getX(), (cursorPts.getY()+dy), null);
    }
    invalidate();
}

private class MyPoints{

    private int x = -100;
    private int y = -100;
    private int deltaY = 0;;

    public MyPoints(){
        this.x = 0;
        this.y = 0;
    }

    public int getX(){
        return this.x;
    }

    public int getY(){
        return this.y;
    }

    public void setOrigin(int x, int y){
        this.x = x;
        this.y = y;
    }

    public int getDeltaY(){
        return deltaY;
    }

    public void setDeltaY(int newY){
        deltaY = (newY-y);
        Log.d(\"TouchUI\", \"DY: \" + deltaY);
    }
}
}
Main.xml
    <?xml version=\"1.0\" encoding=\"utf-8\"?>
    <RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"
android:id=\"@+id/parentLayout\"
android:layout_width=\"fill_parent\"
android:layout_height=\"fill_parent\"
android:orientation=\"vertical\">
<LinearLayout android:orientation=\"horizontal\"
              android:layout_width=\"match_parent\"
              android:layout_height=\"match_parent\">
    <com.robota.android.TouchUI xmlns:android=\"http://schemas.android.com/apk/res/android\"
        android:id=\"@+id/leftTouchUI\"
        android:background=\"#0000\"
        android:layout_height=\"match_parent\"
        android:layout_width=\"wrap_content\"
        android:layout_weight=\"1\">
    </com.robota.android.TouchUI>
    <com.robota.android.TouchUI xmlns:android=\"http://schemas.android.com/apk/res/android\"
        android:id=\"@+id/rightTouchUI\"
        android:background=\"#0000\"
        android:layout_height=\"match_parent\"
        android:layout_width=\"wrap_content\"
        android:layout_weight=\"1\">
    </com.robota.android.TouchUI>
</LinearLayout>
RobotController.java(主要活动类)
    package com.robota.android;

    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.content.ActivityNotFoundException;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.Window;
    import android.widget.ScrollView;
    import android.widget.TextView;
    import android.widget.Toast;

public class RobotController extends Activity {
// Tag used to keep track of class in the Log
private static final String TAG = \"robotController_new\";
// Boolean to debugging
private static final boolean D = true;

// Intent request codes
private static final int DISCONNECT_DEVICE = 1;
private static final int CONNECT_DEVICE = 2;
private static final int REQUEST_ENABLE_BT = 3;

// Handler Codes
public static final int MESSAGE_READ = 1;
public static final int MESSAGE_WRITE = 2;

// Local Bluetooth Adapter
private BluetoothAdapter bluetoothAdapter = null;
// Bluetooth Discovery and Datahandler
private BluetoothComm btComm = null;

// Debug\'s TextView, this is where strings will be written to display
private TextView tv;
private ScrollView sv;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    if(D) Log.d(TAG, \"++ON CREATE++\");
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);

    bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    if(bluetoothAdapter == null){
        if(D) Log.d(TAG, \"NO BLUETOOTH DEVICE\");
        Toast.makeText(this, \"Bluetooth is not available\", Toast.LENGTH_SHORT).show();
        finish();
        return;
    }

    PacketController.controller = this;
}


public void onStart(){
    super.onStart();
    if(D) Log.d(TAG, \"++ON START++\");

    if(!bluetoothAdapter.isEnabled()){
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
    }else{
        // Start BluetoothComm
        if(btComm == null){
            setupComm();
        }
    }
}

/**
 * Creates new Bluetooth Communication
 */
private void setupComm(){
    if(D) Log.d(TAG, \"+++setupComm+++\");
    btComm = new BluetoothComm(this, handler);
}

private void connectDevice(Intent data){
    if(D) Log.d(TAG, \"+++connectDevice+++\");
    String addr = data.getExtras()
        .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
    BluetoothDevice device = bluetoothAdapter.getRemoteDevice(addr);
    if(D) Log.d(TAG,\"REMOTE ADDR: \"+ addr);
    btComm.connect(device);
}

private void disconnectDevice(){
    if(D) Log.d(TAG, \"---disconnectDevice---\");
    if(btComm.getState() == btComm.STATE_CONNECTED){
        btComm.disconnect();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    //super.onCreateOptionsMenu(menu);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Intent serverIntent = null;
    switch(item.getItemId()){       
    case R.id.insecure_connect_scan:
        // Launch the DeviceListActivity to see devices and do scan
        serverIntent = new Intent(this, DeviceListActivity.class);
        try{
            startActivityForResult(serverIntent, CONNECT_DEVICE);
        }catch(ActivityNotFoundException activityNotFound){
            Log.e(TAG, \"Could not start DeviceListActivity(Insecure)\");
        }
        return true;
    }
    return false;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
    switch(requestCode){
    case CONNECT_DEVICE:
        if(resultCode == Activity.RESULT_OK){
            connectDevice(data);
        }
        break;
    case DISCONNECT_DEVICE:
        if(resultCode == Activity.RESULT_OK){
            disconnectDevice();
        }
        break;
    }
}

public Handler getHandler(){
    return this.handler;
}

public BluetoothComm getBtComm(){
    return this.btComm;
}

// The Handler that gets information back from the BluetoothChatService
private final Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if(D) Log.d(TAG, \"check message\");
        switch (msg.what) {
        case MESSAGE_READ:
            if(D) Log.d(TAG, \"trying to read message\");
            byte[] readBuf = (byte[]) msg.obj;
            // construct a string from the valid bytes in the buffer
            String readMessage = new String(readBuf, 0, msg.arg1);
            if(D) Log.d(TAG, \"bytes: \" + readBuf + \" arg1: \" + msg.arg1 + \" Message: \" + readMessage);
            tv.append(readMessage);
            break;
        case MESSAGE_WRITE:
            if(D) Log.d(TAG, \"trying to send message\");
            String sendMessage = new String(String.valueOf(msg.obj));
        }
    }
};
}
我不认为没有其他没有列出的课程是必需的,但是如果需要,请告诉我。 任何帮助深表感谢     
已邀请:
        您将需要保存每个点的指标ID,并将其与每个MotionEvent提供的新ID相比较。解释起来有些棘手,所以我将向您指出这篇亚行帖子,它比我能解释的要好得多。长话短说?多点触控可能有些棘手,但并不像乍一看那样糟糕。     

要回复问题请先登录注册