私はこれを他のプラットフォーム(特に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までずっと機能することを意味します。
それが私が使っているものであり、うまくいけば他の人の助けになります。