2

私はゲームに取り組んでいて、少し問題が発生しました。Android のグラフィック面は初めてなので、これを正しく行っていない可能性があります。

を拡張する独自のオブジェクトSurfaceViewArrayListとがあります。オブジェクトのメソッドをオーバーライドしてから、すべてを描画します。描画部分は正常に動作します。CardViewonDrawCardSurfaceView's onDraw

を使用して個々のカードがタッチされたことを検出しようとしましたonTouchListener。各カードにリスナーを設定しましたが、タッチされたビューが であるかのようにタッチを検出しますSurfaceView。私の考え方が間違っている可能性もありますので、アドバイスをお願いします。

いくつかのコード:

public GameSurfaceView(Context context) {
    super(context);
    GAME_STATE = GameState.LOADING;
    this.context = context;
    holder = getHolder();
    holder.addCallback(new SurfaceHolder.Callback() {

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            Canvas c = holder.lockCanvas(null);
            onDraw(c);
            holder.unlockCanvasAndPost(c);
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        }
    });
}

SurfaceView onDraw():

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawRGB(30, 180, 30);
    for (Card card : user.getTableCards()) {
        card.draw(canvas);
    }
}

カードの onDraw():

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawBitmap(getBitmap(), x, y, null);
}

とオンタッチ

@Override
public boolean onTouch(View v, MotionEvent event) {
    Log.d("TOUCH", "Class: " + v.getClass().toString());
    if (v.getClass() == Card.class) {
        Log.d("CARD", "Touched: " + ((Card) v).getValue());
    }
    return true;
}

私は常にSurfaceViewログに記録されているクラスを取得しています。これはそのようなことをする正しい方法ですか?同じクラスの個々のオブジェクトへのタッチを検出する必要があります..

私は現在、タイプのメンバーRectを各カードに追加し、ループしてタッチの x と y がその rect に含まれているかどうかを確認することでこれを行っていますが、各カードを繰り返し処理するのは高価な方法のようです (最大52) そしてそれをチェック..

ありがとう

4

2 に答える 2

5

2 つの異なる概念を混同しています。A) と B) の両方で説明します。

次の 2 つのオプションがあります。

A) SurfaceView を引き続き使用したい場合 (描画方法をより詳細に制御できるため、ゲームには正しい選択かもしれません)、Card オブジェクトは View ではなく Drawable を拡張する必要があります。Drawable は、キャンバスに描画するか、背景などとしてウィジェットに渡すだけのダム クラスです。Android はそれについて詳しく知る必要はありません。この場合、あなたが説明したように、どのカードがヒットしたかを自分で確認する必要があります。Android ではこれを処理できません。Drawable ではなく View でこれを行っていますが、これは間違っています! または少なくとも巨大な無駄。ビューで適切に行う方法については、以下を参照してください。

B) タッチ イベントや他の多くのことを処理するビューを使用します。

View は、Android のビュー階層に存在することになっている複雑なクラスです。あなたがそれを使用している方法では、その機能のほとんどを捨てています-ビューをキャンバスに直接描画すると、アンドロイドはビューをまったく認識しないため、タッチイベントを処理できません。

カードの適切なビューベースの実装は次のようになります: ビューグループをベースとして使用します。この ViewGroup は LinearLayout である可能性があります。または、カードのカードに任意の位置とサイズを設定する機能が必要な場合は、非推奨ですが AbsoluteView を使用できます。

次に、addView() を使用してカードを ViewGroup に追加します。この中でのカード ビューの配置は、addView() に渡す LayoutParams オブジェクトによって管理されます。このようにして、Android はその存在を認識し、次のようなタッチ イベントを処理します。

  • タッチ イベントは最初に ViewGroup に移動します
  • ViewGroup onTouchEvent は、イベントをその子の onTouchEvent (addView() によって追加されたもの) に送信します。したがって、Card クラスでこのメソッドをオーバーライドするだけです。オブジェクト自体で呼び出されるため、どの Card の onTouchEvent が呼び出されたかは本質的にわかります。
  • カードの onTouchEvent では、true を返すことで、タッチ イベントを処理したことを親に知らせます。これを行わない場合は、代わりに親がイベントを処理できます。

完全に明確にするために、ビューをSurfaceViewに追加していませんでした。実際、ViewGroupではないため、できません。これは、その中で任意の描画操作を実行できる単なる複雑な View オブジェクトです。ただし、これは常にビュー階層のリーフであり、独自の onTouchEvents のみを処理できます。それを子に送信することはできません。

于 2013-06-15T10:40:39.503 に答える