1

我已经在其他平台(尤其是 iPhone/iPad)上看到了这一点,但无法为 Android 找到它/解决它,而其他平台似乎并没有比提出这个问题更进一步。

我有一个具有多人游戏组件的游戏,其中两个玩家必须同时按下同一屏幕上的按钮。除了同时按下按钮外,一切都完成了。

截至目前,Android 似乎调用了按钮的 onTouchEvent,并且由于它已被处理,因此它不会调用另一个按钮。你认为让它同时调用两个按钮(如果触摸在按钮区域内)会起作用吗?有没有其他方法可以实现?

谢谢你的时间。


Anwser:
我最终在 Activity 的 onTouchEvent 函数中实现了两个不同的接触点。

基本实现:

public class MainClass extends Activity { 
// ...
btn1 = (CustomButton)findViewById(R.id.button_one);
btn2 = (CustomButton)findViewById(R.id.button_one);
btn1.ignoreMotionEvent(true);
btn2.ignoreMotionEvent(true);
// ...

@Override
public boolean onTouchEvent(MotionEvent event)
{
    if(r1 == null)
    {
        //r1 and r2 are Rect that define the absolute region of the button.
        //They are both defined here to ensure that the everything will be layed out (didn't always work so just for extra "sure-ness" did it here)
    }
    CustomButton btn = null;
    MotionEvent mevent = null;
    switch(event.getAction())
    {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_UP:
            int x = (int)event.getX();
            int y = (int)event.getY();
            if(r1.contains(x, y))
            {
                btn = btn1;
            }
            else if(r2.contains(x, y))
            {
                btn = btn2;
            }
            if(btn != null)
            {
                mevent = event;
            }
            break;
    }
    if(btn != null)
    {
        btn.ignoreMotionEvent(false);
        btn.onTouchEvent(mevent);
        btn.ignoreMotionEvent(true);
    }
    return super.onTouchEvent(event);
}
}

CustomButton 只是 Button 的扩展版本,其中存在方法 ignoreMotionEvent,这只是设置一个布尔值,确定 CustomButton 的 onTouchEvent 函数是否应立即返回 false 或调用 super.onTouchEvent。

不幸的是,如果您尝试此代码,它将无法正常工作。那为什么要提呢?它是代码的基本轮廓。我遇到的问题是使这项工作的功能在 Android 1.6 及更早版本上不存在。完成这项工作需要 Eclair 和更高版本。

现在只是为了帮助任何其他发现此问题的人,因为他们遇到了同样的问题,这里几乎是我正在运行的内容的精确副本:

public class MainClass extends Activity { 
// ...
btn1 = (CustomButton)findViewById(R.id.button_one);
btn2 = (CustomButton)findViewById(R.id.button_one);
btn1.ignoreMotionEvent(true);
btn2.ignoreMotionEvent(true);
// ...

@Override
public boolean onTouchEvent(MotionEvent event)
{
    if(r1 == null)
    {
        //r1 and r2 are Rect that define the absolute region of the button.
        //They are both defined here to ensure that the everything will be layed out (didn't always work so just for extra "sure-ness" did it here)
    }
    if(Utils.isEclairOrLater())
    {
        //Eclair and later
        boolean froyo = Utils.isFroyoOrLater();
        int action = froyo ? event.getActionMasked() : event.getAction();
        CustomButton btn = null;
        MotionEvent mevent = null;
        switch(action & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP:
                int x = (int)event.getX();
                int y = (int)event.getY();
                if(r1.contains(x, y))
                {
                    btn = btn1;
                }
                else if(r2.contains(x, y))
                {
                    btn = btn2;
                }
                if(btn != null)
                {
                    mevent = event;
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
            case MotionEvent.ACTION_POINTER_UP:
                int index = froyo ? event.getActionIndex() : ((action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT);
                x = (int)event.getX(index);
                y = (int)event.getY(index);
                if(r1.contains(x, y))
                {
                    btn = btn1;
                }
                else if(r2.contains(x, y))
                {
                    btn = btn2;
                }
                if(btn != null)
                {
                    mevent = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP, event.getX(index), event.getY(index), 0);
                }
                break;
        }
        if(btn != null)
        {
            btn.ignoreMotionEvent(false);
            btn.onTouchEvent(mevent);
            btn.ignoreMotionEvent(true);
        }
    }
    else
    {
        //Earlier then Eclair
        CustomButton btn = null;
        MotionEvent mevent = null;
        switch(event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP:
                int x = (int)event.getX();
                int y = (int)event.getY();
                if(r1.contains(x, y))
                {
                    btn = btn1;
                }
                else if(r2.contains(x, y))
                {
                    btn = btn2;
                }
                if(btn != null)
                {
                    mevent = event;
                }
                break;
        }
        if(btn != null)
        {
            btn.ignoreMotionEvent(false);
            btn.onTouchEvent(mevent);
            btn.ignoreMotionEvent(true);
        }
    }
    return super.onTouchEvent(event);
}
}

Utils 是一个简单的实用程序类,出于本示例的目的,它获取 Build.VERSION.SDK_INT 值并将其与 Eclair (5) 和 Froyo (8) 进行比较以获得适当的功能。

它还要求您使用 2.2 或更高版本进行编译。如果您不知道,Android 是向后兼容的,只要您检查由于版本差异而丢失的功能。这意味着尽管您使用 2.2 进行编译,但它会一直工作到 1.0。

这就是我使用的,希望它可以帮助其他人。

4

2 回答 2

0

如果您有两个不同的按钮,您可以将 onTouchListeners 附加到每个按钮,然后让 onTouch 调用向您的主活动发送一条消息,指示该按钮已被按下。大致:

public class MainClass extends Activity implements Handler.Callback {
handler = new Handler(this);
// ...
((Button) findViewById(R.id.button_one)).setOnTouchListener(new OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    handler.sendEmptyMessage(BUTTON_ONE);
    return true;
  }
});
((Button) findViewById(R.id.button_two)).setOnTouchListener(new OnTouchListener() {
  @Override
  public boolean onTouch(View v, MotionEvent event) {
    handler.sendEmptyMessage(BUTTON_TWO);
    return true;
  }
});

public boolean handleMessage(Message msg) {
  if (msg.what == BUTTON_ONE) {
    mButtonOnePressed = System.nanoTime();
    checkIfBothPressed();
  } else if (msg.what == BUTTON_TWO) {
    mButtonTwoPressed = System.nanoTime();
    checkIfBothPressed();
  }
}

public void checkIfBothPressed() {
  if (Math.abs(mButtonOnePressed - mButtonTwoPressed) < 1000000) {
    // They pressed the buttons within one second
  }
}
}

(以上代码未经测试或完整。)

如果您让它们在单个视图上接触两个不同的点,您可以使用 event.getX(index) 和 event.getY(i) 遍历事件。请参阅 event.getPointerCount()。(对不起,这个没有示例代码,主要是因为我认为两个不同的按钮方法更好。:))

于 2010-12-25T17:33:29.990 回答
0

试试我的 MultitouchActivity http://www.passsy.de/multitouch-for-all-views/

于 2012-08-24T13:09:50.083 回答