Android:同时按下按钮

时间:2010-12-25 17:02:42

标签: android button touch simultaneous

我已经在其他平台(特别是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。

这就是我使用的东西,希望它可以帮助别人。

2 个答案:

答案 0 :(得分: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()。 (对不起,这个没有示例代码,主要是因为我认为两个不同的按钮方法更好。:))

答案 1 :(得分:0)

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