1

私はこれを他のプラットフォーム(特にiPhone / iPad)で見ましたが、Androidのit / figure-it-outを見つけることができず、他のプラットフォームは質問をするよりもはるかに遠くないようです。

2人のプレーヤーが同じ画面のボタンを同時に押さなければならないマルチプレーヤーコンポーネントを備えたゲームがあります。ボタンを同時に押す以外はすべて行われます。

現在のところ、AndroidはボタンのonTouchEventを呼び出しているようですが、処理されるため、他のボタンは呼び出されません。両方のボタンを呼び出すようなもの(ボタンの領域内にタッチがある場合)が機能すると思いますか?これを実装できる他の方法はありますか?

御時間ありがとうございます。


Anwser:
アクティビティのonTouchEvent関数に2つの異なるタッチポイントを実装することになりました。

基本的な実装:

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は、メソッドignoreMotionEventが存在するButtonの単なる拡張バージョンです。これは、CustomButtonのonTouchEvent関数が即座にfalseを返すか、super.onTouchEventを呼び出すかを決定するブール値を設定するだけです。

残念ながら、このコードを試しても機能しません。では、なぜそれについて言及するのですか?これがコードの基本的な概要です。私が遭遇した問題は、この機能をAndroid1.6以前には存在させないようにする機能でした。この作業を行うには、エクレア以上が必要です。

同じ問題を抱えていたためにこれを見つけた他の人を助けるために、ここで私が実行しているもののほぼ正確なコピーを示します。

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

2つの異なるボタンがある場合は、それぞれに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
  }
}
}

(上記のコードはテストされていないか、完全ではありません。)

1つのビューで2つの異なるポイントに触れさせる場合は、event.getX(index)とevent.getY(i)を使用してイベントを反復処理できます。event.getPointerCount()を参照してください。(申し訳ありませんが、これのサンプルコードはありません。主に、2つの異なるボタンのアプローチの方が優れていると思います。:))

于 2010-12-25T17:33:29.990 に答える
0

私のMultitouchActivityを試してみて くださいhttp://www.passsy.de/multitouch-for-all-views/

于 2012-08-24T13:09:50.083 に答える